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 #if 0 /* JERRY -- disabled; not used for now */
2755 /*******************************************************************
2756 * fill a notify_info_data with the servername
2757 ********************************************************************/
2759 void spoolss_notify_server_name(int snum,
2760 SPOOL_NOTIFY_INFO_DATA *data,
2761 print_queue_struct *queue,
2762 NT_PRINTER_INFO_LEVEL *printer,
2763 TALLOC_CTX *mem_ctx)
2765 pstring temp_name, temp;
2768 fstrcpy( temp_name, "\\\\%L" );
2769 standard_sub_basic( NULL, temp_name, sizeof(temp_name)-1 );
2772 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2774 data->notify_data.data.length = len;
2775 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2777 if (!data->notify_data.data.string) {
2778 data->notify_data.data.length = 0;
2782 memcpy(data->notify_data.data.string, temp, len);
2788 /*******************************************************************
2789 * fill a notify_info_data with the printername (not including the servername).
2790 ********************************************************************/
2792 void spoolss_notify_printer_name(int snum,
2793 SPOOL_NOTIFY_INFO_DATA *data,
2794 print_queue_struct *queue,
2795 NT_PRINTER_INFO_LEVEL *printer,
2796 TALLOC_CTX *mem_ctx)
2801 /* the notify name should not contain the \\server\ part */
2802 char *p = strrchr(printer->info_2->printername, '\\');
2805 p = printer->info_2->printername;
2810 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2812 data->notify_data.data.length = len;
2813 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2815 if (!data->notify_data.data.string) {
2816 data->notify_data.data.length = 0;
2820 memcpy(data->notify_data.data.string, temp, len);
2823 /*******************************************************************
2824 * fill a notify_info_data with the servicename
2825 ********************************************************************/
2827 void spoolss_notify_share_name(int snum,
2828 SPOOL_NOTIFY_INFO_DATA *data,
2829 print_queue_struct *queue,
2830 NT_PRINTER_INFO_LEVEL *printer,
2831 TALLOC_CTX *mem_ctx)
2836 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2838 data->notify_data.data.length = len;
2839 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2841 if (!data->notify_data.data.string) {
2842 data->notify_data.data.length = 0;
2846 memcpy(data->notify_data.data.string, temp, len);
2849 /*******************************************************************
2850 * fill a notify_info_data with the port name
2851 ********************************************************************/
2853 void spoolss_notify_port_name(int snum,
2854 SPOOL_NOTIFY_INFO_DATA *data,
2855 print_queue_struct *queue,
2856 NT_PRINTER_INFO_LEVEL *printer,
2857 TALLOC_CTX *mem_ctx)
2862 /* even if it's strange, that's consistant in all the code */
2864 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2866 data->notify_data.data.length = len;
2867 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2869 if (!data->notify_data.data.string) {
2870 data->notify_data.data.length = 0;
2874 memcpy(data->notify_data.data.string, temp, len);
2877 /*******************************************************************
2878 * fill a notify_info_data with the printername
2879 * but it doesn't exist, have to see what to do
2880 ********************************************************************/
2882 void spoolss_notify_driver_name(int snum,
2883 SPOOL_NOTIFY_INFO_DATA *data,
2884 print_queue_struct *queue,
2885 NT_PRINTER_INFO_LEVEL *printer,
2886 TALLOC_CTX *mem_ctx)
2891 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2893 data->notify_data.data.length = len;
2894 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2896 if (!data->notify_data.data.string) {
2897 data->notify_data.data.length = 0;
2901 memcpy(data->notify_data.data.string, temp, len);
2904 /*******************************************************************
2905 * fill a notify_info_data with the comment
2906 ********************************************************************/
2908 void spoolss_notify_comment(int snum,
2909 SPOOL_NOTIFY_INFO_DATA *data,
2910 print_queue_struct *queue,
2911 NT_PRINTER_INFO_LEVEL *printer,
2912 TALLOC_CTX *mem_ctx)
2917 if (*printer->info_2->comment == '\0')
2918 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2920 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2922 data->notify_data.data.length = len;
2923 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2925 if (!data->notify_data.data.string) {
2926 data->notify_data.data.length = 0;
2930 memcpy(data->notify_data.data.string, temp, len);
2933 /*******************************************************************
2934 * fill a notify_info_data with the comment
2935 * location = "Room 1, floor 2, building 3"
2936 ********************************************************************/
2938 void spoolss_notify_location(int snum,
2939 SPOOL_NOTIFY_INFO_DATA *data,
2940 print_queue_struct *queue,
2941 NT_PRINTER_INFO_LEVEL *printer,
2942 TALLOC_CTX *mem_ctx)
2947 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2949 data->notify_data.data.length = len;
2950 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2952 if (!data->notify_data.data.string) {
2953 data->notify_data.data.length = 0;
2957 memcpy(data->notify_data.data.string, temp, len);
2960 /*******************************************************************
2961 * fill a notify_info_data with the device mode
2962 * jfm:xxxx don't to it for know but that's a real problem !!!
2963 ********************************************************************/
2965 static void spoolss_notify_devmode(int snum,
2966 SPOOL_NOTIFY_INFO_DATA *data,
2967 print_queue_struct *queue,
2968 NT_PRINTER_INFO_LEVEL *printer,
2969 TALLOC_CTX *mem_ctx)
2973 /*******************************************************************
2974 * fill a notify_info_data with the separator file name
2975 ********************************************************************/
2977 void spoolss_notify_sepfile(int snum,
2978 SPOOL_NOTIFY_INFO_DATA *data,
2979 print_queue_struct *queue,
2980 NT_PRINTER_INFO_LEVEL *printer,
2981 TALLOC_CTX *mem_ctx)
2986 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2988 data->notify_data.data.length = len;
2989 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2991 if (!data->notify_data.data.string) {
2992 data->notify_data.data.length = 0;
2996 memcpy(data->notify_data.data.string, temp, len);
2999 /*******************************************************************
3000 * fill a notify_info_data with the print processor
3001 * jfm:xxxx return always winprint to indicate we don't do anything to it
3002 ********************************************************************/
3004 void spoolss_notify_print_processor(int snum,
3005 SPOOL_NOTIFY_INFO_DATA *data,
3006 print_queue_struct *queue,
3007 NT_PRINTER_INFO_LEVEL *printer,
3008 TALLOC_CTX *mem_ctx)
3013 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3015 data->notify_data.data.length = len;
3016 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3018 if (!data->notify_data.data.string) {
3019 data->notify_data.data.length = 0;
3023 memcpy(data->notify_data.data.string, temp, len);
3026 /*******************************************************************
3027 * fill a notify_info_data with the print processor options
3028 * jfm:xxxx send an empty string
3029 ********************************************************************/
3031 void spoolss_notify_parameters(int snum,
3032 SPOOL_NOTIFY_INFO_DATA *data,
3033 print_queue_struct *queue,
3034 NT_PRINTER_INFO_LEVEL *printer,
3035 TALLOC_CTX *mem_ctx)
3040 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3042 data->notify_data.data.length = len;
3043 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3045 if (!data->notify_data.data.string) {
3046 data->notify_data.data.length = 0;
3050 memcpy(data->notify_data.data.string, temp, len);
3053 /*******************************************************************
3054 * fill a notify_info_data with the data type
3055 * jfm:xxxx always send RAW as data type
3056 ********************************************************************/
3058 void spoolss_notify_datatype(int snum,
3059 SPOOL_NOTIFY_INFO_DATA *data,
3060 print_queue_struct *queue,
3061 NT_PRINTER_INFO_LEVEL *printer,
3062 TALLOC_CTX *mem_ctx)
3067 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3069 data->notify_data.data.length = len;
3070 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3072 if (!data->notify_data.data.string) {
3073 data->notify_data.data.length = 0;
3077 memcpy(data->notify_data.data.string, temp, len);
3080 /*******************************************************************
3081 * fill a notify_info_data with the security descriptor
3082 * jfm:xxxx send an null pointer to say no security desc
3083 * have to implement security before !
3084 ********************************************************************/
3086 static void spoolss_notify_security_desc(int snum,
3087 SPOOL_NOTIFY_INFO_DATA *data,
3088 print_queue_struct *queue,
3089 NT_PRINTER_INFO_LEVEL *printer,
3090 TALLOC_CTX *mem_ctx)
3092 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3093 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3096 /*******************************************************************
3097 * fill a notify_info_data with the attributes
3098 * jfm:xxxx a samba printer is always shared
3099 ********************************************************************/
3101 void spoolss_notify_attributes(int snum,
3102 SPOOL_NOTIFY_INFO_DATA *data,
3103 print_queue_struct *queue,
3104 NT_PRINTER_INFO_LEVEL *printer,
3105 TALLOC_CTX *mem_ctx)
3107 data->notify_data.value[0] = printer->info_2->attributes;
3108 data->notify_data.value[1] = 0;
3111 /*******************************************************************
3112 * fill a notify_info_data with the priority
3113 ********************************************************************/
3115 static void spoolss_notify_priority(int snum,
3116 SPOOL_NOTIFY_INFO_DATA *data,
3117 print_queue_struct *queue,
3118 NT_PRINTER_INFO_LEVEL *printer,
3119 TALLOC_CTX *mem_ctx)
3121 data->notify_data.value[0] = printer->info_2->priority;
3122 data->notify_data.value[1] = 0;
3125 /*******************************************************************
3126 * fill a notify_info_data with the default priority
3127 ********************************************************************/
3129 static void spoolss_notify_default_priority(int snum,
3130 SPOOL_NOTIFY_INFO_DATA *data,
3131 print_queue_struct *queue,
3132 NT_PRINTER_INFO_LEVEL *printer,
3133 TALLOC_CTX *mem_ctx)
3135 data->notify_data.value[0] = printer->info_2->default_priority;
3136 data->notify_data.value[1] = 0;
3139 /*******************************************************************
3140 * fill a notify_info_data with the start time
3141 ********************************************************************/
3143 static void spoolss_notify_start_time(int snum,
3144 SPOOL_NOTIFY_INFO_DATA *data,
3145 print_queue_struct *queue,
3146 NT_PRINTER_INFO_LEVEL *printer,
3147 TALLOC_CTX *mem_ctx)
3149 data->notify_data.value[0] = printer->info_2->starttime;
3150 data->notify_data.value[1] = 0;
3153 /*******************************************************************
3154 * fill a notify_info_data with the until time
3155 ********************************************************************/
3157 static void spoolss_notify_until_time(int snum,
3158 SPOOL_NOTIFY_INFO_DATA *data,
3159 print_queue_struct *queue,
3160 NT_PRINTER_INFO_LEVEL *printer,
3161 TALLOC_CTX *mem_ctx)
3163 data->notify_data.value[0] = printer->info_2->untiltime;
3164 data->notify_data.value[1] = 0;
3167 /*******************************************************************
3168 * fill a notify_info_data with the status
3169 ********************************************************************/
3171 static void spoolss_notify_status(int snum,
3172 SPOOL_NOTIFY_INFO_DATA *data,
3173 print_queue_struct *queue,
3174 NT_PRINTER_INFO_LEVEL *printer,
3175 TALLOC_CTX *mem_ctx)
3177 print_status_struct status;
3179 print_queue_length(snum, &status);
3180 data->notify_data.value[0]=(uint32) status.status;
3181 data->notify_data.value[1] = 0;
3184 /*******************************************************************
3185 * fill a notify_info_data with the number of jobs queued
3186 ********************************************************************/
3188 void spoolss_notify_cjobs(int snum,
3189 SPOOL_NOTIFY_INFO_DATA *data,
3190 print_queue_struct *queue,
3191 NT_PRINTER_INFO_LEVEL *printer,
3192 TALLOC_CTX *mem_ctx)
3194 data->notify_data.value[0] = print_queue_length(snum, NULL);
3195 data->notify_data.value[1] = 0;
3198 /*******************************************************************
3199 * fill a notify_info_data with the average ppm
3200 ********************************************************************/
3202 static void spoolss_notify_average_ppm(int snum,
3203 SPOOL_NOTIFY_INFO_DATA *data,
3204 print_queue_struct *queue,
3205 NT_PRINTER_INFO_LEVEL *printer,
3206 TALLOC_CTX *mem_ctx)
3208 /* always respond 8 pages per minutes */
3209 /* a little hard ! */
3210 data->notify_data.value[0] = printer->info_2->averageppm;
3211 data->notify_data.value[1] = 0;
3214 /*******************************************************************
3215 * fill a notify_info_data with username
3216 ********************************************************************/
3218 static void spoolss_notify_username(int snum,
3219 SPOOL_NOTIFY_INFO_DATA *data,
3220 print_queue_struct *queue,
3221 NT_PRINTER_INFO_LEVEL *printer,
3222 TALLOC_CTX *mem_ctx)
3227 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3229 data->notify_data.data.length = len;
3230 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3232 if (!data->notify_data.data.string) {
3233 data->notify_data.data.length = 0;
3237 memcpy(data->notify_data.data.string, temp, len);
3240 /*******************************************************************
3241 * fill a notify_info_data with job status
3242 ********************************************************************/
3244 static void spoolss_notify_job_status(int snum,
3245 SPOOL_NOTIFY_INFO_DATA *data,
3246 print_queue_struct *queue,
3247 NT_PRINTER_INFO_LEVEL *printer,
3248 TALLOC_CTX *mem_ctx)
3250 data->notify_data.value[0]=nt_printj_status(queue->status);
3251 data->notify_data.value[1] = 0;
3254 /*******************************************************************
3255 * fill a notify_info_data with job name
3256 ********************************************************************/
3258 static void spoolss_notify_job_name(int snum,
3259 SPOOL_NOTIFY_INFO_DATA *data,
3260 print_queue_struct *queue,
3261 NT_PRINTER_INFO_LEVEL *printer,
3262 TALLOC_CTX *mem_ctx)
3267 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3269 data->notify_data.data.length = len;
3270 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3272 if (!data->notify_data.data.string) {
3273 data->notify_data.data.length = 0;
3277 memcpy(data->notify_data.data.string, temp, len);
3280 /*******************************************************************
3281 * fill a notify_info_data with job status
3282 ********************************************************************/
3284 static void spoolss_notify_job_status_string(int snum,
3285 SPOOL_NOTIFY_INFO_DATA *data,
3286 print_queue_struct *queue,
3287 NT_PRINTER_INFO_LEVEL *printer,
3288 TALLOC_CTX *mem_ctx)
3291 * Now we're returning job status codes we just return a "" here. JRA.
3298 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3301 switch (queue->status) {
3306 p = ""; /* NT provides the paused string */
3315 #endif /* NO LONGER NEEDED. */
3317 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3319 data->notify_data.data.length = len;
3320 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3322 if (!data->notify_data.data.string) {
3323 data->notify_data.data.length = 0;
3327 memcpy(data->notify_data.data.string, temp, len);
3330 /*******************************************************************
3331 * fill a notify_info_data with job time
3332 ********************************************************************/
3334 static void spoolss_notify_job_time(int snum,
3335 SPOOL_NOTIFY_INFO_DATA *data,
3336 print_queue_struct *queue,
3337 NT_PRINTER_INFO_LEVEL *printer,
3338 TALLOC_CTX *mem_ctx)
3340 data->notify_data.value[0]=0x0;
3341 data->notify_data.value[1]=0;
3344 /*******************************************************************
3345 * fill a notify_info_data with job size
3346 ********************************************************************/
3348 static void spoolss_notify_job_size(int snum,
3349 SPOOL_NOTIFY_INFO_DATA *data,
3350 print_queue_struct *queue,
3351 NT_PRINTER_INFO_LEVEL *printer,
3352 TALLOC_CTX *mem_ctx)
3354 data->notify_data.value[0]=queue->size;
3355 data->notify_data.value[1]=0;
3358 /*******************************************************************
3359 * fill a notify_info_data with page info
3360 ********************************************************************/
3361 static void spoolss_notify_total_pages(int snum,
3362 SPOOL_NOTIFY_INFO_DATA *data,
3363 print_queue_struct *queue,
3364 NT_PRINTER_INFO_LEVEL *printer,
3365 TALLOC_CTX *mem_ctx)
3367 data->notify_data.value[0]=queue->page_count;
3368 data->notify_data.value[1]=0;
3371 /*******************************************************************
3372 * fill a notify_info_data with pages printed info.
3373 ********************************************************************/
3374 static void spoolss_notify_pages_printed(int snum,
3375 SPOOL_NOTIFY_INFO_DATA *data,
3376 print_queue_struct *queue,
3377 NT_PRINTER_INFO_LEVEL *printer,
3378 TALLOC_CTX *mem_ctx)
3380 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3381 data->notify_data.value[1]=0;
3384 /*******************************************************************
3385 Fill a notify_info_data with job position.
3386 ********************************************************************/
3388 static void spoolss_notify_job_position(int snum,
3389 SPOOL_NOTIFY_INFO_DATA *data,
3390 print_queue_struct *queue,
3391 NT_PRINTER_INFO_LEVEL *printer,
3392 TALLOC_CTX *mem_ctx)
3394 data->notify_data.value[0]=queue->job;
3395 data->notify_data.value[1]=0;
3398 /*******************************************************************
3399 Fill a notify_info_data with submitted time.
3400 ********************************************************************/
3402 static void spoolss_notify_submitted_time(int snum,
3403 SPOOL_NOTIFY_INFO_DATA *data,
3404 print_queue_struct *queue,
3405 NT_PRINTER_INFO_LEVEL *printer,
3406 TALLOC_CTX *mem_ctx)
3413 t=gmtime(&queue->time);
3415 len = sizeof(SYSTEMTIME);
3417 data->notify_data.data.length = len;
3418 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3420 if (!data->notify_data.data.string) {
3421 data->notify_data.data.length = 0;
3425 make_systemtime(&st, t);
3428 * Systemtime must be linearized as a set of UINT16's.
3429 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3432 p = (char *)data->notify_data.data.string;
3433 SSVAL(p, 0, st.year);
3434 SSVAL(p, 2, st.month);
3435 SSVAL(p, 4, st.dayofweek);
3436 SSVAL(p, 6, st.day);
3437 SSVAL(p, 8, st.hour);
3438 SSVAL(p, 10, st.minute);
3439 SSVAL(p, 12, st.second);
3440 SSVAL(p, 14, st.milliseconds);
3443 struct s_notify_info_data_table
3449 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3450 print_queue_struct *queue,
3451 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3454 /* A table describing the various print notification constants and
3455 whether the notification data is a pointer to a variable sized
3456 buffer, a one value uint32 or a two value uint32. */
3458 static const struct s_notify_info_data_table notify_info_data_table[] =
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, NULL},
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, NULL},
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3511 /*******************************************************************
3512 Return the size of info_data structure.
3513 ********************************************************************/
3515 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3519 for (i = 0; i < sizeof(notify_info_data_table); i++)
3521 if ( (notify_info_data_table[i].type == type)
3522 && (notify_info_data_table[i].field == field) )
3524 switch(notify_info_data_table[i].size)
3526 case NOTIFY_ONE_VALUE:
3527 case NOTIFY_TWO_VALUE:
3532 /* The only pointer notify data I have seen on
3533 the wire is the submitted time and this has
3534 the notify size set to 4. -tpot */
3536 case NOTIFY_POINTER:
3539 case NOTIFY_SECDESC:
3545 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3550 /*******************************************************************
3551 Return the type of notify_info_data.
3552 ********************************************************************/
3554 static int type_of_notify_info_data(uint16 type, uint16 field)
3558 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3559 if (notify_info_data_table[i].type == type &&
3560 notify_info_data_table[i].field == field)
3561 return notify_info_data_table[i].size;
3567 /****************************************************************************
3568 ****************************************************************************/
3570 static int search_notify(uint16 type, uint16 field, int *value)
3574 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3575 if (notify_info_data_table[i].type == type &&
3576 notify_info_data_table[i].field == field &&
3577 notify_info_data_table[i].fn != NULL) {
3586 /****************************************************************************
3587 ****************************************************************************/
3589 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3591 info_data->type = type;
3592 info_data->field = field;
3593 info_data->reserved = 0;
3595 info_data->size = size_of_notify_info_data(type, field);
3596 info_data->enc_type = type_of_notify_info_data(type, field);
3603 /*******************************************************************
3605 * fill a notify_info struct with info asked
3607 ********************************************************************/
3609 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3610 snum, SPOOL_NOTIFY_OPTION_TYPE
3611 *option_type, uint32 id,
3612 TALLOC_CTX *mem_ctx)
3618 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3619 NT_PRINTER_INFO_LEVEL *printer = NULL;
3620 print_queue_struct *queue=NULL;
3622 type=option_type->type;
3624 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3625 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3626 option_type->count, lp_servicename(snum)));
3628 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3631 for(field_num=0; field_num<option_type->count; field_num++) {
3632 field = option_type->fields[field_num];
3634 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3636 if (!search_notify(type, field, &j) )
3639 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3640 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3645 current_data = &info->data[info->count];
3647 construct_info_data(current_data, type, field, id);
3649 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3650 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3652 notify_info_data_table[j].fn(snum, current_data, queue,
3658 free_a_printer(&printer, 2);
3662 /*******************************************************************
3664 * fill a notify_info struct with info asked
3666 ********************************************************************/
3668 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3669 SPOOL_NOTIFY_INFO *info,
3670 NT_PRINTER_INFO_LEVEL *printer,
3671 int snum, SPOOL_NOTIFY_OPTION_TYPE
3672 *option_type, uint32 id,
3673 TALLOC_CTX *mem_ctx)
3679 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3681 DEBUG(4,("construct_notify_jobs_info\n"));
3683 type = option_type->type;
3685 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3686 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3687 option_type->count));
3689 for(field_num=0; field_num<option_type->count; field_num++) {
3690 field = option_type->fields[field_num];
3692 if (!search_notify(type, field, &j) )
3695 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3696 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3699 else info->data = tid;
3701 current_data=&(info->data[info->count]);
3703 construct_info_data(current_data, type, field, id);
3704 notify_info_data_table[j].fn(snum, current_data, queue,
3713 * JFM: The enumeration is not that simple, it's even non obvious.
3715 * let's take an example: I want to monitor the PRINTER SERVER for
3716 * the printer's name and the number of jobs currently queued.
3717 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3718 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3720 * I have 3 printers on the back of my server.
3722 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3725 * 1 printer 1 name 1
3726 * 2 printer 1 cjob 1
3727 * 3 printer 2 name 2
3728 * 4 printer 2 cjob 2
3729 * 5 printer 3 name 3
3730 * 6 printer 3 name 3
3732 * that's the print server case, the printer case is even worse.
3735 /*******************************************************************
3737 * enumerate all printers on the printserver
3738 * fill a notify_info struct with info asked
3740 ********************************************************************/
3742 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3743 SPOOL_NOTIFY_INFO *info,
3744 TALLOC_CTX *mem_ctx)
3747 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3748 int n_services=lp_numservices();
3750 SPOOL_NOTIFY_OPTION *option;
3751 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3753 DEBUG(4,("printserver_notify_info\n"));
3758 option=Printer->notify.option;
3763 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3764 sending a ffpcn() request first */
3769 for (i=0; i<option->count; i++) {
3770 option_type=&(option->ctr.type[i]);
3772 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3775 for (snum=0; snum<n_services; snum++)
3777 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3778 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3784 * Debugging information, don't delete.
3787 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3788 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3789 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3791 for (i=0; i<info->count; i++) {
3792 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3793 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3794 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3801 /*******************************************************************
3803 * fill a notify_info struct with info asked
3805 ********************************************************************/
3807 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3808 TALLOC_CTX *mem_ctx)
3811 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3814 SPOOL_NOTIFY_OPTION *option;
3815 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3817 print_queue_struct *queue=NULL;
3818 print_status_struct status;
3820 DEBUG(4,("printer_notify_info\n"));
3825 option=Printer->notify.option;
3831 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3832 sending a ffpcn() request first */
3837 get_printer_snum(p, hnd, &snum);
3839 for (i=0; i<option->count; i++) {
3840 option_type=&option->ctr.type[i];
3842 switch ( option_type->type ) {
3843 case PRINTER_NOTIFY_TYPE:
3844 if(construct_notify_printer_info(Printer, info, snum,
3850 case JOB_NOTIFY_TYPE: {
3851 NT_PRINTER_INFO_LEVEL *printer = NULL;
3853 count = print_queue_status(snum, &queue, &status);
3855 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3858 for (j=0; j<count; j++) {
3859 construct_notify_jobs_info(&queue[j], info,
3866 free_a_printer(&printer, 2);
3876 * Debugging information, don't delete.
3879 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3880 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3881 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3883 for (i=0; i<info->count; i++) {
3884 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3885 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3886 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3892 /********************************************************************
3894 ********************************************************************/
3896 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3898 POLICY_HND *handle = &q_u->handle;
3899 SPOOL_NOTIFY_INFO *info = &r_u->info;
3901 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3902 WERROR result = WERR_BADFID;
3904 /* we always have a NOTIFY_INFO struct */
3908 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3909 OUR_HANDLE(handle)));
3913 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3916 * We are now using the change value, and
3917 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3918 * I don't have a global notification system, I'm sending back all the
3919 * informations even when _NOTHING_ has changed.
3922 /* We need to keep track of the change value to send back in
3923 RRPCN replies otherwise our updates are ignored. */
3925 Printer->notify.fnpcn = True;
3927 if (Printer->notify.client_connected) {
3928 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3929 Printer->notify.change = q_u->change;
3932 /* just ignore the SPOOL_NOTIFY_OPTION */
3934 switch (Printer->printer_type) {
3935 case PRINTER_HANDLE_IS_PRINTSERVER:
3936 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3939 case PRINTER_HANDLE_IS_PRINTER:
3940 result = printer_notify_info(p, handle, info, p->mem_ctx);
3944 Printer->notify.fnpcn = False;
3950 /********************************************************************
3951 * construct_printer_info_0
3952 * fill a printer_info_0 struct
3953 ********************************************************************/
3955 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3959 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3960 counter_printer_0 *session_counter;
3961 uint32 global_counter;
3964 print_status_struct status;
3966 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3969 count = print_queue_length(snum, &status);
3971 /* check if we already have a counter for this printer */
3972 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3973 if (session_counter->snum == snum)
3977 /* it's the first time, add it to the list */
3978 if (session_counter==NULL) {
3979 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3980 free_a_printer(&ntprinter, 2);
3983 ZERO_STRUCTP(session_counter);
3984 session_counter->snum=snum;
3985 session_counter->counter=0;
3986 DLIST_ADD(counter_list, session_counter);
3990 session_counter->counter++;
3993 * the global_counter should be stored in a TDB as it's common to all the clients
3994 * and should be zeroed on samba startup
3996 global_counter=session_counter->counter;
3998 pstrcpy(chaine,ntprinter->info_2->printername);
4000 init_unistr(&printer->printername, chaine);
4002 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
4003 init_unistr(&printer->servername, chaine);
4005 printer->cjobs = count;
4006 printer->total_jobs = 0;
4007 printer->total_bytes = 0;
4009 setuptime = (time_t)ntprinter->info_2->setuptime;
4010 t=gmtime(&setuptime);
4012 printer->year = t->tm_year+1900;
4013 printer->month = t->tm_mon+1;
4014 printer->dayofweek = t->tm_wday;
4015 printer->day = t->tm_mday;
4016 printer->hour = t->tm_hour;
4017 printer->minute = t->tm_min;
4018 printer->second = t->tm_sec;
4019 printer->milliseconds = 0;
4021 printer->global_counter = global_counter;
4022 printer->total_pages = 0;
4024 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4025 printer->major_version = 0x0005; /* NT 5 */
4026 printer->build_version = 0x0893; /* build 2195 */
4028 printer->unknown7 = 0x1;
4029 printer->unknown8 = 0x0;
4030 printer->unknown9 = 0x0;
4031 printer->session_counter = session_counter->counter;
4032 printer->unknown11 = 0x0;
4033 printer->printer_errors = 0x0; /* number of print failure */
4034 printer->unknown13 = 0x0;
4035 printer->unknown14 = 0x1;
4036 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4037 printer->unknown16 = 0x0;
4038 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4039 printer->unknown18 = 0x0;
4040 printer->status = nt_printq_status(status.status);
4041 printer->unknown20 = 0x0;
4042 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4043 printer->unknown22 = 0x0;
4044 printer->unknown23 = 0x6; /* 6 ???*/
4045 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4046 printer->unknown25 = 0;
4047 printer->unknown26 = 0;
4048 printer->unknown27 = 0;
4049 printer->unknown28 = 0;
4050 printer->unknown29 = 0;
4052 free_a_printer(&ntprinter,2);
4056 /********************************************************************
4057 * construct_printer_info_1
4058 * fill a printer_info_1 struct
4059 ********************************************************************/
4060 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4064 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4066 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4069 printer->flags=flags;
4071 if (*ntprinter->info_2->comment == '\0') {
4072 init_unistr(&printer->comment, lp_comment(snum));
4073 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4074 ntprinter->info_2->drivername, lp_comment(snum));
4077 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4078 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4079 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4082 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4084 init_unistr(&printer->description, chaine);
4085 init_unistr(&printer->name, chaine2);
4087 free_a_printer(&ntprinter,2);
4092 /****************************************************************************
4093 Free a DEVMODE struct.
4094 ****************************************************************************/
4096 static void free_dev_mode(DEVICEMODE *dev)
4101 SAFE_FREE(dev->private);
4106 /****************************************************************************
4107 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4108 should be valid upon entry
4109 ****************************************************************************/
4111 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4113 if ( !devmode || !ntdevmode )
4116 init_unistr(&devmode->devicename, ntdevmode->devicename);
4118 init_unistr(&devmode->formname, ntdevmode->formname);
4120 devmode->specversion = ntdevmode->specversion;
4121 devmode->driverversion = ntdevmode->driverversion;
4122 devmode->size = ntdevmode->size;
4123 devmode->driverextra = ntdevmode->driverextra;
4124 devmode->fields = ntdevmode->fields;
4126 devmode->orientation = ntdevmode->orientation;
4127 devmode->papersize = ntdevmode->papersize;
4128 devmode->paperlength = ntdevmode->paperlength;
4129 devmode->paperwidth = ntdevmode->paperwidth;
4130 devmode->scale = ntdevmode->scale;
4131 devmode->copies = ntdevmode->copies;
4132 devmode->defaultsource = ntdevmode->defaultsource;
4133 devmode->printquality = ntdevmode->printquality;
4134 devmode->color = ntdevmode->color;
4135 devmode->duplex = ntdevmode->duplex;
4136 devmode->yresolution = ntdevmode->yresolution;
4137 devmode->ttoption = ntdevmode->ttoption;
4138 devmode->collate = ntdevmode->collate;
4139 devmode->icmmethod = ntdevmode->icmmethod;
4140 devmode->icmintent = ntdevmode->icmintent;
4141 devmode->mediatype = ntdevmode->mediatype;
4142 devmode->dithertype = ntdevmode->dithertype;
4144 if (ntdevmode->private != NULL) {
4145 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4152 /****************************************************************************
4153 Create a DEVMODE struct. Returns malloced memory.
4154 ****************************************************************************/
4156 DEVICEMODE *construct_dev_mode(int snum)
4158 NT_PRINTER_INFO_LEVEL *printer = NULL;
4159 DEVICEMODE *devmode = NULL;
4161 DEBUG(7,("construct_dev_mode\n"));
4163 DEBUGADD(8,("getting printer characteristics\n"));
4165 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4168 if ( !printer->info_2->devmode ) {
4169 DEBUG(5, ("BONG! There was no device mode!\n"));
4173 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4174 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4178 ZERO_STRUCTP(devmode);
4180 DEBUGADD(8,("loading DEVICEMODE\n"));
4182 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4183 free_dev_mode( devmode );
4188 free_a_printer(&printer,2);
4193 /********************************************************************
4194 * construct_printer_info_2
4195 * fill a printer_info_2 struct
4196 ********************************************************************/
4198 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4201 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4203 print_status_struct status;
4205 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4208 count = print_queue_length(snum, &status);
4210 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4211 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4212 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4213 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4214 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4216 if (*ntprinter->info_2->comment == '\0')
4217 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4219 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4221 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4222 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4223 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4224 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4225 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4227 printer->attributes = ntprinter->info_2->attributes;
4229 printer->priority = ntprinter->info_2->priority; /* priority */
4230 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4231 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4232 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4233 printer->status = nt_printq_status(status.status); /* status */
4234 printer->cjobs = count; /* jobs */
4235 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4237 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4238 DEBUG(8, ("Returning NULL Devicemode!\n"));
4241 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4242 /* steal the printer info sec_desc structure. [badly done]. */
4243 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4244 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4245 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4246 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4249 printer->secdesc = NULL;
4252 free_a_printer(&ntprinter, 2);
4256 /********************************************************************
4257 * construct_printer_info_3
4258 * fill a printer_info_3 struct
4259 ********************************************************************/
4261 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4263 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4264 PRINTER_INFO_3 *printer = NULL;
4266 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4270 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4271 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4275 ZERO_STRUCTP(printer);
4277 printer->flags = 4; /* These are the components of the SD we are returning. */
4278 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4279 /* steal the printer info sec_desc structure. [badly done]. */
4280 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4284 * Set the flags for the components we are returning.
4287 if (printer->secdesc->owner_sid)
4288 printer->flags |= OWNER_SECURITY_INFORMATION;
4290 if (printer->secdesc->grp_sid)
4291 printer->flags |= GROUP_SECURITY_INFORMATION;
4293 if (printer->secdesc->dacl)
4294 printer->flags |= DACL_SECURITY_INFORMATION;
4296 if (printer->secdesc->sacl)
4297 printer->flags |= SACL_SECURITY_INFORMATION;
4300 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4301 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4302 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4305 free_a_printer(&ntprinter, 2);
4307 *pp_printer = printer;
4311 /********************************************************************
4312 * construct_printer_info_4
4313 * fill a printer_info_4 struct
4314 ********************************************************************/
4316 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4318 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4320 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4323 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4324 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4325 printer->attributes = ntprinter->info_2->attributes;
4327 free_a_printer(&ntprinter, 2);
4331 /********************************************************************
4332 * construct_printer_info_5
4333 * fill a printer_info_5 struct
4334 ********************************************************************/
4336 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4338 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4340 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4343 init_unistr(&printer->printername, ntprinter->info_2->printername);
4344 init_unistr(&printer->portname, ntprinter->info_2->portname);
4345 printer->attributes = ntprinter->info_2->attributes;
4347 /* these two are not used by NT+ according to MSDN */
4349 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4350 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4352 free_a_printer(&ntprinter, 2);
4357 /********************************************************************
4358 * construct_printer_info_7
4359 * fill a printer_info_7 struct
4360 ********************************************************************/
4362 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4364 char *guid_str = NULL;
4367 if (is_printer_published(print_hnd, snum, &guid)) {
4368 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4369 strupper_m(guid_str);
4370 init_unistr(&printer->guid, guid_str);
4371 printer->action = SPOOL_DS_PUBLISH;
4373 init_unistr(&printer->guid, "");
4374 printer->action = SPOOL_DS_UNPUBLISH;
4380 /********************************************************************
4381 Spoolss_enumprinters.
4382 ********************************************************************/
4384 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4388 int n_services=lp_numservices();
4389 PRINTER_INFO_1 *tp, *printers=NULL;
4390 PRINTER_INFO_1 current_prt;
4392 DEBUG(4,("enum_all_printers_info_1\n"));
4394 for (snum=0; snum<n_services; snum++) {
4395 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4396 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4398 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4399 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4400 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4401 SAFE_FREE(printers);
4406 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4408 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4414 /* check the required size. */
4415 for (i=0; i<*returned; i++)
4416 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4418 if (!alloc_buffer_size(buffer, *needed))
4419 return WERR_INSUFFICIENT_BUFFER;
4421 /* fill the buffer with the structures */
4422 for (i=0; i<*returned; i++)
4423 smb_io_printer_info_1("", buffer, &printers[i], 0);
4426 SAFE_FREE(printers);
4428 if (*needed > offered) {
4430 return WERR_INSUFFICIENT_BUFFER;
4436 /********************************************************************
4437 enum_all_printers_info_1_local.
4438 *********************************************************************/
4440 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4442 DEBUG(4,("enum_all_printers_info_1_local\n"));
4444 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4447 /********************************************************************
4448 enum_all_printers_info_1_name.
4449 *********************************************************************/
4451 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4455 DEBUG(4,("enum_all_printers_info_1_name\n"));
4457 if ((name[0] == '\\') && (name[1] == '\\'))
4460 if (is_myname_or_ipaddr(s)) {
4461 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4464 return WERR_INVALID_NAME;
4467 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4468 /********************************************************************
4469 enum_all_printers_info_1_remote.
4470 *********************************************************************/
4472 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4474 PRINTER_INFO_1 *printer;
4475 fstring printername;
4478 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4480 /* JFM: currently it's more a place holder than anything else.
4481 * In the spooler world there is a notion of server registration.
4482 * the print servers are registered on the PDC (in the same domain)
4484 * We should have a TDB here. The registration is done thru an
4485 * undocumented RPC call.
4488 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4493 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4494 slprintf(desc, sizeof(desc)-1,"%s", name);
4495 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4497 init_unistr(&printer->description, desc);
4498 init_unistr(&printer->name, printername);
4499 init_unistr(&printer->comment, comment);
4500 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4502 /* check the required size. */
4503 *needed += spoolss_size_printer_info_1(printer);
4505 if (!alloc_buffer_size(buffer, *needed)) {
4507 return WERR_INSUFFICIENT_BUFFER;
4510 /* fill the buffer with the structures */
4511 smb_io_printer_info_1("", buffer, printer, 0);
4516 if (*needed > offered) {
4518 return WERR_INSUFFICIENT_BUFFER;
4526 /********************************************************************
4527 enum_all_printers_info_1_network.
4528 *********************************************************************/
4530 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4534 DEBUG(4,("enum_all_printers_info_1_network\n"));
4536 /* If we respond to a enum_printers level 1 on our name with flags
4537 set to PRINTER_ENUM_REMOTE with a list of printers then these
4538 printers incorrectly appear in the APW browse list.
4539 Specifically the printers for the server appear at the workgroup
4540 level where all the other servers in the domain are
4541 listed. Windows responds to this call with a
4542 WERR_CAN_NOT_COMPLETE so we should do the same. */
4544 if (name[0] == '\\' && name[1] == '\\')
4547 if (is_myname_or_ipaddr(s))
4548 return WERR_CAN_NOT_COMPLETE;
4550 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4553 /********************************************************************
4554 * api_spoolss_enumprinters
4556 * called from api_spoolss_enumprinters (see this to understand)
4557 ********************************************************************/
4559 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4563 int n_services=lp_numservices();
4564 PRINTER_INFO_2 *tp, *printers=NULL;
4565 PRINTER_INFO_2 current_prt;
4567 for (snum=0; snum<n_services; snum++) {
4568 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4569 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4571 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4572 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4573 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4574 SAFE_FREE(printers);
4579 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4580 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4586 /* check the required size. */
4587 for (i=0; i<*returned; i++)
4588 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4590 if (!alloc_buffer_size(buffer, *needed)) {
4591 for (i=0; i<*returned; i++) {
4592 free_devmode(printers[i].devmode);
4594 SAFE_FREE(printers);
4595 return WERR_INSUFFICIENT_BUFFER;
4598 /* fill the buffer with the structures */
4599 for (i=0; i<*returned; i++)
4600 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4603 for (i=0; i<*returned; i++) {
4604 free_devmode(printers[i].devmode);
4606 SAFE_FREE(printers);
4608 if (*needed > offered) {
4610 return WERR_INSUFFICIENT_BUFFER;
4616 /********************************************************************
4617 * handle enumeration of printers at level 1
4618 ********************************************************************/
4620 static WERROR enumprinters_level1( uint32 flags, fstring name,
4621 NEW_BUFFER *buffer, uint32 offered,
4622 uint32 *needed, uint32 *returned)
4624 /* Not all the flags are equals */
4626 if (flags & PRINTER_ENUM_LOCAL)
4627 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4629 if (flags & PRINTER_ENUM_NAME)
4630 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4632 #if 0 /* JERRY - disabled for now */
4633 if (flags & PRINTER_ENUM_REMOTE)
4634 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4637 if (flags & PRINTER_ENUM_NETWORK)
4638 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4640 return WERR_OK; /* NT4sp5 does that */
4643 /********************************************************************
4644 * handle enumeration of printers at level 2
4645 ********************************************************************/
4647 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4648 NEW_BUFFER *buffer, uint32 offered,
4649 uint32 *needed, uint32 *returned)
4651 char *s = servername;
4653 if (flags & PRINTER_ENUM_LOCAL) {
4654 return enum_all_printers_info_2(buffer, offered, needed, returned);
4657 if (flags & PRINTER_ENUM_NAME) {
4658 if ((servername[0] == '\\') && (servername[1] == '\\'))
4660 if (is_myname_or_ipaddr(s))
4661 return enum_all_printers_info_2(buffer, offered, needed, returned);
4663 return WERR_INVALID_NAME;
4666 if (flags & PRINTER_ENUM_REMOTE)
4667 return WERR_UNKNOWN_LEVEL;
4672 /********************************************************************
4673 * handle enumeration of printers at level 5
4674 ********************************************************************/
4676 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4677 NEW_BUFFER *buffer, uint32 offered,
4678 uint32 *needed, uint32 *returned)
4680 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4684 /********************************************************************
4685 * api_spoolss_enumprinters
4687 * called from api_spoolss_enumprinters (see this to understand)
4688 ********************************************************************/
4690 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4692 uint32 flags = q_u->flags;
4693 UNISTR2 *servername = &q_u->servername;
4694 uint32 level = q_u->level;
4695 NEW_BUFFER *buffer = NULL;
4696 uint32 offered = q_u->offered;
4697 uint32 *needed = &r_u->needed;
4698 uint32 *returned = &r_u->returned;
4702 /* that's an [in out] buffer */
4703 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4704 buffer = r_u->buffer;
4706 DEBUG(4,("_spoolss_enumprinters\n"));
4713 * flags==PRINTER_ENUM_NAME
4714 * if name=="" then enumerates all printers
4715 * if name!="" then enumerate the printer
4716 * flags==PRINTER_ENUM_REMOTE
4717 * name is NULL, enumerate printers
4718 * Level 2: name!="" enumerates printers, name can't be NULL
4719 * Level 3: doesn't exist
4720 * Level 4: does a local registry lookup
4721 * Level 5: same as Level 2
4724 unistr2_to_ascii(name, servername, sizeof(name)-1);
4729 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4731 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4733 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4738 return WERR_UNKNOWN_LEVEL;
4741 /****************************************************************************
4742 ****************************************************************************/
4744 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4746 PRINTER_INFO_0 *printer=NULL;
4748 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4751 construct_printer_info_0(print_hnd, printer, snum);
4753 /* check the required size. */
4754 *needed += spoolss_size_printer_info_0(printer);
4756 if (!alloc_buffer_size(buffer, *needed)) {
4758 return WERR_INSUFFICIENT_BUFFER;
4761 /* fill the buffer with the structures */
4762 smb_io_printer_info_0("", buffer, printer, 0);
4767 if (*needed > offered) {
4768 return WERR_INSUFFICIENT_BUFFER;
4774 /****************************************************************************
4775 ****************************************************************************/
4777 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4779 PRINTER_INFO_1 *printer=NULL;
4781 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4784 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4786 /* check the required size. */
4787 *needed += spoolss_size_printer_info_1(printer);
4789 if (!alloc_buffer_size(buffer, *needed)) {
4791 return WERR_INSUFFICIENT_BUFFER;
4794 /* fill the buffer with the structures */
4795 smb_io_printer_info_1("", buffer, printer, 0);
4800 if (*needed > offered) {
4801 return WERR_INSUFFICIENT_BUFFER;
4807 /****************************************************************************
4808 ****************************************************************************/
4810 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4812 PRINTER_INFO_2 *printer=NULL;
4814 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4817 construct_printer_info_2(print_hnd, printer, snum);
4819 /* check the required size. */
4820 *needed += spoolss_size_printer_info_2(printer);
4822 if (!alloc_buffer_size(buffer, *needed)) {
4823 free_printer_info_2(printer);
4824 return WERR_INSUFFICIENT_BUFFER;
4827 /* fill the buffer with the structures */
4828 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4829 free_printer_info_2(printer);
4834 free_printer_info_2(printer);
4836 if (*needed > offered) {
4837 return WERR_INSUFFICIENT_BUFFER;
4843 /****************************************************************************
4844 ****************************************************************************/
4846 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4848 PRINTER_INFO_3 *printer=NULL;
4850 if (!construct_printer_info_3(print_hnd, &printer, snum))
4853 /* check the required size. */
4854 *needed += spoolss_size_printer_info_3(printer);
4856 if (!alloc_buffer_size(buffer, *needed)) {
4857 free_printer_info_3(printer);
4858 return WERR_INSUFFICIENT_BUFFER;
4861 /* fill the buffer with the structures */
4862 smb_io_printer_info_3("", buffer, printer, 0);
4865 free_printer_info_3(printer);
4867 if (*needed > offered) {
4868 return WERR_INSUFFICIENT_BUFFER;
4874 /****************************************************************************
4875 ****************************************************************************/
4877 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4879 PRINTER_INFO_4 *printer=NULL;
4881 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4884 if (!construct_printer_info_4(print_hnd, printer, snum))
4887 /* check the required size. */
4888 *needed += spoolss_size_printer_info_4(printer);
4890 if (!alloc_buffer_size(buffer, *needed)) {
4891 free_printer_info_4(printer);
4892 return WERR_INSUFFICIENT_BUFFER;
4895 /* fill the buffer with the structures */
4896 smb_io_printer_info_4("", buffer, printer, 0);
4899 free_printer_info_4(printer);
4901 if (*needed > offered) {
4902 return WERR_INSUFFICIENT_BUFFER;
4908 /****************************************************************************
4909 ****************************************************************************/
4911 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4913 PRINTER_INFO_5 *printer=NULL;
4915 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4918 if (!construct_printer_info_5(print_hnd, printer, snum))
4921 /* check the required size. */
4922 *needed += spoolss_size_printer_info_5(printer);
4924 if (!alloc_buffer_size(buffer, *needed)) {
4925 free_printer_info_5(printer);
4926 return WERR_INSUFFICIENT_BUFFER;
4929 /* fill the buffer with the structures */
4930 smb_io_printer_info_5("", buffer, printer, 0);
4933 free_printer_info_5(printer);
4935 if (*needed > offered) {
4936 return WERR_INSUFFICIENT_BUFFER;
4942 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4944 PRINTER_INFO_7 *printer=NULL;
4946 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4949 if (!construct_printer_info_7(print_hnd, printer, snum))
4952 /* check the required size. */
4953 *needed += spoolss_size_printer_info_7(printer);
4955 if (!alloc_buffer_size(buffer, *needed)) {
4956 free_printer_info_7(printer);
4957 return WERR_INSUFFICIENT_BUFFER;
4960 /* fill the buffer with the structures */
4961 smb_io_printer_info_7("", buffer, printer, 0);
4964 free_printer_info_7(printer);
4966 if (*needed > offered) {
4967 return WERR_INSUFFICIENT_BUFFER;
4973 /****************************************************************************
4974 ****************************************************************************/
4976 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4978 POLICY_HND *handle = &q_u->handle;
4979 uint32 level = q_u->level;
4980 NEW_BUFFER *buffer = NULL;
4981 uint32 offered = q_u->offered;
4982 uint32 *needed = &r_u->needed;
4983 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4987 /* that's an [in out] buffer */
4988 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4989 buffer = r_u->buffer;
4993 if (!get_printer_snum(p, handle, &snum))
4998 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5000 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5002 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5004 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5006 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5008 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5010 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5012 return WERR_UNKNOWN_LEVEL;
5015 /********************************************************************
5016 * fill a DRIVER_INFO_1 struct
5017 ********************************************************************/
5019 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5021 init_unistr( &info->name, driver.info_3->name);
5024 /********************************************************************
5025 * construct_printer_driver_info_1
5026 ********************************************************************/
5028 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5030 NT_PRINTER_INFO_LEVEL *printer = NULL;
5031 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5033 ZERO_STRUCT(driver);
5035 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5036 return WERR_INVALID_PRINTER_NAME;
5038 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5039 return WERR_UNKNOWN_PRINTER_DRIVER;
5041 fill_printer_driver_info_1(info, driver, servername, architecture);
5043 free_a_printer(&printer,2);
5048 /********************************************************************
5049 * construct_printer_driver_info_2
5050 * fill a printer_info_2 struct
5051 ********************************************************************/
5053 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5057 info->version=driver.info_3->cversion;
5059 init_unistr( &info->name, driver.info_3->name );
5060 init_unistr( &info->architecture, driver.info_3->environment );
5063 if (strlen(driver.info_3->driverpath)) {
5064 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5065 init_unistr( &info->driverpath, temp );
5067 init_unistr( &info->driverpath, "" );
5069 if (strlen(driver.info_3->datafile)) {
5070 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5071 init_unistr( &info->datafile, temp );
5073 init_unistr( &info->datafile, "" );
5075 if (strlen(driver.info_3->configfile)) {
5076 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5077 init_unistr( &info->configfile, temp );
5079 init_unistr( &info->configfile, "" );
5082 /********************************************************************
5083 * construct_printer_driver_info_2
5084 * fill a printer_info_2 struct
5085 ********************************************************************/
5087 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5089 NT_PRINTER_INFO_LEVEL *printer = NULL;
5090 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5092 ZERO_STRUCT(printer);
5093 ZERO_STRUCT(driver);
5095 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5096 return WERR_INVALID_PRINTER_NAME;
5098 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5099 return WERR_UNKNOWN_PRINTER_DRIVER;
5101 fill_printer_driver_info_2(info, driver, servername);
5103 free_a_printer(&printer,2);
5108 /********************************************************************
5109 * copy a strings array and convert to UNICODE
5111 * convert an array of ascii string to a UNICODE string
5112 ********************************************************************/
5114 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5122 DEBUG(6,("init_unistr_array\n"));
5133 v = ""; /* hack to handle null lists */
5136 /* hack to allow this to be used in places other than when generating
5137 the list of dependent files */
5140 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5144 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5146 /* add one extra unit16 for the second terminating NULL */
5148 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5149 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5157 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5162 /* special case for ""; we need to add both NULL's here */
5164 (*uni_array)[j++]=0x0000;
5165 (*uni_array)[j]=0x0000;
5168 DEBUGADD(6,("last one:done\n"));
5170 /* return size of array in uint16's */
5175 /********************************************************************
5176 * construct_printer_info_3
5177 * fill a printer_info_3 struct
5178 ********************************************************************/
5180 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5186 info->version=driver.info_3->cversion;
5188 init_unistr( &info->name, driver.info_3->name );
5189 init_unistr( &info->architecture, driver.info_3->environment );
5191 if (strlen(driver.info_3->driverpath)) {
5192 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5193 init_unistr( &info->driverpath, temp );
5195 init_unistr( &info->driverpath, "" );
5197 if (strlen(driver.info_3->datafile)) {
5198 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5199 init_unistr( &info->datafile, temp );
5201 init_unistr( &info->datafile, "" );
5203 if (strlen(driver.info_3->configfile)) {
5204 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5205 init_unistr( &info->configfile, temp );
5207 init_unistr( &info->configfile, "" );
5209 if (strlen(driver.info_3->helpfile)) {
5210 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5211 init_unistr( &info->helpfile, temp );
5213 init_unistr( &info->helpfile, "" );
5215 init_unistr( &info->monitorname, driver.info_3->monitorname );
5216 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5218 info->dependentfiles=NULL;
5219 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5222 /********************************************************************
5223 * construct_printer_info_3
5224 * fill a printer_info_3 struct
5225 ********************************************************************/
5227 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5229 NT_PRINTER_INFO_LEVEL *printer = NULL;
5230 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5232 ZERO_STRUCT(driver);
5234 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5235 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5236 if (!W_ERROR_IS_OK(status))
5237 return WERR_INVALID_PRINTER_NAME;
5239 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5240 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5245 * I put this code in during testing. Helpful when commenting out the
5246 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5247 * as win2k always queries the driver using an infor level of 6.
5248 * I've left it in (but ifdef'd out) because I'll probably
5249 * use it in experimentation again in the future. --jerry 22/01/2002
5252 if (!W_ERROR_IS_OK(status)) {
5254 * Is this a W2k client ?
5257 /* Yes - try again with a WinNT driver. */
5259 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5260 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5264 if (!W_ERROR_IS_OK(status)) {
5265 free_a_printer(&printer,2);
5266 return WERR_UNKNOWN_PRINTER_DRIVER;
5274 fill_printer_driver_info_3(info, driver, servername);
5276 free_a_printer(&printer,2);
5281 /********************************************************************
5282 * construct_printer_info_6
5283 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5284 ********************************************************************/
5286 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5292 memset(&nullstr, '\0', sizeof(fstring));
5294 info->version=driver.info_3->cversion;
5296 init_unistr( &info->name, driver.info_3->name );
5297 init_unistr( &info->architecture, driver.info_3->environment );
5299 if (strlen(driver.info_3->driverpath)) {
5300 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5301 init_unistr( &info->driverpath, temp );
5303 init_unistr( &info->driverpath, "" );
5305 if (strlen(driver.info_3->datafile)) {
5306 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5307 init_unistr( &info->datafile, temp );
5309 init_unistr( &info->datafile, "" );
5311 if (strlen(driver.info_3->configfile)) {
5312 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5313 init_unistr( &info->configfile, temp );
5315 init_unistr( &info->configfile, "" );
5317 if (strlen(driver.info_3->helpfile)) {
5318 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5319 init_unistr( &info->helpfile, temp );
5321 init_unistr( &info->helpfile, "" );
5323 init_unistr( &info->monitorname, driver.info_3->monitorname );
5324 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5326 info->dependentfiles = NULL;
5327 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5329 info->previousdrivernames=NULL;
5330 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5332 info->driver_date.low=0;
5333 info->driver_date.high=0;
5336 info->driver_version_low=0;
5337 info->driver_version_high=0;
5339 init_unistr( &info->mfgname, "");
5340 init_unistr( &info->oem_url, "");
5341 init_unistr( &info->hardware_id, "");
5342 init_unistr( &info->provider, "");
5345 /********************************************************************
5346 * construct_printer_info_6
5347 * fill a printer_info_6 struct
5348 ********************************************************************/
5350 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5351 fstring servername, fstring architecture, uint32 version)
5353 NT_PRINTER_INFO_LEVEL *printer = NULL;
5354 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5357 ZERO_STRUCT(driver);
5359 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5361 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5363 if (!W_ERROR_IS_OK(status))
5364 return WERR_INVALID_PRINTER_NAME;
5366 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5368 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5370 if (!W_ERROR_IS_OK(status))
5373 * Is this a W2k client ?
5377 free_a_printer(&printer,2);
5378 return WERR_UNKNOWN_PRINTER_DRIVER;
5381 /* Yes - try again with a WinNT driver. */
5383 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5384 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5385 if (!W_ERROR_IS_OK(status)) {
5386 free_a_printer(&printer,2);
5387 return WERR_UNKNOWN_PRINTER_DRIVER;
5391 fill_printer_driver_info_6(info, driver, servername);
5393 free_a_printer(&printer,2);
5394 free_a_printer_driver(driver, 3);
5399 /****************************************************************************
5400 ****************************************************************************/
5402 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5404 SAFE_FREE(info->dependentfiles);
5407 /****************************************************************************
5408 ****************************************************************************/
5410 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5412 SAFE_FREE(info->dependentfiles);
5416 /****************************************************************************
5417 ****************************************************************************/
5419 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5421 DRIVER_INFO_1 *info=NULL;
5424 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5427 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5428 if (!W_ERROR_IS_OK(status)) {
5433 /* check the required size. */
5434 *needed += spoolss_size_printer_driver_info_1(info);
5436 if (!alloc_buffer_size(buffer, *needed)) {
5438 return WERR_INSUFFICIENT_BUFFER;
5441 /* fill the buffer with the structures */
5442 smb_io_printer_driver_info_1("", buffer, info, 0);
5447 if (*needed > offered)
5448 return WERR_INSUFFICIENT_BUFFER;
5453 /****************************************************************************
5454 ****************************************************************************/
5456 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5458 DRIVER_INFO_2 *info=NULL;
5461 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5464 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5465 if (!W_ERROR_IS_OK(status)) {
5470 /* check the required size. */
5471 *needed += spoolss_size_printer_driver_info_2(info);
5473 if (!alloc_buffer_size(buffer, *needed)) {
5475 return WERR_INSUFFICIENT_BUFFER;
5478 /* fill the buffer with the structures */
5479 smb_io_printer_driver_info_2("", buffer, info, 0);
5484 if (*needed > offered)
5485 return WERR_INSUFFICIENT_BUFFER;
5490 /****************************************************************************
5491 ****************************************************************************/
5493 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5500 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5501 if (!W_ERROR_IS_OK(status)) {
5505 /* check the required size. */
5506 *needed += spoolss_size_printer_driver_info_3(&info);
5508 if (!alloc_buffer_size(buffer, *needed)) {
5509 free_printer_driver_info_3(&info);
5510 return WERR_INSUFFICIENT_BUFFER;
5513 /* fill the buffer with the structures */
5514 smb_io_printer_driver_info_3("", buffer, &info, 0);
5516 free_printer_driver_info_3(&info);
5518 if (*needed > offered)
5519 return WERR_INSUFFICIENT_BUFFER;
5524 /****************************************************************************
5525 ****************************************************************************/
5527 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5534 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5535 if (!W_ERROR_IS_OK(status)) {
5539 /* check the required size. */
5540 *needed += spoolss_size_printer_driver_info_6(&info);
5542 if (!alloc_buffer_size(buffer, *needed)) {
5543 free_printer_driver_info_6(&info);
5544 return WERR_INSUFFICIENT_BUFFER;
5547 /* fill the buffer with the structures */
5548 smb_io_printer_driver_info_6("", buffer, &info, 0);
5550 free_printer_driver_info_6(&info);
5552 if (*needed > offered)
5553 return WERR_INSUFFICIENT_BUFFER;
5558 /****************************************************************************
5559 ****************************************************************************/
5561 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5563 POLICY_HND *handle = &q_u->handle;
5564 UNISTR2 *uni_arch = &q_u->architecture;
5565 uint32 level = q_u->level;
5566 uint32 clientmajorversion = q_u->clientmajorversion;
5567 NEW_BUFFER *buffer = NULL;
5568 uint32 offered = q_u->offered;
5569 uint32 *needed = &r_u->needed;
5570 uint32 *servermajorversion = &r_u->servermajorversion;
5571 uint32 *serverminorversion = &r_u->serverminorversion;
5572 Printer_entry *printer;
5575 fstring architecture;
5578 /* that's an [in out] buffer */
5579 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5580 buffer = r_u->buffer;
5582 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5584 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5585 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5586 return WERR_INVALID_PRINTER_NAME;
5590 *servermajorversion = 0;
5591 *serverminorversion = 0;
5593 fstrcpy(servername, get_server_name( printer ));
5594 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5596 if (!get_printer_snum(p, handle, &snum))
5601 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5603 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5605 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5607 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5610 /* apparently this call is the equivalent of
5611 EnumPrinterDataEx() for the DsDriver key */
5616 return WERR_UNKNOWN_LEVEL;
5619 /****************************************************************************
5620 ****************************************************************************/
5622 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5624 POLICY_HND *handle = &q_u->handle;
5626 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5629 DEBUG(3,("Error in startpageprinter printer handle\n"));
5633 Printer->page_started=True;
5637 /****************************************************************************
5638 ****************************************************************************/
5640 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5642 POLICY_HND *handle = &q_u->handle;
5645 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5648 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5652 if (!get_printer_snum(p, handle, &snum))
5655 Printer->page_started=False;
5656 print_job_endpage(snum, Printer->jobid);
5661 /********************************************************************
5662 * api_spoolss_getprinter
5663 * called from the spoolss dispatcher
5665 ********************************************************************/
5667 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5669 POLICY_HND *handle = &q_u->handle;
5670 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5671 uint32 *jobid = &r_u->jobid;
5673 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5677 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5678 struct current_user user;
5681 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5685 get_current_user(&user, p);
5688 * a nice thing with NT is it doesn't listen to what you tell it.
5689 * when asked to send _only_ RAW datas, it tries to send datas
5692 * So I add checks like in NT Server ...
5695 if (info_1->p_datatype != 0) {
5696 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5697 if (strcmp(datatype, "RAW") != 0) {
5699 return WERR_INVALID_DATATYPE;
5703 /* get the share number of the printer */
5704 if (!get_printer_snum(p, handle, &snum)) {
5708 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5710 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5712 /* An error occured in print_job_start() so return an appropriate
5715 if (Printer->jobid == -1) {
5716 return map_werror_from_unix(errno);
5719 Printer->document_started=True;
5720 (*jobid) = Printer->jobid;
5725 /********************************************************************
5726 * api_spoolss_getprinter
5727 * called from the spoolss dispatcher
5729 ********************************************************************/
5731 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5733 POLICY_HND *handle = &q_u->handle;
5735 return _spoolss_enddocprinter_internal(p, handle);
5738 /****************************************************************************
5739 ****************************************************************************/
5741 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5743 POLICY_HND *handle = &q_u->handle;
5744 uint32 buffer_size = q_u->buffer_size;
5745 uint8 *buffer = q_u->buffer;
5746 uint32 *buffer_written = &q_u->buffer_size2;
5748 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5751 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5752 r_u->buffer_written = q_u->buffer_size2;
5756 if (!get_printer_snum(p, handle, &snum))
5759 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5760 if (*buffer_written == -1) {
5761 r_u->buffer_written = 0;
5762 if (errno == ENOSPC)
5763 return WERR_NO_SPOOL_SPACE;
5765 return WERR_ACCESS_DENIED;
5768 r_u->buffer_written = q_u->buffer_size2;
5773 /********************************************************************
5774 * api_spoolss_getprinter
5775 * called from the spoolss dispatcher
5777 ********************************************************************/
5779 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5782 struct current_user user;
5784 WERROR errcode = WERR_BADFUNC;
5785 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5787 get_current_user(&user, p);
5790 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5794 if (!get_printer_snum(p, handle, &snum))
5798 case PRINTER_CONTROL_PAUSE:
5799 if (print_queue_pause(&user, snum, &errcode)) {
5803 case PRINTER_CONTROL_RESUME:
5804 case PRINTER_CONTROL_UNPAUSE:
5805 if (print_queue_resume(&user, snum, &errcode)) {
5809 case PRINTER_CONTROL_PURGE:
5810 if (print_queue_purge(&user, snum, &errcode)) {
5815 return WERR_UNKNOWN_LEVEL;
5821 /********************************************************************
5822 * api_spoolss_abortprinter
5823 * From MSDN: "Deletes printer's spool file if printer is configured
5825 ********************************************************************/
5827 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5829 POLICY_HND *handle = &q_u->handle;
5830 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5832 struct current_user user;
5833 WERROR errcode = WERR_OK;
5836 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5840 if (!get_printer_snum(p, handle, &snum))
5843 get_current_user( &user, p );
5845 print_job_delete( &user, snum, Printer->jobid, &errcode );
5850 /********************************************************************
5851 * called by spoolss_api_setprinter
5852 * when updating a printer description
5853 ********************************************************************/
5855 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5856 const SPOOL_PRINTER_INFO_LEVEL *info,
5857 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5859 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5860 struct current_user user;
5864 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5866 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5867 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5868 OUR_HANDLE(handle)));
5870 result = WERR_BADFID;
5874 /* NT seems to like setting the security descriptor even though
5875 nothing may have actually changed. */
5877 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5879 if (DEBUGLEVEL >= 10) {
5883 the_acl = old_secdesc_ctr->sec->dacl;
5884 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5885 PRINTERNAME(snum), the_acl->num_aces));
5887 for (i = 0; i < the_acl->num_aces; i++) {
5890 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5892 DEBUG(10, ("%s 0x%08x\n", sid_str,
5893 the_acl->ace[i].info.mask));
5896 the_acl = secdesc_ctr->sec->dacl;
5899 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5900 PRINTERNAME(snum), the_acl->num_aces));
5902 for (i = 0; i < the_acl->num_aces; i++) {
5905 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5907 DEBUG(10, ("%s 0x%08x\n", sid_str,
5908 the_acl->ace[i].info.mask));
5911 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5915 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5917 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5922 /* Work out which user is performing the operation */
5924 get_current_user(&user, p);
5926 /* Check the user has permissions to change the security
5927 descriptor. By experimentation with two NT machines, the user
5928 requires Full Access to the printer to change security
5931 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5932 result = WERR_ACCESS_DENIED;
5936 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5943 /********************************************************************
5944 Canonicalize printer info from a client
5946 ATTN: It does not matter what we set the servername to hear
5947 since we do the necessary work in get_a_printer() to set it to
5948 the correct value based on what the client sent in the
5949 _spoolss_open_printer_ex().
5950 ********************************************************************/
5952 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5954 fstring printername;
5957 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5958 "portname=%s drivername=%s comment=%s location=%s\n",
5959 info->servername, info->printername, info->sharename,
5960 info->portname, info->drivername, info->comment, info->location));
5962 /* we force some elements to "correct" values */
5963 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5964 fstrcpy(info->sharename, lp_servicename(snum));
5966 /* make sure printername is in \\server\printername format */
5968 fstrcpy( printername, info->printername );
5970 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5971 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5975 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5976 global_myname(), p );
5978 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5979 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5986 /****************************************************************************
5987 ****************************************************************************/
5989 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5991 extern userdom_struct current_user_info;
5992 char *cmd = lp_addprinter_cmd();
5998 fstring remote_machine = "%m";
6000 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6002 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6003 cmd, printer->info_2->printername, printer->info_2->sharename,
6004 printer->info_2->portname, printer->info_2->drivername,
6005 printer->info_2->location, printer->info_2->comment, remote_machine);
6007 DEBUG(10,("Running [%s]\n", command));
6008 ret = smbrun(command, &fd);
6009 DEBUGADD(10,("returned [%d]\n", ret));
6018 /* Get lines and convert them back to dos-codepage */
6019 qlines = fd_lines_load(fd, &numlines);
6020 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6024 /* Set the portname to what the script says the portname should be. */
6025 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6026 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6028 /* Send SIGHUP to process group... is there a better way? */
6031 /* reload our services immediately */
6032 reload_services( False );
6035 file_lines_free(qlines);
6039 /********************************************************************
6040 * Called by spoolss_api_setprinter
6041 * when updating a printer description.
6042 ********************************************************************/
6044 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6045 const SPOOL_PRINTER_INFO_LEVEL *info,
6046 DEVICEMODE *devmode)
6049 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6050 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6055 DEBUG(8,("update_printer\n"));
6060 result = WERR_BADFID;
6064 if (!get_printer_snum(p, handle, &snum)) {
6065 result = WERR_BADFID;
6069 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6070 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6071 result = WERR_BADFID;
6075 DEBUGADD(8,("Converting info_2 struct\n"));
6078 * convert_printer_info converts the incoming
6079 * info from the client and overwrites the info
6080 * just read from the tdb in the pointer 'printer'.
6083 if (!convert_printer_info(info, printer, level)) {
6084 result = WERR_NOMEM;
6089 /* we have a valid devmode
6090 convert it and link it*/
6092 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6093 if (!convert_devicemode(printer->info_2->printername, devmode,
6094 &printer->info_2->devmode)) {
6095 result = WERR_NOMEM;
6100 /* Do sanity check on the requested changes for Samba */
6102 if (!check_printer_ok(printer->info_2, snum)) {
6103 result = WERR_INVALID_PARAM;
6107 /* FIXME!!! If the driver has changed we really should verify that
6108 it is installed before doing much else --jerry */
6110 /* Check calling user has permission to update printer description */
6112 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6113 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6114 result = WERR_ACCESS_DENIED;
6118 /* Call addprinter hook */
6119 /* Check changes to see if this is really needed */
6121 if ( *lp_addprinter_cmd()
6122 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6123 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6124 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6125 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6127 if ( !add_printer_hook(printer) ) {
6128 result = WERR_ACCESS_DENIED;
6133 * make sure we actually reload the services after
6134 * this as smb.conf could have a new section in it
6135 * .... shouldn't .... but could
6137 reload_services(False);
6141 * When a *new* driver is bound to a printer, the drivername is used to
6142 * lookup previously saved driver initialization info, which is then
6143 * bound to the printer, simulating what happens in the Windows arch.
6145 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6147 if (!set_driver_init(printer, 2))
6149 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6150 printer->info_2->drivername));
6153 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6154 printer->info_2->drivername));
6156 notify_printer_driver(snum, printer->info_2->drivername);
6160 * flag which changes actually occured. This is a small subset of
6161 * all the possible changes. We also have to update things in the
6165 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6166 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6167 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6168 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6170 notify_printer_comment(snum, printer->info_2->comment);
6173 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6174 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6175 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6176 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6178 notify_printer_sharename(snum, printer->info_2->sharename);
6181 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6184 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6187 pname = printer->info_2->printername;
6190 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6191 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6192 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6194 notify_printer_printername( snum, pname );
6197 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6198 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6199 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6200 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6202 notify_printer_port(snum, printer->info_2->portname);
6205 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6206 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6207 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6208 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6210 notify_printer_location(snum, printer->info_2->location);
6213 /* here we need to update some more DsSpooler keys */
6214 /* uNCName, serverName, shortServerName */
6216 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6217 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6218 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6219 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6220 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6222 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6223 global_myname(), printer->info_2->sharename );
6224 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6225 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6226 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6228 /* Update printer info */
6229 result = mod_a_printer(printer, 2);
6232 free_a_printer(&printer, 2);
6233 free_a_printer(&old_printer, 2);
6239 /****************************************************************************
6240 ****************************************************************************/
6241 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6242 const SPOOL_PRINTER_INFO_LEVEL *info)
6245 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6247 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6249 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6254 if (!get_printer_snum(p, handle, &snum))
6257 nt_printer_publish(Printer, snum, info7->action);
6261 return WERR_UNKNOWN_LEVEL;
6264 /****************************************************************************
6265 ****************************************************************************/
6267 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6269 POLICY_HND *handle = &q_u->handle;
6270 uint32 level = q_u->level;
6271 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6272 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6273 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6274 uint32 command = q_u->command;
6277 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6280 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6284 /* check the level */
6287 return control_printer(handle, command, p);
6289 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6290 if (!W_ERROR_IS_OK(result))
6293 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6296 return update_printer_sec(handle, level, info, p,
6299 return publish_or_unpublish_printer(p, handle, info);
6301 return WERR_UNKNOWN_LEVEL;
6305 /****************************************************************************
6306 ****************************************************************************/
6308 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6310 POLICY_HND *handle = &q_u->handle;
6311 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6314 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6318 if (Printer->notify.client_connected==True) {
6321 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6323 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6324 !get_printer_snum(p, handle, &snum) )
6327 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6330 Printer->notify.flags=0;
6331 Printer->notify.options=0;
6332 Printer->notify.localmachine[0]='\0';
6333 Printer->notify.printerlocal=0;
6334 if (Printer->notify.option)
6335 free_spool_notify_option(&Printer->notify.option);
6336 Printer->notify.client_connected=False;
6341 /****************************************************************************
6342 ****************************************************************************/
6344 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6346 /* that's an [in out] buffer (despite appearences to the contrary) */
6347 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6350 return WERR_INVALID_PARAM; /* this is what a NT server
6351 returns for AddJob. AddJob
6352 must fail on non-local
6356 /****************************************************************************
6357 ****************************************************************************/
6359 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6360 int position, int snum,
6361 NT_PRINTER_INFO_LEVEL *ntprinter)
6365 t=gmtime(&queue->time);
6367 job_info->jobid=queue->job;
6368 init_unistr(&job_info->printername, lp_servicename(snum));
6369 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6370 init_unistr(&job_info->username, queue->fs_user);
6371 init_unistr(&job_info->document, queue->fs_file);
6372 init_unistr(&job_info->datatype, "RAW");
6373 init_unistr(&job_info->text_status, "");
6374 job_info->status=nt_printj_status(queue->status);
6375 job_info->priority=queue->priority;
6376 job_info->position=position;
6377 job_info->totalpages=queue->page_count;
6378 job_info->pagesprinted=0;
6380 make_systemtime(&job_info->submitted, t);
6383 /****************************************************************************
6384 ****************************************************************************/
6386 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6387 int position, int snum,
6388 NT_PRINTER_INFO_LEVEL *ntprinter,
6389 DEVICEMODE *devmode)
6393 t=gmtime(&queue->time);
6395 job_info->jobid=queue->job;
6397 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6399 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6400 init_unistr(&job_info->username, queue->fs_user);
6401 init_unistr(&job_info->document, queue->fs_file);
6402 init_unistr(&job_info->notifyname, queue->fs_user);
6403 init_unistr(&job_info->datatype, "RAW");
6404 init_unistr(&job_info->printprocessor, "winprint");
6405 init_unistr(&job_info->parameters, "");
6406 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6407 init_unistr(&job_info->text_status, "");
6409 /* and here the security descriptor */
6411 job_info->status=nt_printj_status(queue->status);
6412 job_info->priority=queue->priority;
6413 job_info->position=position;
6414 job_info->starttime=0;
6415 job_info->untiltime=0;
6416 job_info->totalpages=queue->page_count;
6417 job_info->size=queue->size;
6418 make_systemtime(&(job_info->submitted), t);
6419 job_info->timeelapsed=0;
6420 job_info->pagesprinted=0;
6422 job_info->devmode = devmode;
6427 /****************************************************************************
6428 Enumjobs at level 1.
6429 ****************************************************************************/
6431 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6432 NT_PRINTER_INFO_LEVEL *ntprinter,
6433 NEW_BUFFER *buffer, uint32 offered,
6434 uint32 *needed, uint32 *returned)
6439 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6446 for (i=0; i<*returned; i++)
6447 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6451 /* check the required size. */
6452 for (i=0; i<*returned; i++)
6453 (*needed) += spoolss_size_job_info_1(&info[i]);
6455 if (!alloc_buffer_size(buffer, *needed)) {
6457 return WERR_INSUFFICIENT_BUFFER;
6460 /* fill the buffer with the structures */
6461 for (i=0; i<*returned; i++)
6462 smb_io_job_info_1("", buffer, &info[i], 0);
6467 if (*needed > offered) {
6469 return WERR_INSUFFICIENT_BUFFER;
6475 /****************************************************************************
6476 Enumjobs at level 2.
6477 ****************************************************************************/
6479 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6480 NT_PRINTER_INFO_LEVEL *ntprinter,
6481 NEW_BUFFER *buffer, uint32 offered,
6482 uint32 *needed, uint32 *returned)
6484 JOB_INFO_2 *info = NULL;
6487 DEVICEMODE *devmode = NULL;
6489 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6492 result = WERR_NOMEM;
6496 /* this should not be a failure condition if the devmode is NULL */
6498 devmode = construct_dev_mode(snum);
6500 for (i=0; i<*returned; i++)
6501 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6504 free_a_printer(&ntprinter, 2);
6507 /* check the required size. */
6508 for (i=0; i<*returned; i++)
6509 (*needed) += spoolss_size_job_info_2(&info[i]);
6511 if (*needed > offered) {
6513 result = WERR_INSUFFICIENT_BUFFER;
6517 if (!alloc_buffer_size(buffer, *needed)) {
6519 result = WERR_INSUFFICIENT_BUFFER;
6523 /* fill the buffer with the structures */
6524 for (i=0; i<*returned; i++)
6525 smb_io_job_info_2("", buffer, &info[i], 0);
6530 free_a_printer(&ntprinter, 2);
6531 free_devmode(devmode);
6539 /****************************************************************************
6541 ****************************************************************************/
6543 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6545 POLICY_HND *handle = &q_u->handle;
6546 uint32 level = q_u->level;
6547 NEW_BUFFER *buffer = NULL;
6548 uint32 offered = q_u->offered;
6549 uint32 *needed = &r_u->needed;
6550 uint32 *returned = &r_u->returned;
6552 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6554 print_status_struct prt_status;
6555 print_queue_struct *queue=NULL;
6557 /* that's an [in out] buffer */
6558 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6559 buffer = r_u->buffer;
6561 DEBUG(4,("_spoolss_enumjobs\n"));
6566 /* lookup the printer snum and tdb entry */
6568 if (!get_printer_snum(p, handle, &snum))
6571 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6572 if ( !W_ERROR_IS_OK(wret) )
6575 *returned = print_queue_status(snum, &queue, &prt_status);
6576 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6578 if (*returned == 0) {
6585 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6588 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6593 wret = WERR_UNKNOWN_LEVEL;
6596 free_a_printer( &ntprinter, 2 );
6600 /****************************************************************************
6601 ****************************************************************************/
6603 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6608 /****************************************************************************
6609 ****************************************************************************/
6611 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6613 POLICY_HND *handle = &q_u->handle;
6614 uint32 jobid = q_u->jobid;
6615 uint32 command = q_u->command;
6617 struct current_user user;
6619 WERROR errcode = WERR_BADFUNC;
6621 if (!get_printer_snum(p, handle, &snum)) {
6625 if (!print_job_exists(snum, jobid)) {
6626 return WERR_INVALID_PRINTER_NAME;
6629 get_current_user(&user, p);
6632 case JOB_CONTROL_CANCEL:
6633 case JOB_CONTROL_DELETE:
6634 if (print_job_delete(&user, snum, jobid, &errcode)) {
6638 case JOB_CONTROL_PAUSE:
6639 if (print_job_pause(&user, snum, jobid, &errcode)) {
6643 case JOB_CONTROL_RESTART:
6644 case JOB_CONTROL_RESUME:
6645 if (print_job_resume(&user, snum, jobid, &errcode)) {
6650 return WERR_UNKNOWN_LEVEL;
6656 /****************************************************************************
6657 Enumerates all printer drivers at level 1.
6658 ****************************************************************************/
6660 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6665 fstring *list = NULL;
6667 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6668 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6672 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6674 ndrivers=get_ntdrivers(&list, architecture, version);
6675 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6681 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6682 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6683 SAFE_FREE(driver_info_1);
6687 else driver_info_1 = tdi1;
6690 for (i=0; i<ndrivers; i++) {
6692 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6693 ZERO_STRUCT(driver);
6694 status = get_a_printer_driver(&driver, 3, list[i],
6695 architecture, version);
6696 if (!W_ERROR_IS_OK(status)) {
6700 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6701 free_a_printer_driver(driver, 3);
6704 *returned+=ndrivers;
6708 /* check the required size. */
6709 for (i=0; i<*returned; i++) {
6710 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6711 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6714 if (!alloc_buffer_size(buffer, *needed)) {
6715 SAFE_FREE(driver_info_1);
6716 return WERR_INSUFFICIENT_BUFFER;
6719 /* fill the buffer with the driver structures */
6720 for (i=0; i<*returned; i++) {
6721 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6722 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6725 SAFE_FREE(driver_info_1);
6727 if (*needed > offered) {
6729 return WERR_INSUFFICIENT_BUFFER;
6735 /****************************************************************************
6736 Enumerates all printer drivers at level 2.
6737 ****************************************************************************/
6739 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6744 fstring *list = NULL;
6746 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6747 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6751 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6753 ndrivers=get_ntdrivers(&list, architecture, version);
6754 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6760 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6761 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6762 SAFE_FREE(driver_info_2);
6766 else driver_info_2 = tdi2;
6769 for (i=0; i<ndrivers; i++) {
6772 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6773 ZERO_STRUCT(driver);
6774 status = get_a_printer_driver(&driver, 3, list[i],
6775 architecture, version);
6776 if (!W_ERROR_IS_OK(status)) {
6780 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6781 free_a_printer_driver(driver, 3);
6784 *returned+=ndrivers;
6788 /* check the required size. */
6789 for (i=0; i<*returned; i++) {
6790 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6791 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6794 if (!alloc_buffer_size(buffer, *needed)) {
6795 SAFE_FREE(driver_info_2);
6796 return WERR_INSUFFICIENT_BUFFER;
6799 /* fill the buffer with the form structures */
6800 for (i=0; i<*returned; i++) {
6801 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6802 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6805 SAFE_FREE(driver_info_2);
6807 if (*needed > offered) {
6809 return WERR_INSUFFICIENT_BUFFER;
6815 /****************************************************************************
6816 Enumerates all printer drivers at level 3.
6817 ****************************************************************************/
6819 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6824 fstring *list = NULL;
6826 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6827 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6831 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6833 ndrivers=get_ntdrivers(&list, architecture, version);
6834 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6840 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6841 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6842 SAFE_FREE(driver_info_3);
6846 else driver_info_3 = tdi3;
6849 for (i=0; i<ndrivers; i++) {
6852 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6853 ZERO_STRUCT(driver);
6854 status = get_a_printer_driver(&driver, 3, list[i],
6855 architecture, version);
6856 if (!W_ERROR_IS_OK(status)) {
6860 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6861 free_a_printer_driver(driver, 3);
6864 *returned+=ndrivers;
6868 /* check the required size. */
6869 for (i=0; i<*returned; i++) {
6870 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6871 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6874 if (!alloc_buffer_size(buffer, *needed)) {
6875 SAFE_FREE(driver_info_3);
6876 return WERR_INSUFFICIENT_BUFFER;
6879 /* fill the buffer with the driver structures */
6880 for (i=0; i<*returned; i++) {
6881 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6882 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6885 for (i=0; i<*returned; i++)
6886 SAFE_FREE(driver_info_3[i].dependentfiles);
6888 SAFE_FREE(driver_info_3);
6890 if (*needed > offered) {
6892 return WERR_INSUFFICIENT_BUFFER;
6898 /****************************************************************************
6899 Enumerates all printer drivers.
6900 ****************************************************************************/
6902 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6904 uint32 level = q_u->level;
6905 NEW_BUFFER *buffer = NULL;
6906 uint32 offered = q_u->offered;
6907 uint32 *needed = &r_u->needed;
6908 uint32 *returned = &r_u->returned;
6910 fstring *list = NULL;
6912 fstring architecture;
6914 /* that's an [in out] buffer */
6915 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6916 buffer = r_u->buffer;
6918 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6922 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6923 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6925 if ( !is_myname_or_ipaddr( servername ) )
6926 return WERR_UNKNOWN_PRINTER_DRIVER;
6930 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6932 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6934 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6938 return WERR_UNKNOWN_LEVEL;
6942 /****************************************************************************
6943 ****************************************************************************/
6945 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6947 form->flag=list->flag;
6948 init_unistr(&form->name, list->name);
6949 form->width=list->width;
6950 form->length=list->length;
6951 form->left=list->left;
6952 form->top=list->top;
6953 form->right=list->right;
6954 form->bottom=list->bottom;
6957 /****************************************************************************
6958 ****************************************************************************/
6960 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6962 uint32 level = q_u->level;
6963 NEW_BUFFER *buffer = NULL;
6964 uint32 offered = q_u->offered;
6965 uint32 *needed = &r_u->needed;
6966 uint32 *numofforms = &r_u->numofforms;
6967 uint32 numbuiltinforms;
6969 nt_forms_struct *list=NULL;
6970 nt_forms_struct *builtinlist=NULL;
6975 /* that's an [in out] buffer */
6976 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6977 buffer = r_u->buffer;
6979 DEBUG(4,("_spoolss_enumforms\n"));
6980 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6981 DEBUGADD(5,("Info level [%d]\n", level));
6983 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6984 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6985 *numofforms = get_ntforms(&list);
6986 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6987 *numofforms += numbuiltinforms;
6989 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6993 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6998 /* construct the list of form structures */
6999 for (i=0; i<numbuiltinforms; i++) {
7000 DEBUGADD(6,("Filling form number [%d]\n",i));
7001 fill_form_1(&forms_1[i], &builtinlist[i]);
7004 SAFE_FREE(builtinlist);
7006 for (; i<*numofforms; i++) {
7007 DEBUGADD(6,("Filling form number [%d]\n",i));
7008 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7013 /* check the required size. */
7014 for (i=0; i<numbuiltinforms; i++) {
7015 DEBUGADD(6,("adding form [%d]'s size\n",i));
7016 buffer_size += spoolss_size_form_1(&forms_1[i]);
7018 for (; i<*numofforms; i++) {
7019 DEBUGADD(6,("adding form [%d]'s size\n",i));
7020 buffer_size += spoolss_size_form_1(&forms_1[i]);
7023 *needed=buffer_size;
7025 if (!alloc_buffer_size(buffer, buffer_size)){
7027 return WERR_INSUFFICIENT_BUFFER;
7030 /* fill the buffer with the form structures */
7031 for (i=0; i<numbuiltinforms; i++) {
7032 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7033 smb_io_form_1("", buffer, &forms_1[i], 0);
7035 for (; i<*numofforms; i++) {
7036 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7037 smb_io_form_1("", buffer, &forms_1[i], 0);
7042 if (*needed > offered) {
7044 return WERR_INSUFFICIENT_BUFFER;
7051 SAFE_FREE(builtinlist);
7052 return WERR_UNKNOWN_LEVEL;
7057 /****************************************************************************
7058 ****************************************************************************/
7060 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7062 uint32 level = q_u->level;
7063 UNISTR2 *uni_formname = &q_u->formname;
7064 NEW_BUFFER *buffer = NULL;
7065 uint32 offered = q_u->offered;
7066 uint32 *needed = &r_u->needed;
7068 nt_forms_struct *list=NULL;
7069 nt_forms_struct builtin_form;
7074 int numofforms=0, i=0;
7076 /* that's an [in out] buffer */
7077 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7078 buffer = r_u->buffer;
7080 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7082 DEBUG(4,("_spoolss_getform\n"));
7083 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7084 DEBUGADD(5,("Info level [%d]\n", level));
7086 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7087 if (!foundBuiltin) {
7088 numofforms = get_ntforms(&list);
7089 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7091 if (numofforms == 0)
7098 fill_form_1(&form_1, &builtin_form);
7101 /* Check if the requested name is in the list of form structures */
7102 for (i=0; i<numofforms; i++) {
7104 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7106 if (strequal(form_name, list[i].name)) {
7107 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7108 fill_form_1(&form_1, &list[i]);
7114 if (i == numofforms) {
7118 /* check the required size. */
7120 *needed=spoolss_size_form_1(&form_1);
7122 if (!alloc_buffer_size(buffer, buffer_size)){
7123 return WERR_INSUFFICIENT_BUFFER;
7126 if (*needed > offered) {
7127 return WERR_INSUFFICIENT_BUFFER;
7130 /* fill the buffer with the form structures */
7131 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7132 smb_io_form_1("", buffer, &form_1, 0);
7138 return WERR_UNKNOWN_LEVEL;
7142 /****************************************************************************
7143 ****************************************************************************/
7145 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7147 init_unistr(&port->port_name, name);
7150 /****************************************************************************
7151 ****************************************************************************/
7153 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7155 init_unistr(&port->port_name, name);
7156 init_unistr(&port->monitor_name, "Local Monitor");
7157 init_unistr(&port->description, "Local Port");
7158 port->port_type=PORT_TYPE_WRITE;
7162 /****************************************************************************
7164 ****************************************************************************/
7166 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7168 PORT_INFO_1 *ports=NULL;
7171 if (*lp_enumports_cmd()) {
7172 char *cmd = lp_enumports_cmd();
7179 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7181 DEBUG(10,("Running [%s]\n", command));
7182 ret = smbrun(command, &fd);
7183 DEBUG(10,("Returned [%d]\n", ret));
7187 /* Is this the best error to return here? */
7188 return WERR_ACCESS_DENIED;
7192 qlines = fd_lines_load(fd, &numlines);
7193 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7197 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7198 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7199 dos_errstr(WERR_NOMEM)));
7200 file_lines_free(qlines);
7204 for (i=0; i<numlines; i++) {
7205 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7206 fill_port_1(&ports[i], qlines[i]);
7209 file_lines_free(qlines);
7212 *returned = numlines;
7215 *returned = 1; /* Sole Samba port returned. */
7217 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7220 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7222 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7225 /* check the required size. */
7226 for (i=0; i<*returned; i++) {
7227 DEBUGADD(6,("adding port [%d]'s size\n", i));
7228 *needed += spoolss_size_port_info_1(&ports[i]);
7231 if (!alloc_buffer_size(buffer, *needed)) {
7233 return WERR_INSUFFICIENT_BUFFER;
7236 /* fill the buffer with the ports structures */
7237 for (i=0; i<*returned; i++) {
7238 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7239 smb_io_port_1("", buffer, &ports[i], 0);
7244 if (*needed > offered) {
7246 return WERR_INSUFFICIENT_BUFFER;
7252 /****************************************************************************
7254 ****************************************************************************/
7256 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7258 PORT_INFO_2 *ports=NULL;
7261 if (*lp_enumports_cmd()) {
7262 char *cmd = lp_enumports_cmd();
7271 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7272 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7274 path = lp_lockdir();
7276 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7277 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7280 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7281 ret = smbrun(command, &fd);
7282 DEBUGADD(10,("returned [%d]\n", ret));
7286 /* Is this the best error to return here? */
7287 return WERR_ACCESS_DENIED;
7291 qlines = fd_lines_load(fd, &numlines);
7292 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7296 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7297 file_lines_free(qlines);
7301 for (i=0; i<numlines; i++) {
7302 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7303 fill_port_2(&(ports[i]), qlines[i]);
7306 file_lines_free(qlines);
7309 *returned = numlines;
7315 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7318 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7320 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7323 /* check the required size. */
7324 for (i=0; i<*returned; i++) {
7325 DEBUGADD(6,("adding port [%d]'s size\n", i));
7326 *needed += spoolss_size_port_info_2(&ports[i]);
7329 if (!alloc_buffer_size(buffer, *needed)) {
7331 return WERR_INSUFFICIENT_BUFFER;
7334 /* fill the buffer with the ports structures */
7335 for (i=0; i<*returned; i++) {
7336 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7337 smb_io_port_2("", buffer, &ports[i], 0);
7342 if (*needed > offered) {
7344 return WERR_INSUFFICIENT_BUFFER;
7350 /****************************************************************************
7352 ****************************************************************************/
7354 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7356 uint32 level = q_u->level;
7357 NEW_BUFFER *buffer = NULL;
7358 uint32 offered = q_u->offered;
7359 uint32 *needed = &r_u->needed;
7360 uint32 *returned = &r_u->returned;
7362 /* that's an [in out] buffer */
7363 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7364 buffer = r_u->buffer;
7366 DEBUG(4,("_spoolss_enumports\n"));
7373 return enumports_level_1(buffer, offered, needed, returned);
7375 return enumports_level_2(buffer, offered, needed, returned);
7377 return WERR_UNKNOWN_LEVEL;
7381 /****************************************************************************
7382 ****************************************************************************/
7384 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7385 const SPOOL_PRINTER_INFO_LEVEL *info,
7386 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7387 uint32 user_switch, const SPOOL_USER_CTR *user,
7390 NT_PRINTER_INFO_LEVEL *printer = NULL;
7393 WERROR err = WERR_OK;
7395 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7396 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7400 ZERO_STRUCTP(printer);
7402 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7403 if (!convert_printer_info(info, printer, 2)) {
7404 free_a_printer(&printer, 2);
7408 /* check to see if the printer already exists */
7410 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7411 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7412 printer->info_2->sharename));
7413 free_a_printer(&printer, 2);
7414 return WERR_PRINTER_ALREADY_EXISTS;
7417 /* FIXME!!! smbd should check to see if the driver is installed before
7418 trying to add a printer like this --jerry */
7420 if (*lp_addprinter_cmd() ) {
7421 if ( !add_printer_hook(printer) ) {
7422 free_a_printer(&printer,2);
7423 return WERR_ACCESS_DENIED;
7427 /* use our primary netbios name since get_a_printer() will convert
7428 it to what the client expects on a case by case basis */
7430 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7431 printer->info_2->sharename);
7434 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7435 free_a_printer(&printer,2);
7436 return WERR_ACCESS_DENIED;
7439 /* you must be a printer admin to add a new printer */
7440 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7441 free_a_printer(&printer,2);
7442 return WERR_ACCESS_DENIED;
7446 * Do sanity check on the requested changes for Samba.
7449 if (!check_printer_ok(printer->info_2, snum)) {
7450 free_a_printer(&printer,2);
7451 return WERR_INVALID_PARAM;
7455 * When a printer is created, the drivername bound to the printer is used
7456 * to lookup previously saved driver initialization info, which is then
7457 * bound to the new printer, simulating what happens in the Windows arch.
7462 set_driver_init(printer, 2);
7466 /* A valid devmode was included, convert and link it
7468 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7470 if (!convert_devicemode(printer->info_2->printername, devmode,
7471 &printer->info_2->devmode))
7475 /* write the ASCII on disk */
7476 err = mod_a_printer(printer, 2);
7477 if (!W_ERROR_IS_OK(err)) {
7478 free_a_printer(&printer,2);
7482 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7483 /* Handle open failed - remove addition. */
7484 del_a_printer(printer->info_2->sharename);
7485 free_a_printer(&printer,2);
7486 return WERR_ACCESS_DENIED;
7489 update_c_setprinter(False);
7490 free_a_printer(&printer,2);
7495 /****************************************************************************
7496 ****************************************************************************/
7498 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7500 UNISTR2 *uni_srv_name = &q_u->server_name;
7501 uint32 level = q_u->level;
7502 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7503 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7504 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7505 uint32 user_switch = q_u->user_switch;
7506 SPOOL_USER_CTR *user = &q_u->user_ctr;
7507 POLICY_HND *handle = &r_u->handle;
7511 /* we don't handle yet */
7512 /* but I know what to do ... */
7513 return WERR_UNKNOWN_LEVEL;
7515 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7517 user_switch, user, handle);
7519 return WERR_UNKNOWN_LEVEL;
7523 /****************************************************************************
7524 ****************************************************************************/
7526 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7528 uint32 level = q_u->level;
7529 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7530 WERROR err = WERR_OK;
7531 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7532 struct current_user user;
7533 fstring driver_name;
7536 ZERO_STRUCT(driver);
7538 get_current_user(&user, p);
7540 if (!convert_printer_driver_info(info, &driver, level)) {
7545 DEBUG(5,("Cleaning driver's information\n"));
7546 err = clean_up_driver_struct(driver, level, &user);
7547 if (!W_ERROR_IS_OK(err))
7550 DEBUG(5,("Moving driver to final destination\n"));
7551 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7552 if (W_ERROR_IS_OK(err))
7553 err = WERR_ACCESS_DENIED;
7557 if (add_a_printer_driver(driver, level)!=0) {
7558 err = WERR_ACCESS_DENIED;
7562 /* BEGIN_ADMIN_LOG */
7565 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7566 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7567 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7570 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7571 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7572 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7578 * I think this is where he DrvUpgradePrinter() hook would be
7579 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7580 * server. Right now, we just need to send ourselves a message
7581 * to update each printer bound to this driver. --jerry
7584 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7585 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7590 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7591 * decide if the driver init data should be deleted. The rules are:
7592 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7593 * 2) delete init data only if there is no 2k/Xp driver
7594 * 3) always delete init data
7595 * The generalized rule is always use init data from the highest order driver.
7596 * It is necessary to follow the driver install by an initialization step to
7597 * finish off this process.
7600 version = driver.info_3->cversion;
7601 else if (level == 6)
7602 version = driver.info_6->version;
7607 * 9x printer driver - never delete init data
7610 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7615 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7616 * there is no 2k/Xp driver init data for this driver name.
7620 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7622 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7624 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7626 if (!del_driver_init(driver_name))
7627 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7630 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7632 free_a_printer_driver(driver1,3);
7633 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7640 * 2k or Xp printer driver - always delete init data
7643 if (!del_driver_init(driver_name))
7644 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7648 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7654 free_a_printer_driver(driver, level);
7658 /********************************************************************
7659 * spoolss_addprinterdriverex
7660 ********************************************************************/
7662 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7664 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7665 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7668 * we only support the semantics of AddPrinterDriver()
7669 * i.e. only copy files that are newer than existing ones
7672 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7673 return WERR_ACCESS_DENIED;
7675 ZERO_STRUCT(q_u_local);
7676 ZERO_STRUCT(r_u_local);
7678 /* just pass the information off to _spoolss_addprinterdriver() */
7679 q_u_local.server_name_ptr = q_u->server_name_ptr;
7680 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7681 q_u_local.level = q_u->level;
7682 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7684 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7687 /****************************************************************************
7688 ****************************************************************************/
7690 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7692 init_unistr(&info->name, name);
7695 /****************************************************************************
7696 ****************************************************************************/
7698 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7704 const char *short_archi;
7705 DRIVER_DIRECTORY_1 *info=NULL;
7707 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7708 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7710 /* check for beginning double '\'s and that the server
7713 pservername = servername;
7714 if ( *pservername == '\\' && strlen(servername)>2 ) {
7718 if ( !is_myname_or_ipaddr( pservername ) )
7719 return WERR_INVALID_PARAM;
7721 if (!(short_archi = get_short_archi(long_archi)))
7722 return WERR_INVALID_ENVIRONMENT;
7724 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7727 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7729 DEBUG(4,("printer driver directory: [%s]\n", path));
7731 fill_driverdir_1(info, path);
7733 *needed += spoolss_size_driverdir_info_1(info);
7735 if (!alloc_buffer_size(buffer, *needed)) {
7737 return WERR_INSUFFICIENT_BUFFER;
7740 smb_io_driverdir_1("", buffer, info, 0);
7744 if (*needed > offered)
7745 return WERR_INSUFFICIENT_BUFFER;
7750 /****************************************************************************
7751 ****************************************************************************/
7753 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7755 UNISTR2 *name = &q_u->name;
7756 UNISTR2 *uni_environment = &q_u->environment;
7757 uint32 level = q_u->level;
7758 NEW_BUFFER *buffer = NULL;
7759 uint32 offered = q_u->offered;
7760 uint32 *needed = &r_u->needed;
7762 /* that's an [in out] buffer */
7763 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7764 buffer = r_u->buffer;
7766 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7772 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7774 return WERR_UNKNOWN_LEVEL;
7778 /****************************************************************************
7779 ****************************************************************************/
7781 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7783 POLICY_HND *handle = &q_u->handle;
7784 uint32 idx = q_u->index;
7785 uint32 in_value_len = q_u->valuesize;
7786 uint32 in_data_len = q_u->datasize;
7787 uint32 *out_max_value_len = &r_u->valuesize;
7788 uint16 **out_value = &r_u->value;
7789 uint32 *out_value_len = &r_u->realvaluesize;
7790 uint32 *out_type = &r_u->type;
7791 uint32 *out_max_data_len = &r_u->datasize;
7792 uint8 **data_out = &r_u->data;
7793 uint32 *out_data_len = &r_u->realdatasize;
7795 NT_PRINTER_INFO_LEVEL *printer = NULL;
7797 uint32 biggest_valuesize;
7798 uint32 biggest_datasize;
7800 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7803 REGISTRY_VALUE *val = NULL;
7804 NT_PRINTER_DATA *p_data;
7805 int i, key_index, num_values;
7808 ZERO_STRUCT( printer );
7812 *out_max_data_len = 0;
7816 DEBUG(5,("spoolss_enumprinterdata\n"));
7819 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7823 if (!get_printer_snum(p,handle, &snum))
7826 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7827 if (!W_ERROR_IS_OK(result))
7830 p_data = &printer->info_2->data;
7831 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7836 * The NT machine wants to know the biggest size of value and data
7838 * cf: MSDN EnumPrinterData remark section
7841 if ( !in_value_len && !in_data_len && (key_index != -1) )
7843 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7845 biggest_valuesize = 0;
7846 biggest_datasize = 0;
7848 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7850 for ( i=0; i<num_values; i++ )
7852 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7854 name_length = strlen(val->valuename);
7855 if ( strlen(val->valuename) > biggest_valuesize )
7856 biggest_valuesize = name_length;
7858 if ( val->size > biggest_datasize )
7859 biggest_datasize = val->size;
7861 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7865 /* the value is an UNICODE string but real_value_size is the length
7866 in bytes including the trailing 0 */
7868 *out_value_len = 2 * (1+biggest_valuesize);
7869 *out_data_len = biggest_datasize;
7871 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7877 * the value len is wrong in NT sp3
7878 * that's the number of bytes not the number of unicode chars
7881 if ( key_index != -1 )
7882 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7887 /* out_value should default to "" or else NT4 has
7888 problems unmarshalling the response */
7890 *out_max_value_len=(in_value_len/sizeof(uint16));
7892 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7894 result = WERR_NOMEM;
7898 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7900 /* the data is counted in bytes */
7902 *out_max_data_len = in_data_len;
7903 *out_data_len = in_data_len;
7905 /* only allocate when given a non-zero data_len */
7907 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7909 result = WERR_NOMEM;
7913 result = WERR_NO_MORE_ITEMS;
7919 * - counted in bytes in the request
7920 * - counted in UNICODE chars in the max reply
7921 * - counted in bytes in the real size
7923 * take a pause *before* coding not *during* coding
7927 *out_max_value_len=(in_value_len/sizeof(uint16));
7928 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7930 result = WERR_NOMEM;
7934 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7938 *out_type = regval_type( val );
7940 /* data - counted in bytes */
7942 *out_max_data_len = in_data_len;
7943 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7945 result = WERR_NOMEM;
7948 data_len = (size_t)regval_size(val);
7949 memcpy( *data_out, regval_data_p(val), data_len );
7950 *out_data_len = data_len;
7954 free_a_printer(&printer, 2);
7958 /****************************************************************************
7959 ****************************************************************************/
7961 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7963 POLICY_HND *handle = &q_u->handle;
7964 UNISTR2 *value = &q_u->value;
7965 uint32 type = q_u->type;
7966 uint8 *data = q_u->data;
7967 uint32 real_len = q_u->real_len;
7969 NT_PRINTER_INFO_LEVEL *printer = NULL;
7971 WERROR status = WERR_OK;
7972 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7975 DEBUG(5,("spoolss_setprinterdata\n"));
7978 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7982 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7983 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7984 return WERR_INVALID_PARAM;
7987 if (!get_printer_snum(p,handle, &snum))
7991 * Access check : NT returns "access denied" if you make a
7992 * SetPrinterData call without the necessary privildge.
7993 * we were originally returning OK if nothing changed
7994 * which made Win2k issue **a lot** of SetPrinterData
7995 * when connecting to a printer --jerry
7998 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8000 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8001 status = WERR_ACCESS_DENIED;
8005 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8006 if (!W_ERROR_IS_OK(status))
8009 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8012 * When client side code sets a magic printer data key, detect it and save
8013 * the current printer data and the magic key's data (its the DEVMODE) for
8014 * future printer/driver initializations.
8016 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8018 /* Set devmode and printer initialization info */
8019 status = save_driver_init( printer, 2, data, real_len );
8021 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8025 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8026 type, data, real_len );
8027 if ( W_ERROR_IS_OK(status) )
8028 status = mod_a_printer(printer, 2);
8032 free_a_printer(&printer, 2);
8037 /****************************************************************************
8038 ****************************************************************************/
8040 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8042 POLICY_HND *handle = &q_u->handle;
8043 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8046 DEBUG(5,("_spoolss_resetprinter\n"));
8049 * All we do is to check to see if the handle and queue is valid.
8050 * This call really doesn't mean anything to us because we only
8051 * support RAW printing. --jerry
8055 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8059 if (!get_printer_snum(p,handle, &snum))
8063 /* blindly return success */
8068 /****************************************************************************
8069 ****************************************************************************/
8071 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8073 POLICY_HND *handle = &q_u->handle;
8074 UNISTR2 *value = &q_u->valuename;
8076 NT_PRINTER_INFO_LEVEL *printer = NULL;
8078 WERROR status = WERR_OK;
8079 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8082 DEBUG(5,("spoolss_deleteprinterdata\n"));
8085 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8089 if (!get_printer_snum(p, handle, &snum))
8092 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8093 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8094 return WERR_ACCESS_DENIED;
8097 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8098 if (!W_ERROR_IS_OK(status))
8101 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8103 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8105 if ( W_ERROR_IS_OK(status) )
8106 mod_a_printer( printer, 2 );
8108 free_a_printer(&printer, 2);
8113 /****************************************************************************
8114 ****************************************************************************/
8116 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8118 POLICY_HND *handle = &q_u->handle;
8119 FORM *form = &q_u->form;
8120 nt_forms_struct tmpForm;
8122 WERROR status = WERR_OK;
8123 NT_PRINTER_INFO_LEVEL *printer = NULL;
8126 nt_forms_struct *list=NULL;
8127 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8129 DEBUG(5,("spoolss_addform\n"));
8132 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8137 /* forms can be added on printer of on the print server handle */
8139 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8141 if (!get_printer_snum(p,handle, &snum))
8144 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8145 if (!W_ERROR_IS_OK(status))
8149 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8150 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8151 status = WERR_ACCESS_DENIED;
8155 /* can't add if builtin */
8157 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8158 status = WERR_ALREADY_EXISTS;
8162 count = get_ntforms(&list);
8164 if(!add_a_form(&list, form, &count)) {
8165 status = WERR_NOMEM;
8169 write_ntforms(&list, count);
8172 * ChangeID must always be set if this is a printer
8175 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8176 status = mod_a_printer(printer, 2);
8180 free_a_printer(&printer, 2);
8186 /****************************************************************************
8187 ****************************************************************************/
8189 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8191 POLICY_HND *handle = &q_u->handle;
8192 UNISTR2 *form_name = &q_u->name;
8193 nt_forms_struct tmpForm;
8195 nt_forms_struct *list=NULL;
8196 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8198 WERROR status = WERR_OK;
8199 NT_PRINTER_INFO_LEVEL *printer = NULL;
8201 DEBUG(5,("spoolss_deleteform\n"));
8204 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8208 /* forms can be deleted on printer of on the print server handle */
8210 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8212 if (!get_printer_snum(p,handle, &snum))
8215 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8216 if (!W_ERROR_IS_OK(status))
8220 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8221 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8222 status = WERR_ACCESS_DENIED;
8226 /* can't delete if builtin */
8228 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8229 status = WERR_INVALID_PARAM;
8233 count = get_ntforms(&list);
8235 if ( !delete_a_form(&list, form_name, &count, &status ))
8239 * ChangeID must always be set if this is a printer
8242 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8243 status = mod_a_printer(printer, 2);
8247 free_a_printer(&printer, 2);
8253 /****************************************************************************
8254 ****************************************************************************/
8256 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8258 POLICY_HND *handle = &q_u->handle;
8259 FORM *form = &q_u->form;
8260 nt_forms_struct tmpForm;
8262 WERROR status = WERR_OK;
8263 NT_PRINTER_INFO_LEVEL *printer = NULL;
8266 nt_forms_struct *list=NULL;
8267 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8269 DEBUG(5,("spoolss_setform\n"));
8272 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8276 /* forms can be modified on printer of on the print server handle */
8278 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8280 if (!get_printer_snum(p,handle, &snum))
8283 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8284 if (!W_ERROR_IS_OK(status))
8288 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8289 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8290 status = WERR_ACCESS_DENIED;
8294 /* can't set if builtin */
8295 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8296 status = WERR_INVALID_PARAM;
8300 count = get_ntforms(&list);
8301 update_a_form(&list, form, count);
8302 write_ntforms(&list, count);
8305 * ChangeID must always be set if this is a printer
8308 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8309 status = mod_a_printer(printer, 2);
8314 free_a_printer(&printer, 2);
8320 /****************************************************************************
8321 enumprintprocessors level 1.
8322 ****************************************************************************/
8324 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8326 PRINTPROCESSOR_1 *info_1=NULL;
8328 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8333 init_unistr(&info_1->name, "winprint");
8335 *needed += spoolss_size_printprocessor_info_1(info_1);
8337 if (!alloc_buffer_size(buffer, *needed))
8338 return WERR_INSUFFICIENT_BUFFER;
8340 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8344 if (*needed > offered) {
8346 return WERR_INSUFFICIENT_BUFFER;
8352 /****************************************************************************
8353 ****************************************************************************/
8355 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8357 uint32 level = q_u->level;
8358 NEW_BUFFER *buffer = NULL;
8359 uint32 offered = q_u->offered;
8360 uint32 *needed = &r_u->needed;
8361 uint32 *returned = &r_u->returned;
8363 /* that's an [in out] buffer */
8364 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8365 buffer = r_u->buffer;
8367 DEBUG(5,("spoolss_enumprintprocessors\n"));
8370 * Enumerate the print processors ...
8372 * Just reply with "winprint", to keep NT happy
8373 * and I can use my nice printer checker.
8381 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8383 return WERR_UNKNOWN_LEVEL;
8387 /****************************************************************************
8388 enumprintprocdatatypes level 1.
8389 ****************************************************************************/
8391 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8393 PRINTPROCDATATYPE_1 *info_1=NULL;
8395 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8400 init_unistr(&info_1->name, "RAW");
8402 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8404 if (!alloc_buffer_size(buffer, *needed))
8405 return WERR_INSUFFICIENT_BUFFER;
8407 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8411 if (*needed > offered) {
8413 return WERR_INSUFFICIENT_BUFFER;
8419 /****************************************************************************
8420 ****************************************************************************/
8422 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8424 uint32 level = q_u->level;
8425 NEW_BUFFER *buffer = NULL;
8426 uint32 offered = q_u->offered;
8427 uint32 *needed = &r_u->needed;
8428 uint32 *returned = &r_u->returned;
8430 /* that's an [in out] buffer */
8431 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8432 buffer = r_u->buffer;
8434 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8441 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8443 return WERR_UNKNOWN_LEVEL;
8447 /****************************************************************************
8448 enumprintmonitors level 1.
8449 ****************************************************************************/
8451 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8453 PRINTMONITOR_1 *info_1=NULL;
8455 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8460 init_unistr(&info_1->name, "Local Port");
8462 *needed += spoolss_size_printmonitor_info_1(info_1);
8464 if (!alloc_buffer_size(buffer, *needed))
8465 return WERR_INSUFFICIENT_BUFFER;
8467 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8471 if (*needed > offered) {
8473 return WERR_INSUFFICIENT_BUFFER;
8479 /****************************************************************************
8480 enumprintmonitors level 2.
8481 ****************************************************************************/
8483 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8485 PRINTMONITOR_2 *info_2=NULL;
8487 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8492 init_unistr(&info_2->name, "Local Port");
8493 init_unistr(&info_2->environment, "Windows NT X86");
8494 init_unistr(&info_2->dll_name, "localmon.dll");
8496 *needed += spoolss_size_printmonitor_info_2(info_2);
8498 if (!alloc_buffer_size(buffer, *needed))
8499 return WERR_INSUFFICIENT_BUFFER;
8501 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8505 if (*needed > offered) {
8507 return WERR_INSUFFICIENT_BUFFER;
8513 /****************************************************************************
8514 ****************************************************************************/
8516 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8518 uint32 level = q_u->level;
8519 NEW_BUFFER *buffer = NULL;
8520 uint32 offered = q_u->offered;
8521 uint32 *needed = &r_u->needed;
8522 uint32 *returned = &r_u->returned;
8524 /* that's an [in out] buffer */
8525 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8526 buffer = r_u->buffer;
8528 DEBUG(5,("spoolss_enumprintmonitors\n"));
8531 * Enumerate the print monitors ...
8533 * Just reply with "Local Port", to keep NT happy
8534 * and I can use my nice printer checker.
8542 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8544 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8546 return WERR_UNKNOWN_LEVEL;
8550 /****************************************************************************
8551 ****************************************************************************/
8553 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8554 NT_PRINTER_INFO_LEVEL *ntprinter,
8555 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8560 JOB_INFO_1 *info_1=NULL;
8562 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8564 if (info_1 == NULL) {
8568 for (i=0; i<count && found==False; i++) {
8569 if ((*queue)[i].job==(int)jobid)
8575 /* NT treats not found as bad param... yet another bad choice */
8576 return WERR_INVALID_PARAM;
8579 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8581 *needed += spoolss_size_job_info_1(info_1);
8583 if (!alloc_buffer_size(buffer, *needed)) {
8585 return WERR_INSUFFICIENT_BUFFER;
8588 smb_io_job_info_1("", buffer, info_1, 0);
8592 if (*needed > offered)
8593 return WERR_INSUFFICIENT_BUFFER;
8598 /****************************************************************************
8599 ****************************************************************************/
8601 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8602 NT_PRINTER_INFO_LEVEL *ntprinter,
8603 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8610 DEVICEMODE *devmode = NULL;
8611 NT_DEVICEMODE *nt_devmode = NULL;
8613 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8615 ZERO_STRUCTP(info_2);
8617 if (info_2 == NULL) {
8622 for ( i=0; i<count && found==False; i++ )
8624 if ((*queue)[i].job == (int)jobid)
8630 /* NT treats not found as bad param... yet another bad
8632 ret = WERR_INVALID_PARAM;
8637 * if the print job does not have a DEVMODE associated with it,
8638 * just use the one for the printer. A NULL devicemode is not
8639 * a failure condition
8642 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8643 devmode = construct_dev_mode(snum);
8645 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8646 ZERO_STRUCTP( devmode );
8647 convert_nt_devicemode( devmode, nt_devmode );
8651 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8653 *needed += spoolss_size_job_info_2(info_2);
8655 if (!alloc_buffer_size(buffer, *needed)) {
8656 ret = WERR_INSUFFICIENT_BUFFER;
8660 smb_io_job_info_2("", buffer, info_2, 0);
8662 if (*needed > offered) {
8663 ret = WERR_INSUFFICIENT_BUFFER;
8670 /* Cleanup allocated memory */
8672 free_job_info_2(info_2); /* Also frees devmode */
8674 free_a_printer(&ntprinter, 2);
8679 /****************************************************************************
8680 ****************************************************************************/
8682 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8684 POLICY_HND *handle = &q_u->handle;
8685 uint32 jobid = q_u->jobid;
8686 uint32 level = q_u->level;
8687 NEW_BUFFER *buffer = NULL;
8688 uint32 offered = q_u->offered;
8689 uint32 *needed = &r_u->needed;
8690 WERROR wstatus = WERR_OK;
8691 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8694 print_queue_struct *queue = NULL;
8695 print_status_struct prt_status;
8697 /* that's an [in out] buffer */
8698 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8699 buffer = r_u->buffer;
8701 DEBUG(5,("spoolss_getjob\n"));
8705 if (!get_printer_snum(p, handle, &snum))
8708 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8709 if ( !W_ERROR_IS_OK(wstatus) )
8712 count = print_queue_status(snum, &queue, &prt_status);
8714 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8715 count, prt_status.status, prt_status.message));
8719 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8720 buffer, offered, needed);
8723 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8724 buffer, offered, needed);
8727 wstatus = WERR_UNKNOWN_LEVEL;
8732 free_a_printer( &ntprinter, 2 );
8737 /********************************************************************
8738 spoolss_getprinterdataex
8740 From MSDN documentation of GetPrinterDataEx: pass request
8741 to GetPrinterData if key is "PrinterDriverData".
8742 ********************************************************************/
8744 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8746 POLICY_HND *handle = &q_u->handle;
8747 uint32 in_size = q_u->size;
8748 uint32 *type = &r_u->type;
8749 uint32 *out_size = &r_u->size;
8750 uint8 **data = &r_u->data;
8751 uint32 *needed = &r_u->needed;
8752 fstring keyname, valuename;
8754 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8756 NT_PRINTER_INFO_LEVEL *printer = NULL;
8758 WERROR status = WERR_OK;
8760 DEBUG(4,("_spoolss_getprinterdataex\n"));
8762 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8763 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8765 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8766 keyname, valuename));
8768 /* in case of problem, return some default values */
8772 *out_size = in_size;
8775 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8776 status = WERR_BADFID;
8780 /* Is the handle to a printer or to the server? */
8782 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8783 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8784 status = WERR_INVALID_PARAM;
8788 if ( !get_printer_snum(p,handle, &snum) )
8791 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8792 if ( !W_ERROR_IS_OK(status) )
8795 /* check to see if the keyname is valid */
8796 if ( !strlen(keyname) ) {
8797 status = WERR_INVALID_PARAM;
8801 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8802 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8803 free_a_printer( &printer, 2 );
8804 status = WERR_BADFILE;
8808 /* When given a new keyname, we should just create it */
8810 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8812 if (*needed > *out_size)
8813 status = WERR_MORE_DATA;
8816 if ( !W_ERROR_IS_OK(status) )
8818 DEBUG(5, ("error: allocating %d\n", *out_size));
8820 /* reply this param doesn't exist */
8824 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8825 status = WERR_NOMEM;
8835 free_a_printer( &printer, 2 );
8840 /********************************************************************
8841 * spoolss_setprinterdataex
8842 ********************************************************************/
8844 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8846 POLICY_HND *handle = &q_u->handle;
8847 uint32 type = q_u->type;
8848 uint8 *data = q_u->data;
8849 uint32 real_len = q_u->real_len;
8851 NT_PRINTER_INFO_LEVEL *printer = NULL;
8853 WERROR status = WERR_OK;
8854 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8859 DEBUG(4,("_spoolss_setprinterdataex\n"));
8861 /* From MSDN documentation of SetPrinterDataEx: pass request to
8862 SetPrinterData if key is "PrinterDriverData" */
8865 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8869 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8870 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8871 return WERR_INVALID_PARAM;
8874 if ( !get_printer_snum(p,handle, &snum) )
8878 * Access check : NT returns "access denied" if you make a
8879 * SetPrinterData call without the necessary privildge.
8880 * we were originally returning OK if nothing changed
8881 * which made Win2k issue **a lot** of SetPrinterData
8882 * when connecting to a printer --jerry
8885 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8887 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8888 return WERR_ACCESS_DENIED;
8891 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8892 if (!W_ERROR_IS_OK(status))
8895 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8896 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8898 /* check for OID in valuename */
8900 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8906 /* save the registry data */
8908 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8910 if ( W_ERROR_IS_OK(status) )
8912 /* save the OID if one was specified */
8914 fstrcat( keyname, "\\" );
8915 fstrcat( keyname, SPOOL_OID_KEY );
8918 * I'm not checking the status here on purpose. Don't know
8919 * if this is right, but I'm returning the status from the
8920 * previous set_printer_dataex() call. I have no idea if
8921 * this is right. --jerry
8924 set_printer_dataex( printer, keyname, valuename,
8925 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8928 status = mod_a_printer(printer, 2);
8931 free_a_printer(&printer, 2);
8937 /********************************************************************
8938 * spoolss_deleteprinterdataex
8939 ********************************************************************/
8941 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8943 POLICY_HND *handle = &q_u->handle;
8944 UNISTR2 *value = &q_u->valuename;
8945 UNISTR2 *key = &q_u->keyname;
8947 NT_PRINTER_INFO_LEVEL *printer = NULL;
8949 WERROR status = WERR_OK;
8950 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8951 pstring valuename, keyname;
8953 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8956 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8960 if (!get_printer_snum(p, handle, &snum))
8963 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8964 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8965 return WERR_ACCESS_DENIED;
8968 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8969 if (!W_ERROR_IS_OK(status))
8972 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8973 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8975 status = delete_printer_dataex( printer, keyname, valuename );
8977 if ( W_ERROR_IS_OK(status) )
8978 mod_a_printer( printer, 2 );
8980 free_a_printer(&printer, 2);
8985 /********************************************************************
8986 * spoolss_enumprinterkey
8987 ********************************************************************/
8990 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8993 fstring *keynames = NULL;
8994 uint16 *enumkeys = NULL;
8997 POLICY_HND *handle = &q_u->handle;
8998 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8999 NT_PRINTER_DATA *data;
9000 NT_PRINTER_INFO_LEVEL *printer = NULL;
9002 WERROR status = WERR_BADFILE;
9005 DEBUG(4,("_spoolss_enumprinterkey\n"));
9008 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9012 if ( !get_printer_snum(p,handle, &snum) )
9015 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9016 if (!W_ERROR_IS_OK(status))
9019 /* get the list of subkey names */
9021 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9022 data = &printer->info_2->data;
9024 num_keys = get_printer_subkeys( data, key, &keynames );
9026 if ( num_keys == -1 ) {
9027 status = WERR_BADFILE;
9031 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9033 r_u->needed = printerkey_len*2;
9035 if ( q_u->size < r_u->needed ) {
9036 status = WERR_MORE_DATA;
9040 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9041 status = WERR_NOMEM;
9047 if ( q_u->size < r_u->needed )
9048 status = WERR_MORE_DATA;
9051 free_a_printer( &printer, 2 );
9052 SAFE_FREE( keynames );
9057 /********************************************************************
9058 * spoolss_deleteprinterkey
9059 ********************************************************************/
9061 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9063 POLICY_HND *handle = &q_u->handle;
9064 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9066 NT_PRINTER_INFO_LEVEL *printer = NULL;
9070 DEBUG(5,("spoolss_deleteprinterkey\n"));
9073 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9077 /* if keyname == NULL, return error */
9079 if ( !q_u->keyname.buffer )
9080 return WERR_INVALID_PARAM;
9082 if (!get_printer_snum(p, handle, &snum))
9085 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9086 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9087 return WERR_ACCESS_DENIED;
9090 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9091 if (!W_ERROR_IS_OK(status))
9094 /* delete the key and all subneys */
9096 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9098 status = delete_all_printer_data( printer->info_2, key );
9100 if ( W_ERROR_IS_OK(status) )
9101 status = mod_a_printer(printer, 2);
9103 free_a_printer( &printer, 2 );
9109 /********************************************************************
9110 * spoolss_enumprinterdataex
9111 ********************************************************************/
9113 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9115 POLICY_HND *handle = &q_u->handle;
9116 uint32 in_size = q_u->size;
9119 NT_PRINTER_INFO_LEVEL *printer = NULL;
9120 PRINTER_ENUM_VALUES *enum_values = NULL;
9121 NT_PRINTER_DATA *p_data;
9123 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9128 REGISTRY_VALUE *val;
9133 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9136 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9141 * first check for a keyname of NULL or "". Win2k seems to send
9142 * this a lot and we should send back WERR_INVALID_PARAM
9143 * no need to spend time looking up the printer in this case.
9147 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9148 if ( !strlen(key) ) {
9149 result = WERR_INVALID_PARAM;
9153 /* get the printer off of disk */
9155 if (!get_printer_snum(p,handle, &snum))
9158 ZERO_STRUCT(printer);
9159 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9160 if (!W_ERROR_IS_OK(result))
9163 /* now look for a match on the key name */
9165 p_data = &printer->info_2->data;
9167 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9168 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9170 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9171 result = WERR_INVALID_PARAM;
9178 /* allocate the memory for the array of pointers -- if necessary */
9180 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9183 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9185 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9186 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9187 result = WERR_NOMEM;
9191 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9195 * loop through all params and build the array to pass
9196 * back to the client
9199 for ( i=0; i<num_entries; i++ )
9201 /* lookup the registry value */
9203 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9204 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9208 value_name = regval_name( val );
9209 init_unistr( &enum_values[i].valuename, value_name );
9210 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9211 enum_values[i].type = regval_type( val );
9213 data_len = regval_size( val );
9215 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9217 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9219 result = WERR_NOMEM;
9223 enum_values[i].data_len = data_len;
9225 /* keep track of the size of the array in bytes */
9227 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9230 /* housekeeping information in the reply */
9232 r_u->needed = needed;
9233 r_u->returned = num_entries;
9235 if (needed > in_size) {
9236 result = WERR_MORE_DATA;
9240 /* copy data into the reply */
9242 r_u->ctr.size = r_u->needed;
9243 r_u->ctr.size_of_array = r_u->returned;
9244 r_u->ctr.values = enum_values;
9250 free_a_printer(&printer, 2);
9255 /****************************************************************************
9256 ****************************************************************************/
9258 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9260 init_unistr(&info->name, name);
9263 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9264 UNISTR2 *environment,
9271 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9273 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9275 if (!get_short_archi(long_archi))
9276 return WERR_INVALID_ENVIRONMENT;
9278 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9281 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9283 fill_printprocessordirectory_1(info, path);
9285 *needed += spoolss_size_printprocessordirectory_info_1(info);
9287 if (!alloc_buffer_size(buffer, *needed)) {
9289 return WERR_INSUFFICIENT_BUFFER;
9292 smb_io_printprocessordirectory_1("", buffer, info, 0);
9296 if (*needed > offered)
9297 return WERR_INSUFFICIENT_BUFFER;
9302 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9304 uint32 level = q_u->level;
9305 NEW_BUFFER *buffer = NULL;
9306 uint32 offered = q_u->offered;
9307 uint32 *needed = &r_u->needed;
9310 /* that's an [in out] buffer */
9311 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9312 buffer = r_u->buffer;
9314 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9320 result = getprintprocessordirectory_level_1
9321 (&q_u->name, &q_u->environment, buffer, offered, needed);
9324 result = WERR_UNKNOWN_LEVEL;
9332 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9333 SPOOL_R_REPLYOPENPRINTER *r_u)
9335 DEBUG(5,("_spoolss_replyopenprinter\n"));
9337 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9342 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9343 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9345 DEBUG(5,("_spoolss_replycloseprinter\n"));