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 },
2001 for (i=0; archi_table[i].long_archi != NULL; i++)
2003 if (strcmp(arch, archi_table[i].long_archi) == 0)
2004 return (archi_table[i].version);
2010 /********************************************************************
2011 * _spoolss_deleteprinterdriver
2012 ********************************************************************/
2014 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2018 NT_PRINTER_DRIVER_INFO_LEVEL info;
2019 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2021 struct current_user user;
2023 WERROR status_win2k = WERR_ACCESS_DENIED;
2025 get_current_user(&user, p);
2027 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2028 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2030 /* check that we have a valid driver name first */
2032 if ((version=get_version_id(arch)) == -1)
2033 return WERR_INVALID_ENVIRONMENT;
2036 ZERO_STRUCT(info_win2k);
2038 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2040 /* try for Win2k driver if "Windows NT x86" */
2042 if ( version == 2 ) {
2044 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2045 status = WERR_UNKNOWN_PRINTER_DRIVER;
2049 /* otherwise it was a failure */
2051 status = WERR_UNKNOWN_PRINTER_DRIVER;
2057 if (printer_driver_in_use(info.info_3)) {
2058 status = WERR_PRINTER_DRIVER_IN_USE;
2064 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2066 /* if we get to here, we now have 2 driver info structures to remove */
2067 /* remove the Win2k driver first*/
2069 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2070 free_a_printer_driver( info_win2k, 3 );
2072 /* this should not have failed---if it did, report to client */
2073 if ( !W_ERROR_IS_OK(status_win2k) )
2078 status = delete_printer_driver(info.info_3, &user, version, False);
2080 /* if at least one of the deletes succeeded return OK */
2082 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2086 free_a_printer_driver( info, 3 );
2091 /********************************************************************
2092 * spoolss_deleteprinterdriverex
2093 ********************************************************************/
2095 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2099 NT_PRINTER_DRIVER_INFO_LEVEL info;
2100 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2102 uint32 flags = q_u->delete_flags;
2104 struct current_user user;
2106 WERROR status_win2k = WERR_ACCESS_DENIED;
2108 get_current_user(&user, p);
2110 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2111 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2113 /* check that we have a valid driver name first */
2114 if ((version=get_version_id(arch)) == -1) {
2115 /* this is what NT returns */
2116 return WERR_INVALID_ENVIRONMENT;
2119 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2120 version = q_u->version;
2123 ZERO_STRUCT(info_win2k);
2125 status = get_a_printer_driver(&info, 3, driver, arch, version);
2127 if ( !W_ERROR_IS_OK(status) )
2130 * if the client asked for a specific version,
2131 * or this is something other than Windows NT x86,
2135 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2138 /* try for Win2k driver if "Windows NT x86" */
2141 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2142 status = WERR_UNKNOWN_PRINTER_DRIVER;
2147 if ( printer_driver_in_use(info.info_3) ) {
2148 status = WERR_PRINTER_DRIVER_IN_USE;
2153 * we have a couple of cases to consider.
2154 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2155 * then the delete should fail if **any** files overlap with
2157 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2158 * non-overlapping files
2159 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2160 * is set, the do not delete any files
2161 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2164 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2166 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2168 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2169 /* no idea of the correct error here */
2170 status = WERR_ACCESS_DENIED;
2175 /* also check for W32X86/3 if necessary; maybe we already have? */
2177 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2178 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2181 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2182 /* no idea of the correct error here */
2183 free_a_printer_driver( info_win2k, 3 );
2184 status = WERR_ACCESS_DENIED;
2188 /* if we get to here, we now have 2 driver info structures to remove */
2189 /* remove the Win2k driver first*/
2191 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2192 free_a_printer_driver( info_win2k, 3 );
2194 /* this should not have failed---if it did, report to client */
2196 if ( !W_ERROR_IS_OK(status_win2k) )
2201 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2203 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2206 free_a_printer_driver( info, 3 );
2212 /****************************************************************************
2213 Internal routine for retreiving printerdata
2214 ***************************************************************************/
2216 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2217 const char *key, const char *value, uint32 *type, uint8 **data,
2218 uint32 *needed, uint32 in_size )
2220 REGISTRY_VALUE *val;
2223 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2224 return WERR_BADFILE;
2226 *type = regval_type( val );
2228 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2230 size = regval_size( val );
2232 /* copy the min(in_size, len) */
2235 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2237 /* special case for 0 length values */
2239 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2243 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2252 DEBUG(5,("get_printer_dataex: copy done\n"));
2257 /****************************************************************************
2258 Internal routine for removing printerdata
2259 ***************************************************************************/
2261 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2263 return delete_printer_data( printer->info_2, key, value );
2266 /****************************************************************************
2267 Internal routine for storing printerdata
2268 ***************************************************************************/
2270 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2271 uint32 type, uint8 *data, int real_len )
2273 delete_printer_data( printer->info_2, key, value );
2275 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2278 /********************************************************************
2279 GetPrinterData on a printer server Handle.
2280 ********************************************************************/
2282 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2286 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2288 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2290 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2296 if (!StrCaseCmp(value, "BeepEnabled")) {
2298 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2300 SIVAL(*data, 0, 0x00);
2305 if (!StrCaseCmp(value, "EventLog")) {
2307 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2309 /* formally was 0x1b */
2310 SIVAL(*data, 0, 0x0);
2315 if (!StrCaseCmp(value, "NetPopup")) {
2317 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2319 SIVAL(*data, 0, 0x00);
2324 if (!StrCaseCmp(value, "MajorVersion")) {
2326 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2329 /* Windows NT 4.0 seems to not allow uploading of drivers
2330 to a server that reports 0x3 as the MajorVersion.
2331 need to investigate more how Win2k gets around this .
2334 if ( RA_WINNT == get_remote_arch() )
2343 if (!StrCaseCmp(value, "MinorVersion")) {
2345 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2353 * uint32 size = 0x114
2355 * uint32 minor = [0|1]
2356 * uint32 build = [2195|2600]
2357 * extra unicode string = e.g. "Service Pack 3"
2359 if (!StrCaseCmp(value, "OSVersion")) {
2363 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2365 ZERO_STRUCTP( *data );
2367 SIVAL(*data, 0, *needed); /* size */
2368 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2370 SIVAL(*data, 12, 2195); /* build */
2372 /* leave extra string empty */
2378 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2379 const char *string="C:\\PRINTERS";
2381 *needed = 2*(strlen(string)+1);
2382 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2384 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2386 /* it's done by hand ready to go on the wire */
2387 for (i=0; i<strlen(string); i++) {
2388 (*data)[2*i]=string[i];
2389 (*data)[2*i+1]='\0';
2394 if (!StrCaseCmp(value, "Architecture")) {
2395 const char *string="Windows NT x86";
2397 *needed = 2*(strlen(string)+1);
2398 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2400 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2401 for (i=0; i<strlen(string); i++) {
2402 (*data)[2*i]=string[i];
2403 (*data)[2*i+1]='\0';
2408 if (!StrCaseCmp(value, "DsPresent")) {
2410 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2412 SIVAL(*data, 0, 0x01);
2417 if (!StrCaseCmp(value, "DNSMachineName")) {
2420 if (!get_mydnsfullname(hostname))
2421 return WERR_BADFILE;
2423 *needed = 2*(strlen(hostname)+1);
2424 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2426 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2427 for (i=0; i<strlen(hostname); i++) {
2428 (*data)[2*i]=hostname[i];
2429 (*data)[2*i+1]='\0';
2435 return WERR_BADFILE;
2438 /********************************************************************
2439 * spoolss_getprinterdata
2440 ********************************************************************/
2442 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2444 POLICY_HND *handle = &q_u->handle;
2445 UNISTR2 *valuename = &q_u->valuename;
2446 uint32 in_size = q_u->size;
2447 uint32 *type = &r_u->type;
2448 uint32 *out_size = &r_u->size;
2449 uint8 **data = &r_u->data;
2450 uint32 *needed = &r_u->needed;
2453 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2454 NT_PRINTER_INFO_LEVEL *printer = NULL;
2458 * Reminder: when it's a string, the length is in BYTES
2459 * even if UNICODE is negociated.
2464 *out_size = in_size;
2466 /* in case of problem, return some default values */
2471 DEBUG(4,("_spoolss_getprinterdata\n"));
2474 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2475 status = WERR_BADFID;
2479 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2481 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2482 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2485 if ( !get_printer_snum(p,handle, &snum) ) {
2486 status = WERR_BADFID;
2490 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2491 if ( !W_ERROR_IS_OK(status) )
2494 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2496 if ( strequal(value, "ChangeId") ) {
2498 *needed = sizeof(uint32);
2499 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2500 status = WERR_NOMEM;
2503 SIVAL( *data, 0, printer->info_2->changeid );
2507 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2510 if (*needed > *out_size)
2511 status = WERR_MORE_DATA;
2514 if ( !W_ERROR_IS_OK(status) )
2516 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2518 /* reply this param doesn't exist */
2521 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2523 free_a_printer( &printer, 2 );
2532 /* cleanup & exit */
2535 free_a_printer( &printer, 2 );
2540 /*********************************************************
2541 Connect to the client machine.
2542 **********************************************************/
2544 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2545 struct in_addr *client_ip, const char *remote_machine)
2547 ZERO_STRUCTP(the_cli);
2549 if(cli_initialise(the_cli) == NULL) {
2550 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2554 if ( is_zero_ip(*client_ip) ) {
2555 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2556 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2557 cli_shutdown(the_cli);
2561 if (ismyip(the_cli->dest_ip)) {
2562 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2563 cli_shutdown(the_cli);
2568 the_cli->dest_ip.s_addr = client_ip->s_addr;
2569 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2570 inet_ntoa(*client_ip) ));
2573 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2574 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) ));
2575 cli_shutdown(the_cli);
2579 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2580 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2582 cli_shutdown(the_cli);
2586 the_cli->protocol = PROTOCOL_NT1;
2587 cli_setup_signing_state(the_cli, lp_client_signing());
2589 if (!cli_negprot(the_cli)) {
2590 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2591 cli_shutdown(the_cli);
2595 if (the_cli->protocol != PROTOCOL_NT1) {
2596 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2597 cli_shutdown(the_cli);
2602 * Do an anonymous session setup.
2605 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2606 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2607 cli_shutdown(the_cli);
2611 if (!(the_cli->sec_mode & 1)) {
2612 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2613 cli_shutdown(the_cli);
2617 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2618 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) ));
2619 cli_shutdown(the_cli);
2624 * Ok - we have an anonymous connection to the IPC$ share.
2625 * Now start the NT Domain stuff :-).
2628 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2629 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)));
2630 cli_nt_session_close(the_cli);
2631 cli_ulogoff(the_cli);
2632 cli_shutdown(the_cli);
2639 /***************************************************************************
2640 Connect to the client.
2641 ****************************************************************************/
2643 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2644 uint32 localprinter, uint32 type,
2645 POLICY_HND *handle, struct in_addr *client_ip)
2650 * If it's the first connection, contact the client
2651 * and connect to the IPC$ share anonymously
2653 if (smb_connections==0) {
2654 fstring unix_printer;
2656 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2658 ZERO_STRUCT(notify_cli);
2660 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2663 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2664 /* Tell the connections db we're now interested in printer
2665 * notify messages. */
2666 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2670 * Tell the specific printing tdb we want messages for this printer
2671 * by registering our PID.
2674 if (!print_notify_register_pid(snum))
2675 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2679 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2682 if (!W_ERROR_IS_OK(result))
2683 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2684 dos_errstr(result)));
2686 return (W_ERROR_IS_OK(result));
2689 /********************************************************************
2691 * ReplyFindFirstPrinterChangeNotifyEx
2693 * before replying OK: status=0 a rpc call is made to the workstation
2694 * asking ReplyOpenPrinter
2696 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2697 * called from api_spoolss_rffpcnex
2698 ********************************************************************/
2700 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2702 POLICY_HND *handle = &q_u->handle;
2703 uint32 flags = q_u->flags;
2704 uint32 options = q_u->options;
2705 UNISTR2 *localmachine = &q_u->localmachine;
2706 uint32 printerlocal = q_u->printerlocal;
2708 SPOOL_NOTIFY_OPTION *option = q_u->option;
2709 struct in_addr client_ip;
2711 /* store the notify value in the printer struct */
2713 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2716 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2720 Printer->notify.flags=flags;
2721 Printer->notify.options=options;
2722 Printer->notify.printerlocal=printerlocal;
2724 if (Printer->notify.option)
2725 free_spool_notify_option(&Printer->notify.option);
2727 Printer->notify.option=dup_spool_notify_option(option);
2729 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2730 sizeof(Printer->notify.localmachine)-1);
2732 /* Connect to the client machine and send a ReplyOpenPrinter */
2734 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2736 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2737 !get_printer_snum(p, handle, &snum) )
2740 client_ip.s_addr = inet_addr(p->conn->client_address);
2742 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2743 Printer->notify.printerlocal, 1,
2744 &Printer->notify.client_hnd, &client_ip))
2745 return WERR_SERVER_UNAVAILABLE;
2747 Printer->notify.client_connected=True;
2752 #if 0 /* JERRY -- disabled; not used for now */
2754 /*******************************************************************
2755 * fill a notify_info_data with the servername
2756 ********************************************************************/
2758 void spoolss_notify_server_name(int snum,
2759 SPOOL_NOTIFY_INFO_DATA *data,
2760 print_queue_struct *queue,
2761 NT_PRINTER_INFO_LEVEL *printer,
2762 TALLOC_CTX *mem_ctx)
2764 pstring temp_name, temp;
2767 fstrcpy( temp_name, "\\\\%L" );
2768 standard_sub_basic( NULL, temp_name, sizeof(temp_name)-1 );
2771 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2773 data->notify_data.data.length = len;
2774 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2776 if (!data->notify_data.data.string) {
2777 data->notify_data.data.length = 0;
2781 memcpy(data->notify_data.data.string, temp, len);
2787 /*******************************************************************
2788 * fill a notify_info_data with the printername (not including the servername).
2789 ********************************************************************/
2791 void spoolss_notify_printer_name(int snum,
2792 SPOOL_NOTIFY_INFO_DATA *data,
2793 print_queue_struct *queue,
2794 NT_PRINTER_INFO_LEVEL *printer,
2795 TALLOC_CTX *mem_ctx)
2800 /* the notify name should not contain the \\server\ part */
2801 char *p = strrchr(printer->info_2->printername, '\\');
2804 p = printer->info_2->printername;
2809 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2811 data->notify_data.data.length = len;
2812 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2814 if (!data->notify_data.data.string) {
2815 data->notify_data.data.length = 0;
2819 memcpy(data->notify_data.data.string, temp, len);
2822 /*******************************************************************
2823 * fill a notify_info_data with the servicename
2824 ********************************************************************/
2826 void spoolss_notify_share_name(int snum,
2827 SPOOL_NOTIFY_INFO_DATA *data,
2828 print_queue_struct *queue,
2829 NT_PRINTER_INFO_LEVEL *printer,
2830 TALLOC_CTX *mem_ctx)
2835 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2837 data->notify_data.data.length = len;
2838 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2840 if (!data->notify_data.data.string) {
2841 data->notify_data.data.length = 0;
2845 memcpy(data->notify_data.data.string, temp, len);
2848 /*******************************************************************
2849 * fill a notify_info_data with the port name
2850 ********************************************************************/
2852 void spoolss_notify_port_name(int snum,
2853 SPOOL_NOTIFY_INFO_DATA *data,
2854 print_queue_struct *queue,
2855 NT_PRINTER_INFO_LEVEL *printer,
2856 TALLOC_CTX *mem_ctx)
2861 /* even if it's strange, that's consistant in all the code */
2863 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2865 data->notify_data.data.length = len;
2866 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2868 if (!data->notify_data.data.string) {
2869 data->notify_data.data.length = 0;
2873 memcpy(data->notify_data.data.string, temp, len);
2876 /*******************************************************************
2877 * fill a notify_info_data with the printername
2878 * but it doesn't exist, have to see what to do
2879 ********************************************************************/
2881 void spoolss_notify_driver_name(int snum,
2882 SPOOL_NOTIFY_INFO_DATA *data,
2883 print_queue_struct *queue,
2884 NT_PRINTER_INFO_LEVEL *printer,
2885 TALLOC_CTX *mem_ctx)
2890 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2892 data->notify_data.data.length = len;
2893 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2895 if (!data->notify_data.data.string) {
2896 data->notify_data.data.length = 0;
2900 memcpy(data->notify_data.data.string, temp, len);
2903 /*******************************************************************
2904 * fill a notify_info_data with the comment
2905 ********************************************************************/
2907 void spoolss_notify_comment(int snum,
2908 SPOOL_NOTIFY_INFO_DATA *data,
2909 print_queue_struct *queue,
2910 NT_PRINTER_INFO_LEVEL *printer,
2911 TALLOC_CTX *mem_ctx)
2916 if (*printer->info_2->comment == '\0')
2917 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2919 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2921 data->notify_data.data.length = len;
2922 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2924 if (!data->notify_data.data.string) {
2925 data->notify_data.data.length = 0;
2929 memcpy(data->notify_data.data.string, temp, len);
2932 /*******************************************************************
2933 * fill a notify_info_data with the comment
2934 * location = "Room 1, floor 2, building 3"
2935 ********************************************************************/
2937 void spoolss_notify_location(int snum,
2938 SPOOL_NOTIFY_INFO_DATA *data,
2939 print_queue_struct *queue,
2940 NT_PRINTER_INFO_LEVEL *printer,
2941 TALLOC_CTX *mem_ctx)
2946 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2948 data->notify_data.data.length = len;
2949 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2951 if (!data->notify_data.data.string) {
2952 data->notify_data.data.length = 0;
2956 memcpy(data->notify_data.data.string, temp, len);
2959 /*******************************************************************
2960 * fill a notify_info_data with the device mode
2961 * jfm:xxxx don't to it for know but that's a real problem !!!
2962 ********************************************************************/
2964 static void spoolss_notify_devmode(int snum,
2965 SPOOL_NOTIFY_INFO_DATA *data,
2966 print_queue_struct *queue,
2967 NT_PRINTER_INFO_LEVEL *printer,
2968 TALLOC_CTX *mem_ctx)
2972 /*******************************************************************
2973 * fill a notify_info_data with the separator file name
2974 ********************************************************************/
2976 void spoolss_notify_sepfile(int snum,
2977 SPOOL_NOTIFY_INFO_DATA *data,
2978 print_queue_struct *queue,
2979 NT_PRINTER_INFO_LEVEL *printer,
2980 TALLOC_CTX *mem_ctx)
2985 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2987 data->notify_data.data.length = len;
2988 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2990 if (!data->notify_data.data.string) {
2991 data->notify_data.data.length = 0;
2995 memcpy(data->notify_data.data.string, temp, len);
2998 /*******************************************************************
2999 * fill a notify_info_data with the print processor
3000 * jfm:xxxx return always winprint to indicate we don't do anything to it
3001 ********************************************************************/
3003 void spoolss_notify_print_processor(int snum,
3004 SPOOL_NOTIFY_INFO_DATA *data,
3005 print_queue_struct *queue,
3006 NT_PRINTER_INFO_LEVEL *printer,
3007 TALLOC_CTX *mem_ctx)
3012 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3014 data->notify_data.data.length = len;
3015 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3017 if (!data->notify_data.data.string) {
3018 data->notify_data.data.length = 0;
3022 memcpy(data->notify_data.data.string, temp, len);
3025 /*******************************************************************
3026 * fill a notify_info_data with the print processor options
3027 * jfm:xxxx send an empty string
3028 ********************************************************************/
3030 void spoolss_notify_parameters(int snum,
3031 SPOOL_NOTIFY_INFO_DATA *data,
3032 print_queue_struct *queue,
3033 NT_PRINTER_INFO_LEVEL *printer,
3034 TALLOC_CTX *mem_ctx)
3039 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3041 data->notify_data.data.length = len;
3042 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3044 if (!data->notify_data.data.string) {
3045 data->notify_data.data.length = 0;
3049 memcpy(data->notify_data.data.string, temp, len);
3052 /*******************************************************************
3053 * fill a notify_info_data with the data type
3054 * jfm:xxxx always send RAW as data type
3055 ********************************************************************/
3057 void spoolss_notify_datatype(int snum,
3058 SPOOL_NOTIFY_INFO_DATA *data,
3059 print_queue_struct *queue,
3060 NT_PRINTER_INFO_LEVEL *printer,
3061 TALLOC_CTX *mem_ctx)
3066 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3068 data->notify_data.data.length = len;
3069 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3071 if (!data->notify_data.data.string) {
3072 data->notify_data.data.length = 0;
3076 memcpy(data->notify_data.data.string, temp, len);
3079 /*******************************************************************
3080 * fill a notify_info_data with the security descriptor
3081 * jfm:xxxx send an null pointer to say no security desc
3082 * have to implement security before !
3083 ********************************************************************/
3085 static void spoolss_notify_security_desc(int snum,
3086 SPOOL_NOTIFY_INFO_DATA *data,
3087 print_queue_struct *queue,
3088 NT_PRINTER_INFO_LEVEL *printer,
3089 TALLOC_CTX *mem_ctx)
3091 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3092 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3095 /*******************************************************************
3096 * fill a notify_info_data with the attributes
3097 * jfm:xxxx a samba printer is always shared
3098 ********************************************************************/
3100 void spoolss_notify_attributes(int snum,
3101 SPOOL_NOTIFY_INFO_DATA *data,
3102 print_queue_struct *queue,
3103 NT_PRINTER_INFO_LEVEL *printer,
3104 TALLOC_CTX *mem_ctx)
3106 data->notify_data.value[0] = printer->info_2->attributes;
3107 data->notify_data.value[1] = 0;
3110 /*******************************************************************
3111 * fill a notify_info_data with the priority
3112 ********************************************************************/
3114 static void spoolss_notify_priority(int snum,
3115 SPOOL_NOTIFY_INFO_DATA *data,
3116 print_queue_struct *queue,
3117 NT_PRINTER_INFO_LEVEL *printer,
3118 TALLOC_CTX *mem_ctx)
3120 data->notify_data.value[0] = printer->info_2->priority;
3121 data->notify_data.value[1] = 0;
3124 /*******************************************************************
3125 * fill a notify_info_data with the default priority
3126 ********************************************************************/
3128 static void spoolss_notify_default_priority(int snum,
3129 SPOOL_NOTIFY_INFO_DATA *data,
3130 print_queue_struct *queue,
3131 NT_PRINTER_INFO_LEVEL *printer,
3132 TALLOC_CTX *mem_ctx)
3134 data->notify_data.value[0] = printer->info_2->default_priority;
3135 data->notify_data.value[1] = 0;
3138 /*******************************************************************
3139 * fill a notify_info_data with the start time
3140 ********************************************************************/
3142 static void spoolss_notify_start_time(int snum,
3143 SPOOL_NOTIFY_INFO_DATA *data,
3144 print_queue_struct *queue,
3145 NT_PRINTER_INFO_LEVEL *printer,
3146 TALLOC_CTX *mem_ctx)
3148 data->notify_data.value[0] = printer->info_2->starttime;
3149 data->notify_data.value[1] = 0;
3152 /*******************************************************************
3153 * fill a notify_info_data with the until time
3154 ********************************************************************/
3156 static void spoolss_notify_until_time(int snum,
3157 SPOOL_NOTIFY_INFO_DATA *data,
3158 print_queue_struct *queue,
3159 NT_PRINTER_INFO_LEVEL *printer,
3160 TALLOC_CTX *mem_ctx)
3162 data->notify_data.value[0] = printer->info_2->untiltime;
3163 data->notify_data.value[1] = 0;
3166 /*******************************************************************
3167 * fill a notify_info_data with the status
3168 ********************************************************************/
3170 static void spoolss_notify_status(int snum,
3171 SPOOL_NOTIFY_INFO_DATA *data,
3172 print_queue_struct *queue,
3173 NT_PRINTER_INFO_LEVEL *printer,
3174 TALLOC_CTX *mem_ctx)
3176 print_status_struct status;
3178 print_queue_length(snum, &status);
3179 data->notify_data.value[0]=(uint32) status.status;
3180 data->notify_data.value[1] = 0;
3183 /*******************************************************************
3184 * fill a notify_info_data with the number of jobs queued
3185 ********************************************************************/
3187 void spoolss_notify_cjobs(int snum,
3188 SPOOL_NOTIFY_INFO_DATA *data,
3189 print_queue_struct *queue,
3190 NT_PRINTER_INFO_LEVEL *printer,
3191 TALLOC_CTX *mem_ctx)
3193 data->notify_data.value[0] = print_queue_length(snum, NULL);
3194 data->notify_data.value[1] = 0;
3197 /*******************************************************************
3198 * fill a notify_info_data with the average ppm
3199 ********************************************************************/
3201 static void spoolss_notify_average_ppm(int snum,
3202 SPOOL_NOTIFY_INFO_DATA *data,
3203 print_queue_struct *queue,
3204 NT_PRINTER_INFO_LEVEL *printer,
3205 TALLOC_CTX *mem_ctx)
3207 /* always respond 8 pages per minutes */
3208 /* a little hard ! */
3209 data->notify_data.value[0] = printer->info_2->averageppm;
3210 data->notify_data.value[1] = 0;
3213 /*******************************************************************
3214 * fill a notify_info_data with username
3215 ********************************************************************/
3217 static void spoolss_notify_username(int snum,
3218 SPOOL_NOTIFY_INFO_DATA *data,
3219 print_queue_struct *queue,
3220 NT_PRINTER_INFO_LEVEL *printer,
3221 TALLOC_CTX *mem_ctx)
3226 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3228 data->notify_data.data.length = len;
3229 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3231 if (!data->notify_data.data.string) {
3232 data->notify_data.data.length = 0;
3236 memcpy(data->notify_data.data.string, temp, len);
3239 /*******************************************************************
3240 * fill a notify_info_data with job status
3241 ********************************************************************/
3243 static void spoolss_notify_job_status(int snum,
3244 SPOOL_NOTIFY_INFO_DATA *data,
3245 print_queue_struct *queue,
3246 NT_PRINTER_INFO_LEVEL *printer,
3247 TALLOC_CTX *mem_ctx)
3249 data->notify_data.value[0]=nt_printj_status(queue->status);
3250 data->notify_data.value[1] = 0;
3253 /*******************************************************************
3254 * fill a notify_info_data with job name
3255 ********************************************************************/
3257 static void spoolss_notify_job_name(int snum,
3258 SPOOL_NOTIFY_INFO_DATA *data,
3259 print_queue_struct *queue,
3260 NT_PRINTER_INFO_LEVEL *printer,
3261 TALLOC_CTX *mem_ctx)
3266 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3268 data->notify_data.data.length = len;
3269 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3271 if (!data->notify_data.data.string) {
3272 data->notify_data.data.length = 0;
3276 memcpy(data->notify_data.data.string, temp, len);
3279 /*******************************************************************
3280 * fill a notify_info_data with job status
3281 ********************************************************************/
3283 static void spoolss_notify_job_status_string(int snum,
3284 SPOOL_NOTIFY_INFO_DATA *data,
3285 print_queue_struct *queue,
3286 NT_PRINTER_INFO_LEVEL *printer,
3287 TALLOC_CTX *mem_ctx)
3290 * Now we're returning job status codes we just return a "" here. JRA.
3297 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3300 switch (queue->status) {
3305 p = ""; /* NT provides the paused string */
3314 #endif /* NO LONGER NEEDED. */
3316 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3318 data->notify_data.data.length = len;
3319 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3321 if (!data->notify_data.data.string) {
3322 data->notify_data.data.length = 0;
3326 memcpy(data->notify_data.data.string, temp, len);
3329 /*******************************************************************
3330 * fill a notify_info_data with job time
3331 ********************************************************************/
3333 static void spoolss_notify_job_time(int snum,
3334 SPOOL_NOTIFY_INFO_DATA *data,
3335 print_queue_struct *queue,
3336 NT_PRINTER_INFO_LEVEL *printer,
3337 TALLOC_CTX *mem_ctx)
3339 data->notify_data.value[0]=0x0;
3340 data->notify_data.value[1]=0;
3343 /*******************************************************************
3344 * fill a notify_info_data with job size
3345 ********************************************************************/
3347 static void spoolss_notify_job_size(int snum,
3348 SPOOL_NOTIFY_INFO_DATA *data,
3349 print_queue_struct *queue,
3350 NT_PRINTER_INFO_LEVEL *printer,
3351 TALLOC_CTX *mem_ctx)
3353 data->notify_data.value[0]=queue->size;
3354 data->notify_data.value[1]=0;
3357 /*******************************************************************
3358 * fill a notify_info_data with page info
3359 ********************************************************************/
3360 static void spoolss_notify_total_pages(int snum,
3361 SPOOL_NOTIFY_INFO_DATA *data,
3362 print_queue_struct *queue,
3363 NT_PRINTER_INFO_LEVEL *printer,
3364 TALLOC_CTX *mem_ctx)
3366 data->notify_data.value[0]=queue->page_count;
3367 data->notify_data.value[1]=0;
3370 /*******************************************************************
3371 * fill a notify_info_data with pages printed info.
3372 ********************************************************************/
3373 static void spoolss_notify_pages_printed(int snum,
3374 SPOOL_NOTIFY_INFO_DATA *data,
3375 print_queue_struct *queue,
3376 NT_PRINTER_INFO_LEVEL *printer,
3377 TALLOC_CTX *mem_ctx)
3379 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3380 data->notify_data.value[1]=0;
3383 /*******************************************************************
3384 Fill a notify_info_data with job position.
3385 ********************************************************************/
3387 static void spoolss_notify_job_position(int snum,
3388 SPOOL_NOTIFY_INFO_DATA *data,
3389 print_queue_struct *queue,
3390 NT_PRINTER_INFO_LEVEL *printer,
3391 TALLOC_CTX *mem_ctx)
3393 data->notify_data.value[0]=queue->job;
3394 data->notify_data.value[1]=0;
3397 /*******************************************************************
3398 Fill a notify_info_data with submitted time.
3399 ********************************************************************/
3401 static void spoolss_notify_submitted_time(int snum,
3402 SPOOL_NOTIFY_INFO_DATA *data,
3403 print_queue_struct *queue,
3404 NT_PRINTER_INFO_LEVEL *printer,
3405 TALLOC_CTX *mem_ctx)
3412 t=gmtime(&queue->time);
3414 len = sizeof(SYSTEMTIME);
3416 data->notify_data.data.length = len;
3417 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3419 if (!data->notify_data.data.string) {
3420 data->notify_data.data.length = 0;
3424 make_systemtime(&st, t);
3427 * Systemtime must be linearized as a set of UINT16's.
3428 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3431 p = (char *)data->notify_data.data.string;
3432 SSVAL(p, 0, st.year);
3433 SSVAL(p, 2, st.month);
3434 SSVAL(p, 4, st.dayofweek);
3435 SSVAL(p, 6, st.day);
3436 SSVAL(p, 8, st.hour);
3437 SSVAL(p, 10, st.minute);
3438 SSVAL(p, 12, st.second);
3439 SSVAL(p, 14, st.milliseconds);
3442 struct s_notify_info_data_table
3448 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3449 print_queue_struct *queue,
3450 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3453 /* A table describing the various print notification constants and
3454 whether the notification data is a pointer to a variable sized
3455 buffer, a one value uint32 or a two value uint32. */
3457 static const struct s_notify_info_data_table notify_info_data_table[] =
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, NULL},
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, NULL},
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3510 /*******************************************************************
3511 Return the size of info_data structure.
3512 ********************************************************************/
3514 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3518 for (i = 0; i < sizeof(notify_info_data_table); i++)
3520 if ( (notify_info_data_table[i].type == type)
3521 && (notify_info_data_table[i].field == field) )
3523 switch(notify_info_data_table[i].size)
3525 case NOTIFY_ONE_VALUE:
3526 case NOTIFY_TWO_VALUE:
3531 /* The only pointer notify data I have seen on
3532 the wire is the submitted time and this has
3533 the notify size set to 4. -tpot */
3535 case NOTIFY_POINTER:
3538 case NOTIFY_SECDESC:
3544 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3549 /*******************************************************************
3550 Return the type of notify_info_data.
3551 ********************************************************************/
3553 static int type_of_notify_info_data(uint16 type, uint16 field)
3557 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3558 if (notify_info_data_table[i].type == type &&
3559 notify_info_data_table[i].field == field)
3560 return notify_info_data_table[i].size;
3566 /****************************************************************************
3567 ****************************************************************************/
3569 static int search_notify(uint16 type, uint16 field, int *value)
3573 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3574 if (notify_info_data_table[i].type == type &&
3575 notify_info_data_table[i].field == field &&
3576 notify_info_data_table[i].fn != NULL) {
3585 /****************************************************************************
3586 ****************************************************************************/
3588 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3590 info_data->type = type;
3591 info_data->field = field;
3592 info_data->reserved = 0;
3594 info_data->size = size_of_notify_info_data(type, field);
3595 info_data->enc_type = type_of_notify_info_data(type, field);
3602 /*******************************************************************
3604 * fill a notify_info struct with info asked
3606 ********************************************************************/
3608 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3609 snum, SPOOL_NOTIFY_OPTION_TYPE
3610 *option_type, uint32 id,
3611 TALLOC_CTX *mem_ctx)
3617 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3618 NT_PRINTER_INFO_LEVEL *printer = NULL;
3619 print_queue_struct *queue=NULL;
3621 type=option_type->type;
3623 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3624 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3625 option_type->count, lp_servicename(snum)));
3627 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3630 for(field_num=0; field_num<option_type->count; field_num++) {
3631 field = option_type->fields[field_num];
3633 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3635 if (!search_notify(type, field, &j) )
3638 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3639 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3644 current_data = &info->data[info->count];
3646 construct_info_data(current_data, type, field, id);
3648 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3649 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3651 notify_info_data_table[j].fn(snum, current_data, queue,
3657 free_a_printer(&printer, 2);
3661 /*******************************************************************
3663 * fill a notify_info struct with info asked
3665 ********************************************************************/
3667 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3668 SPOOL_NOTIFY_INFO *info,
3669 NT_PRINTER_INFO_LEVEL *printer,
3670 int snum, SPOOL_NOTIFY_OPTION_TYPE
3671 *option_type, uint32 id,
3672 TALLOC_CTX *mem_ctx)
3678 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3680 DEBUG(4,("construct_notify_jobs_info\n"));
3682 type = option_type->type;
3684 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3685 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3686 option_type->count));
3688 for(field_num=0; field_num<option_type->count; field_num++) {
3689 field = option_type->fields[field_num];
3691 if (!search_notify(type, field, &j) )
3694 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3695 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3698 else info->data = tid;
3700 current_data=&(info->data[info->count]);
3702 construct_info_data(current_data, type, field, id);
3703 notify_info_data_table[j].fn(snum, current_data, queue,
3712 * JFM: The enumeration is not that simple, it's even non obvious.
3714 * let's take an example: I want to monitor the PRINTER SERVER for
3715 * the printer's name and the number of jobs currently queued.
3716 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3717 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3719 * I have 3 printers on the back of my server.
3721 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3724 * 1 printer 1 name 1
3725 * 2 printer 1 cjob 1
3726 * 3 printer 2 name 2
3727 * 4 printer 2 cjob 2
3728 * 5 printer 3 name 3
3729 * 6 printer 3 name 3
3731 * that's the print server case, the printer case is even worse.
3734 /*******************************************************************
3736 * enumerate all printers on the printserver
3737 * fill a notify_info struct with info asked
3739 ********************************************************************/
3741 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3742 SPOOL_NOTIFY_INFO *info,
3743 TALLOC_CTX *mem_ctx)
3746 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3747 int n_services=lp_numservices();
3749 SPOOL_NOTIFY_OPTION *option;
3750 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3752 DEBUG(4,("printserver_notify_info\n"));
3757 option=Printer->notify.option;
3762 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3763 sending a ffpcn() request first */
3768 for (i=0; i<option->count; i++) {
3769 option_type=&(option->ctr.type[i]);
3771 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3774 for (snum=0; snum<n_services; snum++)
3776 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3777 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3783 * Debugging information, don't delete.
3786 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3787 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3788 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3790 for (i=0; i<info->count; i++) {
3791 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3792 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3793 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3800 /*******************************************************************
3802 * fill a notify_info struct with info asked
3804 ********************************************************************/
3806 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3807 TALLOC_CTX *mem_ctx)
3810 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3813 SPOOL_NOTIFY_OPTION *option;
3814 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3816 print_queue_struct *queue=NULL;
3817 print_status_struct status;
3819 DEBUG(4,("printer_notify_info\n"));
3824 option=Printer->notify.option;
3830 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3831 sending a ffpcn() request first */
3836 get_printer_snum(p, hnd, &snum);
3838 for (i=0; i<option->count; i++) {
3839 option_type=&option->ctr.type[i];
3841 switch ( option_type->type ) {
3842 case PRINTER_NOTIFY_TYPE:
3843 if(construct_notify_printer_info(Printer, info, snum,
3849 case JOB_NOTIFY_TYPE: {
3850 NT_PRINTER_INFO_LEVEL *printer = NULL;
3852 count = print_queue_status(snum, &queue, &status);
3854 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3857 for (j=0; j<count; j++) {
3858 construct_notify_jobs_info(&queue[j], info,
3865 free_a_printer(&printer, 2);
3875 * Debugging information, don't delete.
3878 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3879 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3880 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3882 for (i=0; i<info->count; i++) {
3883 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3884 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3885 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3891 /********************************************************************
3893 ********************************************************************/
3895 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3897 POLICY_HND *handle = &q_u->handle;
3898 SPOOL_NOTIFY_INFO *info = &r_u->info;
3900 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3901 WERROR result = WERR_BADFID;
3903 /* we always have a NOTIFY_INFO struct */
3907 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3908 OUR_HANDLE(handle)));
3912 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3915 * We are now using the change value, and
3916 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3917 * I don't have a global notification system, I'm sending back all the
3918 * informations even when _NOTHING_ has changed.
3921 /* We need to keep track of the change value to send back in
3922 RRPCN replies otherwise our updates are ignored. */
3924 Printer->notify.fnpcn = True;
3926 if (Printer->notify.client_connected) {
3927 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3928 Printer->notify.change = q_u->change;
3931 /* just ignore the SPOOL_NOTIFY_OPTION */
3933 switch (Printer->printer_type) {
3934 case PRINTER_HANDLE_IS_PRINTSERVER:
3935 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3938 case PRINTER_HANDLE_IS_PRINTER:
3939 result = printer_notify_info(p, handle, info, p->mem_ctx);
3943 Printer->notify.fnpcn = False;
3949 /********************************************************************
3950 * construct_printer_info_0
3951 * fill a printer_info_0 struct
3952 ********************************************************************/
3954 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3958 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3959 counter_printer_0 *session_counter;
3960 uint32 global_counter;
3963 print_status_struct status;
3965 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3968 count = print_queue_length(snum, &status);
3970 /* check if we already have a counter for this printer */
3971 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3972 if (session_counter->snum == snum)
3976 /* it's the first time, add it to the list */
3977 if (session_counter==NULL) {
3978 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3979 free_a_printer(&ntprinter, 2);
3982 ZERO_STRUCTP(session_counter);
3983 session_counter->snum=snum;
3984 session_counter->counter=0;
3985 DLIST_ADD(counter_list, session_counter);
3989 session_counter->counter++;
3992 * the global_counter should be stored in a TDB as it's common to all the clients
3993 * and should be zeroed on samba startup
3995 global_counter=session_counter->counter;
3997 pstrcpy(chaine,ntprinter->info_2->printername);
3999 init_unistr(&printer->printername, chaine);
4001 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
4002 init_unistr(&printer->servername, chaine);
4004 printer->cjobs = count;
4005 printer->total_jobs = 0;
4006 printer->total_bytes = 0;
4008 setuptime = (time_t)ntprinter->info_2->setuptime;
4009 t=gmtime(&setuptime);
4011 printer->year = t->tm_year+1900;
4012 printer->month = t->tm_mon+1;
4013 printer->dayofweek = t->tm_wday;
4014 printer->day = t->tm_mday;
4015 printer->hour = t->tm_hour;
4016 printer->minute = t->tm_min;
4017 printer->second = t->tm_sec;
4018 printer->milliseconds = 0;
4020 printer->global_counter = global_counter;
4021 printer->total_pages = 0;
4023 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4024 printer->major_version = 0x0005; /* NT 5 */
4025 printer->build_version = 0x0893; /* build 2195 */
4027 printer->unknown7 = 0x1;
4028 printer->unknown8 = 0x0;
4029 printer->unknown9 = 0x0;
4030 printer->session_counter = session_counter->counter;
4031 printer->unknown11 = 0x0;
4032 printer->printer_errors = 0x0; /* number of print failure */
4033 printer->unknown13 = 0x0;
4034 printer->unknown14 = 0x1;
4035 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4036 printer->unknown16 = 0x0;
4037 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4038 printer->unknown18 = 0x0;
4039 printer->status = nt_printq_status(status.status);
4040 printer->unknown20 = 0x0;
4041 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4042 printer->unknown22 = 0x0;
4043 printer->unknown23 = 0x6; /* 6 ???*/
4044 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4045 printer->unknown25 = 0;
4046 printer->unknown26 = 0;
4047 printer->unknown27 = 0;
4048 printer->unknown28 = 0;
4049 printer->unknown29 = 0;
4051 free_a_printer(&ntprinter,2);
4055 /********************************************************************
4056 * construct_printer_info_1
4057 * fill a printer_info_1 struct
4058 ********************************************************************/
4059 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4063 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4065 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4068 printer->flags=flags;
4070 if (*ntprinter->info_2->comment == '\0') {
4071 init_unistr(&printer->comment, lp_comment(snum));
4072 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4073 ntprinter->info_2->drivername, lp_comment(snum));
4076 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4077 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4078 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4081 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4083 init_unistr(&printer->description, chaine);
4084 init_unistr(&printer->name, chaine2);
4086 free_a_printer(&ntprinter,2);
4091 /****************************************************************************
4092 Free a DEVMODE struct.
4093 ****************************************************************************/
4095 static void free_dev_mode(DEVICEMODE *dev)
4100 SAFE_FREE(dev->private);
4105 /****************************************************************************
4106 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4107 should be valid upon entry
4108 ****************************************************************************/
4110 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4112 if ( !devmode || !ntdevmode )
4115 init_unistr(&devmode->devicename, ntdevmode->devicename);
4117 init_unistr(&devmode->formname, ntdevmode->formname);
4119 devmode->specversion = ntdevmode->specversion;
4120 devmode->driverversion = ntdevmode->driverversion;
4121 devmode->size = ntdevmode->size;
4122 devmode->driverextra = ntdevmode->driverextra;
4123 devmode->fields = ntdevmode->fields;
4125 devmode->orientation = ntdevmode->orientation;
4126 devmode->papersize = ntdevmode->papersize;
4127 devmode->paperlength = ntdevmode->paperlength;
4128 devmode->paperwidth = ntdevmode->paperwidth;
4129 devmode->scale = ntdevmode->scale;
4130 devmode->copies = ntdevmode->copies;
4131 devmode->defaultsource = ntdevmode->defaultsource;
4132 devmode->printquality = ntdevmode->printquality;
4133 devmode->color = ntdevmode->color;
4134 devmode->duplex = ntdevmode->duplex;
4135 devmode->yresolution = ntdevmode->yresolution;
4136 devmode->ttoption = ntdevmode->ttoption;
4137 devmode->collate = ntdevmode->collate;
4138 devmode->icmmethod = ntdevmode->icmmethod;
4139 devmode->icmintent = ntdevmode->icmintent;
4140 devmode->mediatype = ntdevmode->mediatype;
4141 devmode->dithertype = ntdevmode->dithertype;
4143 if (ntdevmode->private != NULL) {
4144 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4151 /****************************************************************************
4152 Create a DEVMODE struct. Returns malloced memory.
4153 ****************************************************************************/
4155 DEVICEMODE *construct_dev_mode(int snum)
4157 NT_PRINTER_INFO_LEVEL *printer = NULL;
4158 DEVICEMODE *devmode = NULL;
4160 DEBUG(7,("construct_dev_mode\n"));
4162 DEBUGADD(8,("getting printer characteristics\n"));
4164 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4167 if ( !printer->info_2->devmode ) {
4168 DEBUG(5, ("BONG! There was no device mode!\n"));
4172 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4173 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4177 ZERO_STRUCTP(devmode);
4179 DEBUGADD(8,("loading DEVICEMODE\n"));
4181 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4182 free_dev_mode( devmode );
4187 free_a_printer(&printer,2);
4192 /********************************************************************
4193 * construct_printer_info_2
4194 * fill a printer_info_2 struct
4195 ********************************************************************/
4197 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4200 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4202 print_status_struct status;
4204 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4207 count = print_queue_length(snum, &status);
4209 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4210 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4211 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4212 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4213 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4215 if (*ntprinter->info_2->comment == '\0')
4216 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4218 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4220 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4221 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4222 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4223 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4224 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4226 printer->attributes = ntprinter->info_2->attributes;
4228 printer->priority = ntprinter->info_2->priority; /* priority */
4229 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4230 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4231 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4232 printer->status = nt_printq_status(status.status); /* status */
4233 printer->cjobs = count; /* jobs */
4234 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4236 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4237 DEBUG(8, ("Returning NULL Devicemode!\n"));
4240 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4241 /* steal the printer info sec_desc structure. [badly done]. */
4242 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4243 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4244 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4245 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4248 printer->secdesc = NULL;
4251 free_a_printer(&ntprinter, 2);
4255 /********************************************************************
4256 * construct_printer_info_3
4257 * fill a printer_info_3 struct
4258 ********************************************************************/
4260 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4262 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4263 PRINTER_INFO_3 *printer = NULL;
4265 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4269 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4270 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4274 ZERO_STRUCTP(printer);
4276 printer->flags = 4; /* These are the components of the SD we are returning. */
4277 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4278 /* steal the printer info sec_desc structure. [badly done]. */
4279 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4283 * Set the flags for the components we are returning.
4286 if (printer->secdesc->owner_sid)
4287 printer->flags |= OWNER_SECURITY_INFORMATION;
4289 if (printer->secdesc->grp_sid)
4290 printer->flags |= GROUP_SECURITY_INFORMATION;
4292 if (printer->secdesc->dacl)
4293 printer->flags |= DACL_SECURITY_INFORMATION;
4295 if (printer->secdesc->sacl)
4296 printer->flags |= SACL_SECURITY_INFORMATION;
4299 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4300 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4301 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4304 free_a_printer(&ntprinter, 2);
4306 *pp_printer = printer;
4310 /********************************************************************
4311 * construct_printer_info_4
4312 * fill a printer_info_4 struct
4313 ********************************************************************/
4315 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4317 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4319 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4322 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4323 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4324 printer->attributes = ntprinter->info_2->attributes;
4326 free_a_printer(&ntprinter, 2);
4330 /********************************************************************
4331 * construct_printer_info_5
4332 * fill a printer_info_5 struct
4333 ********************************************************************/
4335 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4337 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4339 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4342 init_unistr(&printer->printername, ntprinter->info_2->printername);
4343 init_unistr(&printer->portname, ntprinter->info_2->portname);
4344 printer->attributes = ntprinter->info_2->attributes;
4346 /* these two are not used by NT+ according to MSDN */
4348 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4349 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4351 free_a_printer(&ntprinter, 2);
4356 /********************************************************************
4357 * construct_printer_info_7
4358 * fill a printer_info_7 struct
4359 ********************************************************************/
4361 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4363 char *guid_str = NULL;
4366 if (is_printer_published(print_hnd, snum, &guid)) {
4367 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4368 strupper_m(guid_str);
4369 init_unistr(&printer->guid, guid_str);
4370 printer->action = SPOOL_DS_PUBLISH;
4372 init_unistr(&printer->guid, "");
4373 printer->action = SPOOL_DS_UNPUBLISH;
4379 /********************************************************************
4380 Spoolss_enumprinters.
4381 ********************************************************************/
4383 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4387 int n_services=lp_numservices();
4388 PRINTER_INFO_1 *tp, *printers=NULL;
4389 PRINTER_INFO_1 current_prt;
4391 DEBUG(4,("enum_all_printers_info_1\n"));
4393 for (snum=0; snum<n_services; snum++) {
4394 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4395 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4397 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4398 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4399 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4400 SAFE_FREE(printers);
4405 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4407 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4413 /* check the required size. */
4414 for (i=0; i<*returned; i++)
4415 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4417 if (!alloc_buffer_size(buffer, *needed))
4418 return WERR_INSUFFICIENT_BUFFER;
4420 /* fill the buffer with the structures */
4421 for (i=0; i<*returned; i++)
4422 smb_io_printer_info_1("", buffer, &printers[i], 0);
4425 SAFE_FREE(printers);
4427 if (*needed > offered) {
4429 return WERR_INSUFFICIENT_BUFFER;
4435 /********************************************************************
4436 enum_all_printers_info_1_local.
4437 *********************************************************************/
4439 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4441 DEBUG(4,("enum_all_printers_info_1_local\n"));
4443 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4446 /********************************************************************
4447 enum_all_printers_info_1_name.
4448 *********************************************************************/
4450 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4454 DEBUG(4,("enum_all_printers_info_1_name\n"));
4456 if ((name[0] == '\\') && (name[1] == '\\'))
4459 if (is_myname_or_ipaddr(s)) {
4460 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4463 return WERR_INVALID_NAME;
4466 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4467 /********************************************************************
4468 enum_all_printers_info_1_remote.
4469 *********************************************************************/
4471 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4473 PRINTER_INFO_1 *printer;
4474 fstring printername;
4477 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4479 /* JFM: currently it's more a place holder than anything else.
4480 * In the spooler world there is a notion of server registration.
4481 * the print servers are registered on the PDC (in the same domain)
4483 * We should have a TDB here. The registration is done thru an
4484 * undocumented RPC call.
4487 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4492 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4493 slprintf(desc, sizeof(desc)-1,"%s", name);
4494 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4496 init_unistr(&printer->description, desc);
4497 init_unistr(&printer->name, printername);
4498 init_unistr(&printer->comment, comment);
4499 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4501 /* check the required size. */
4502 *needed += spoolss_size_printer_info_1(printer);
4504 if (!alloc_buffer_size(buffer, *needed)) {
4506 return WERR_INSUFFICIENT_BUFFER;
4509 /* fill the buffer with the structures */
4510 smb_io_printer_info_1("", buffer, printer, 0);
4515 if (*needed > offered) {
4517 return WERR_INSUFFICIENT_BUFFER;
4525 /********************************************************************
4526 enum_all_printers_info_1_network.
4527 *********************************************************************/
4529 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4533 DEBUG(4,("enum_all_printers_info_1_network\n"));
4535 /* If we respond to a enum_printers level 1 on our name with flags
4536 set to PRINTER_ENUM_REMOTE with a list of printers then these
4537 printers incorrectly appear in the APW browse list.
4538 Specifically the printers for the server appear at the workgroup
4539 level where all the other servers in the domain are
4540 listed. Windows responds to this call with a
4541 WERR_CAN_NOT_COMPLETE so we should do the same. */
4543 if (name[0] == '\\' && name[1] == '\\')
4546 if (is_myname_or_ipaddr(s))
4547 return WERR_CAN_NOT_COMPLETE;
4549 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4552 /********************************************************************
4553 * api_spoolss_enumprinters
4555 * called from api_spoolss_enumprinters (see this to understand)
4556 ********************************************************************/
4558 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4562 int n_services=lp_numservices();
4563 PRINTER_INFO_2 *tp, *printers=NULL;
4564 PRINTER_INFO_2 current_prt;
4566 for (snum=0; snum<n_services; snum++) {
4567 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4568 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4570 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4571 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4572 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4573 SAFE_FREE(printers);
4578 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4579 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4585 /* check the required size. */
4586 for (i=0; i<*returned; i++)
4587 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4589 if (!alloc_buffer_size(buffer, *needed)) {
4590 for (i=0; i<*returned; i++) {
4591 free_devmode(printers[i].devmode);
4593 SAFE_FREE(printers);
4594 return WERR_INSUFFICIENT_BUFFER;
4597 /* fill the buffer with the structures */
4598 for (i=0; i<*returned; i++)
4599 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4602 for (i=0; i<*returned; i++) {
4603 free_devmode(printers[i].devmode);
4605 SAFE_FREE(printers);
4607 if (*needed > offered) {
4609 return WERR_INSUFFICIENT_BUFFER;
4615 /********************************************************************
4616 * handle enumeration of printers at level 1
4617 ********************************************************************/
4619 static WERROR enumprinters_level1( uint32 flags, fstring name,
4620 NEW_BUFFER *buffer, uint32 offered,
4621 uint32 *needed, uint32 *returned)
4623 /* Not all the flags are equals */
4625 if (flags & PRINTER_ENUM_LOCAL)
4626 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4628 if (flags & PRINTER_ENUM_NAME)
4629 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4631 #if 0 /* JERRY - disabled for now */
4632 if (flags & PRINTER_ENUM_REMOTE)
4633 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4636 if (flags & PRINTER_ENUM_NETWORK)
4637 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4639 return WERR_OK; /* NT4sp5 does that */
4642 /********************************************************************
4643 * handle enumeration of printers at level 2
4644 ********************************************************************/
4646 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4647 NEW_BUFFER *buffer, uint32 offered,
4648 uint32 *needed, uint32 *returned)
4650 char *s = servername;
4652 if (flags & PRINTER_ENUM_LOCAL) {
4653 return enum_all_printers_info_2(buffer, offered, needed, returned);
4656 if (flags & PRINTER_ENUM_NAME) {
4657 if ((servername[0] == '\\') && (servername[1] == '\\'))
4659 if (is_myname_or_ipaddr(s))
4660 return enum_all_printers_info_2(buffer, offered, needed, returned);
4662 return WERR_INVALID_NAME;
4665 if (flags & PRINTER_ENUM_REMOTE)
4666 return WERR_UNKNOWN_LEVEL;
4671 /********************************************************************
4672 * handle enumeration of printers at level 5
4673 ********************************************************************/
4675 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4676 NEW_BUFFER *buffer, uint32 offered,
4677 uint32 *needed, uint32 *returned)
4679 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4683 /********************************************************************
4684 * api_spoolss_enumprinters
4686 * called from api_spoolss_enumprinters (see this to understand)
4687 ********************************************************************/
4689 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4691 uint32 flags = q_u->flags;
4692 UNISTR2 *servername = &q_u->servername;
4693 uint32 level = q_u->level;
4694 NEW_BUFFER *buffer = NULL;
4695 uint32 offered = q_u->offered;
4696 uint32 *needed = &r_u->needed;
4697 uint32 *returned = &r_u->returned;
4701 /* that's an [in out] buffer */
4702 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4703 buffer = r_u->buffer;
4705 DEBUG(4,("_spoolss_enumprinters\n"));
4712 * flags==PRINTER_ENUM_NAME
4713 * if name=="" then enumerates all printers
4714 * if name!="" then enumerate the printer
4715 * flags==PRINTER_ENUM_REMOTE
4716 * name is NULL, enumerate printers
4717 * Level 2: name!="" enumerates printers, name can't be NULL
4718 * Level 3: doesn't exist
4719 * Level 4: does a local registry lookup
4720 * Level 5: same as Level 2
4723 unistr2_to_ascii(name, servername, sizeof(name)-1);
4728 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4730 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4732 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4737 return WERR_UNKNOWN_LEVEL;
4740 /****************************************************************************
4741 ****************************************************************************/
4743 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4745 PRINTER_INFO_0 *printer=NULL;
4747 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4750 construct_printer_info_0(print_hnd, printer, snum);
4752 /* check the required size. */
4753 *needed += spoolss_size_printer_info_0(printer);
4755 if (!alloc_buffer_size(buffer, *needed)) {
4757 return WERR_INSUFFICIENT_BUFFER;
4760 /* fill the buffer with the structures */
4761 smb_io_printer_info_0("", buffer, printer, 0);
4766 if (*needed > offered) {
4767 return WERR_INSUFFICIENT_BUFFER;
4773 /****************************************************************************
4774 ****************************************************************************/
4776 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4778 PRINTER_INFO_1 *printer=NULL;
4780 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4783 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4785 /* check the required size. */
4786 *needed += spoolss_size_printer_info_1(printer);
4788 if (!alloc_buffer_size(buffer, *needed)) {
4790 return WERR_INSUFFICIENT_BUFFER;
4793 /* fill the buffer with the structures */
4794 smb_io_printer_info_1("", buffer, printer, 0);
4799 if (*needed > offered) {
4800 return WERR_INSUFFICIENT_BUFFER;
4806 /****************************************************************************
4807 ****************************************************************************/
4809 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4811 PRINTER_INFO_2 *printer=NULL;
4813 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4816 construct_printer_info_2(print_hnd, printer, snum);
4818 /* check the required size. */
4819 *needed += spoolss_size_printer_info_2(printer);
4821 if (!alloc_buffer_size(buffer, *needed)) {
4822 free_printer_info_2(printer);
4823 return WERR_INSUFFICIENT_BUFFER;
4826 /* fill the buffer with the structures */
4827 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4828 free_printer_info_2(printer);
4833 free_printer_info_2(printer);
4835 if (*needed > offered) {
4836 return WERR_INSUFFICIENT_BUFFER;
4842 /****************************************************************************
4843 ****************************************************************************/
4845 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4847 PRINTER_INFO_3 *printer=NULL;
4849 if (!construct_printer_info_3(print_hnd, &printer, snum))
4852 /* check the required size. */
4853 *needed += spoolss_size_printer_info_3(printer);
4855 if (!alloc_buffer_size(buffer, *needed)) {
4856 free_printer_info_3(printer);
4857 return WERR_INSUFFICIENT_BUFFER;
4860 /* fill the buffer with the structures */
4861 smb_io_printer_info_3("", buffer, printer, 0);
4864 free_printer_info_3(printer);
4866 if (*needed > offered) {
4867 return WERR_INSUFFICIENT_BUFFER;
4873 /****************************************************************************
4874 ****************************************************************************/
4876 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4878 PRINTER_INFO_4 *printer=NULL;
4880 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4883 if (!construct_printer_info_4(print_hnd, printer, snum))
4886 /* check the required size. */
4887 *needed += spoolss_size_printer_info_4(printer);
4889 if (!alloc_buffer_size(buffer, *needed)) {
4890 free_printer_info_4(printer);
4891 return WERR_INSUFFICIENT_BUFFER;
4894 /* fill the buffer with the structures */
4895 smb_io_printer_info_4("", buffer, printer, 0);
4898 free_printer_info_4(printer);
4900 if (*needed > offered) {
4901 return WERR_INSUFFICIENT_BUFFER;
4907 /****************************************************************************
4908 ****************************************************************************/
4910 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4912 PRINTER_INFO_5 *printer=NULL;
4914 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4917 if (!construct_printer_info_5(print_hnd, printer, snum))
4920 /* check the required size. */
4921 *needed += spoolss_size_printer_info_5(printer);
4923 if (!alloc_buffer_size(buffer, *needed)) {
4924 free_printer_info_5(printer);
4925 return WERR_INSUFFICIENT_BUFFER;
4928 /* fill the buffer with the structures */
4929 smb_io_printer_info_5("", buffer, printer, 0);
4932 free_printer_info_5(printer);
4934 if (*needed > offered) {
4935 return WERR_INSUFFICIENT_BUFFER;
4941 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4943 PRINTER_INFO_7 *printer=NULL;
4945 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4948 if (!construct_printer_info_7(print_hnd, printer, snum))
4951 /* check the required size. */
4952 *needed += spoolss_size_printer_info_7(printer);
4954 if (!alloc_buffer_size(buffer, *needed)) {
4955 free_printer_info_7(printer);
4956 return WERR_INSUFFICIENT_BUFFER;
4959 /* fill the buffer with the structures */
4960 smb_io_printer_info_7("", buffer, printer, 0);
4963 free_printer_info_7(printer);
4965 if (*needed > offered) {
4966 return WERR_INSUFFICIENT_BUFFER;
4972 /****************************************************************************
4973 ****************************************************************************/
4975 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4977 POLICY_HND *handle = &q_u->handle;
4978 uint32 level = q_u->level;
4979 NEW_BUFFER *buffer = NULL;
4980 uint32 offered = q_u->offered;
4981 uint32 *needed = &r_u->needed;
4982 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4986 /* that's an [in out] buffer */
4987 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4988 buffer = r_u->buffer;
4992 if (!get_printer_snum(p, handle, &snum))
4997 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4999 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5001 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5003 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5005 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5007 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5009 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5011 return WERR_UNKNOWN_LEVEL;
5014 /********************************************************************
5015 * fill a DRIVER_INFO_1 struct
5016 ********************************************************************/
5018 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5020 init_unistr( &info->name, driver.info_3->name);
5023 /********************************************************************
5024 * construct_printer_driver_info_1
5025 ********************************************************************/
5027 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5029 NT_PRINTER_INFO_LEVEL *printer = NULL;
5030 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5032 ZERO_STRUCT(driver);
5034 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5035 return WERR_INVALID_PRINTER_NAME;
5037 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5038 return WERR_UNKNOWN_PRINTER_DRIVER;
5040 fill_printer_driver_info_1(info, driver, servername, architecture);
5042 free_a_printer(&printer,2);
5047 /********************************************************************
5048 * construct_printer_driver_info_2
5049 * fill a printer_info_2 struct
5050 ********************************************************************/
5052 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5056 info->version=driver.info_3->cversion;
5058 init_unistr( &info->name, driver.info_3->name );
5059 init_unistr( &info->architecture, driver.info_3->environment );
5062 if (strlen(driver.info_3->driverpath)) {
5063 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5064 init_unistr( &info->driverpath, temp );
5066 init_unistr( &info->driverpath, "" );
5068 if (strlen(driver.info_3->datafile)) {
5069 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5070 init_unistr( &info->datafile, temp );
5072 init_unistr( &info->datafile, "" );
5074 if (strlen(driver.info_3->configfile)) {
5075 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5076 init_unistr( &info->configfile, temp );
5078 init_unistr( &info->configfile, "" );
5081 /********************************************************************
5082 * construct_printer_driver_info_2
5083 * fill a printer_info_2 struct
5084 ********************************************************************/
5086 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5088 NT_PRINTER_INFO_LEVEL *printer = NULL;
5089 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5091 ZERO_STRUCT(printer);
5092 ZERO_STRUCT(driver);
5094 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5095 return WERR_INVALID_PRINTER_NAME;
5097 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5098 return WERR_UNKNOWN_PRINTER_DRIVER;
5100 fill_printer_driver_info_2(info, driver, servername);
5102 free_a_printer(&printer,2);
5107 /********************************************************************
5108 * copy a strings array and convert to UNICODE
5110 * convert an array of ascii string to a UNICODE string
5111 ********************************************************************/
5113 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5121 DEBUG(6,("init_unistr_array\n"));
5132 v = ""; /* hack to handle null lists */
5135 /* hack to allow this to be used in places other than when generating
5136 the list of dependent files */
5139 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5143 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5145 /* add one extra unit16 for the second terminating NULL */
5147 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5148 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5156 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5161 /* special case for ""; we need to add both NULL's here */
5163 (*uni_array)[j++]=0x0000;
5164 (*uni_array)[j]=0x0000;
5167 DEBUGADD(6,("last one:done\n"));
5169 /* return size of array in uint16's */
5174 /********************************************************************
5175 * construct_printer_info_3
5176 * fill a printer_info_3 struct
5177 ********************************************************************/
5179 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5185 info->version=driver.info_3->cversion;
5187 init_unistr( &info->name, driver.info_3->name );
5188 init_unistr( &info->architecture, driver.info_3->environment );
5190 if (strlen(driver.info_3->driverpath)) {
5191 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5192 init_unistr( &info->driverpath, temp );
5194 init_unistr( &info->driverpath, "" );
5196 if (strlen(driver.info_3->datafile)) {
5197 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5198 init_unistr( &info->datafile, temp );
5200 init_unistr( &info->datafile, "" );
5202 if (strlen(driver.info_3->configfile)) {
5203 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5204 init_unistr( &info->configfile, temp );
5206 init_unistr( &info->configfile, "" );
5208 if (strlen(driver.info_3->helpfile)) {
5209 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5210 init_unistr( &info->helpfile, temp );
5212 init_unistr( &info->helpfile, "" );
5214 init_unistr( &info->monitorname, driver.info_3->monitorname );
5215 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5217 info->dependentfiles=NULL;
5218 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5221 /********************************************************************
5222 * construct_printer_info_3
5223 * fill a printer_info_3 struct
5224 ********************************************************************/
5226 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5228 NT_PRINTER_INFO_LEVEL *printer = NULL;
5229 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5231 ZERO_STRUCT(driver);
5233 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5234 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5235 if (!W_ERROR_IS_OK(status))
5236 return WERR_INVALID_PRINTER_NAME;
5238 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5239 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5244 * I put this code in during testing. Helpful when commenting out the
5245 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5246 * as win2k always queries the driver using an infor level of 6.
5247 * I've left it in (but ifdef'd out) because I'll probably
5248 * use it in experimentation again in the future. --jerry 22/01/2002
5251 if (!W_ERROR_IS_OK(status)) {
5253 * Is this a W2k client ?
5256 /* Yes - try again with a WinNT driver. */
5258 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5259 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5263 if (!W_ERROR_IS_OK(status)) {
5264 free_a_printer(&printer,2);
5265 return WERR_UNKNOWN_PRINTER_DRIVER;
5273 fill_printer_driver_info_3(info, driver, servername);
5275 free_a_printer(&printer,2);
5280 /********************************************************************
5281 * construct_printer_info_6
5282 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5283 ********************************************************************/
5285 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5291 memset(&nullstr, '\0', sizeof(fstring));
5293 info->version=driver.info_3->cversion;
5295 init_unistr( &info->name, driver.info_3->name );
5296 init_unistr( &info->architecture, driver.info_3->environment );
5298 if (strlen(driver.info_3->driverpath)) {
5299 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5300 init_unistr( &info->driverpath, temp );
5302 init_unistr( &info->driverpath, "" );
5304 if (strlen(driver.info_3->datafile)) {
5305 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5306 init_unistr( &info->datafile, temp );
5308 init_unistr( &info->datafile, "" );
5310 if (strlen(driver.info_3->configfile)) {
5311 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5312 init_unistr( &info->configfile, temp );
5314 init_unistr( &info->configfile, "" );
5316 if (strlen(driver.info_3->helpfile)) {
5317 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5318 init_unistr( &info->helpfile, temp );
5320 init_unistr( &info->helpfile, "" );
5322 init_unistr( &info->monitorname, driver.info_3->monitorname );
5323 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5325 info->dependentfiles = NULL;
5326 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5328 info->previousdrivernames=NULL;
5329 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5331 info->driver_date.low=0;
5332 info->driver_date.high=0;
5335 info->driver_version_low=0;
5336 info->driver_version_high=0;
5338 init_unistr( &info->mfgname, "");
5339 init_unistr( &info->oem_url, "");
5340 init_unistr( &info->hardware_id, "");
5341 init_unistr( &info->provider, "");
5344 /********************************************************************
5345 * construct_printer_info_6
5346 * fill a printer_info_6 struct
5347 ********************************************************************/
5349 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5350 fstring servername, fstring architecture, uint32 version)
5352 NT_PRINTER_INFO_LEVEL *printer = NULL;
5353 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5356 ZERO_STRUCT(driver);
5358 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5360 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5362 if (!W_ERROR_IS_OK(status))
5363 return WERR_INVALID_PRINTER_NAME;
5365 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5367 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5369 if (!W_ERROR_IS_OK(status))
5372 * Is this a W2k client ?
5376 free_a_printer(&printer,2);
5377 return WERR_UNKNOWN_PRINTER_DRIVER;
5380 /* Yes - try again with a WinNT driver. */
5382 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5383 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5384 if (!W_ERROR_IS_OK(status)) {
5385 free_a_printer(&printer,2);
5386 return WERR_UNKNOWN_PRINTER_DRIVER;
5390 fill_printer_driver_info_6(info, driver, servername);
5392 free_a_printer(&printer,2);
5393 free_a_printer_driver(driver, 3);
5398 /****************************************************************************
5399 ****************************************************************************/
5401 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5403 SAFE_FREE(info->dependentfiles);
5406 /****************************************************************************
5407 ****************************************************************************/
5409 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5411 SAFE_FREE(info->dependentfiles);
5415 /****************************************************************************
5416 ****************************************************************************/
5418 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5420 DRIVER_INFO_1 *info=NULL;
5423 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5426 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5427 if (!W_ERROR_IS_OK(status)) {
5432 /* check the required size. */
5433 *needed += spoolss_size_printer_driver_info_1(info);
5435 if (!alloc_buffer_size(buffer, *needed)) {
5437 return WERR_INSUFFICIENT_BUFFER;
5440 /* fill the buffer with the structures */
5441 smb_io_printer_driver_info_1("", buffer, info, 0);
5446 if (*needed > offered)
5447 return WERR_INSUFFICIENT_BUFFER;
5452 /****************************************************************************
5453 ****************************************************************************/
5455 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5457 DRIVER_INFO_2 *info=NULL;
5460 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5463 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5464 if (!W_ERROR_IS_OK(status)) {
5469 /* check the required size. */
5470 *needed += spoolss_size_printer_driver_info_2(info);
5472 if (!alloc_buffer_size(buffer, *needed)) {
5474 return WERR_INSUFFICIENT_BUFFER;
5477 /* fill the buffer with the structures */
5478 smb_io_printer_driver_info_2("", buffer, info, 0);
5483 if (*needed > offered)
5484 return WERR_INSUFFICIENT_BUFFER;
5489 /****************************************************************************
5490 ****************************************************************************/
5492 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5499 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5500 if (!W_ERROR_IS_OK(status)) {
5504 /* check the required size. */
5505 *needed += spoolss_size_printer_driver_info_3(&info);
5507 if (!alloc_buffer_size(buffer, *needed)) {
5508 free_printer_driver_info_3(&info);
5509 return WERR_INSUFFICIENT_BUFFER;
5512 /* fill the buffer with the structures */
5513 smb_io_printer_driver_info_3("", buffer, &info, 0);
5515 free_printer_driver_info_3(&info);
5517 if (*needed > offered)
5518 return WERR_INSUFFICIENT_BUFFER;
5523 /****************************************************************************
5524 ****************************************************************************/
5526 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5533 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5534 if (!W_ERROR_IS_OK(status)) {
5538 /* check the required size. */
5539 *needed += spoolss_size_printer_driver_info_6(&info);
5541 if (!alloc_buffer_size(buffer, *needed)) {
5542 free_printer_driver_info_6(&info);
5543 return WERR_INSUFFICIENT_BUFFER;
5546 /* fill the buffer with the structures */
5547 smb_io_printer_driver_info_6("", buffer, &info, 0);
5549 free_printer_driver_info_6(&info);
5551 if (*needed > offered)
5552 return WERR_INSUFFICIENT_BUFFER;
5557 /****************************************************************************
5558 ****************************************************************************/
5560 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5562 POLICY_HND *handle = &q_u->handle;
5563 UNISTR2 *uni_arch = &q_u->architecture;
5564 uint32 level = q_u->level;
5565 uint32 clientmajorversion = q_u->clientmajorversion;
5566 NEW_BUFFER *buffer = NULL;
5567 uint32 offered = q_u->offered;
5568 uint32 *needed = &r_u->needed;
5569 uint32 *servermajorversion = &r_u->servermajorversion;
5570 uint32 *serverminorversion = &r_u->serverminorversion;
5571 Printer_entry *printer;
5574 fstring architecture;
5577 /* that's an [in out] buffer */
5578 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5579 buffer = r_u->buffer;
5581 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5583 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5584 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5585 return WERR_INVALID_PRINTER_NAME;
5589 *servermajorversion = 0;
5590 *serverminorversion = 0;
5592 fstrcpy(servername, get_server_name( printer ));
5593 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5595 if (!get_printer_snum(p, handle, &snum))
5600 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5602 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5604 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5606 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5609 /* apparently this call is the equivalent of
5610 EnumPrinterDataEx() for the DsDriver key */
5615 return WERR_UNKNOWN_LEVEL;
5618 /****************************************************************************
5619 ****************************************************************************/
5621 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5623 POLICY_HND *handle = &q_u->handle;
5625 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5628 DEBUG(3,("Error in startpageprinter printer handle\n"));
5632 Printer->page_started=True;
5636 /****************************************************************************
5637 ****************************************************************************/
5639 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5641 POLICY_HND *handle = &q_u->handle;
5644 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5647 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5651 if (!get_printer_snum(p, handle, &snum))
5654 Printer->page_started=False;
5655 print_job_endpage(snum, Printer->jobid);
5660 /********************************************************************
5661 * api_spoolss_getprinter
5662 * called from the spoolss dispatcher
5664 ********************************************************************/
5666 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5668 POLICY_HND *handle = &q_u->handle;
5669 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5670 uint32 *jobid = &r_u->jobid;
5672 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5676 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5677 struct current_user user;
5680 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5684 get_current_user(&user, p);
5687 * a nice thing with NT is it doesn't listen to what you tell it.
5688 * when asked to send _only_ RAW datas, it tries to send datas
5691 * So I add checks like in NT Server ...
5694 if (info_1->p_datatype != 0) {
5695 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5696 if (strcmp(datatype, "RAW") != 0) {
5698 return WERR_INVALID_DATATYPE;
5702 /* get the share number of the printer */
5703 if (!get_printer_snum(p, handle, &snum)) {
5707 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5709 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5711 /* An error occured in print_job_start() so return an appropriate
5714 if (Printer->jobid == -1) {
5715 return map_werror_from_unix(errno);
5718 Printer->document_started=True;
5719 (*jobid) = Printer->jobid;
5724 /********************************************************************
5725 * api_spoolss_getprinter
5726 * called from the spoolss dispatcher
5728 ********************************************************************/
5730 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5732 POLICY_HND *handle = &q_u->handle;
5734 return _spoolss_enddocprinter_internal(p, handle);
5737 /****************************************************************************
5738 ****************************************************************************/
5740 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5742 POLICY_HND *handle = &q_u->handle;
5743 uint32 buffer_size = q_u->buffer_size;
5744 uint8 *buffer = q_u->buffer;
5745 uint32 *buffer_written = &q_u->buffer_size2;
5747 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5750 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5751 r_u->buffer_written = q_u->buffer_size2;
5755 if (!get_printer_snum(p, handle, &snum))
5758 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5759 if (*buffer_written == -1) {
5760 r_u->buffer_written = 0;
5761 if (errno == ENOSPC)
5762 return WERR_NO_SPOOL_SPACE;
5764 return WERR_ACCESS_DENIED;
5767 r_u->buffer_written = q_u->buffer_size2;
5772 /********************************************************************
5773 * api_spoolss_getprinter
5774 * called from the spoolss dispatcher
5776 ********************************************************************/
5778 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5781 struct current_user user;
5783 WERROR errcode = WERR_BADFUNC;
5784 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5786 get_current_user(&user, p);
5789 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5793 if (!get_printer_snum(p, handle, &snum))
5797 case PRINTER_CONTROL_PAUSE:
5798 if (print_queue_pause(&user, snum, &errcode)) {
5802 case PRINTER_CONTROL_RESUME:
5803 case PRINTER_CONTROL_UNPAUSE:
5804 if (print_queue_resume(&user, snum, &errcode)) {
5808 case PRINTER_CONTROL_PURGE:
5809 if (print_queue_purge(&user, snum, &errcode)) {
5814 return WERR_UNKNOWN_LEVEL;
5820 /********************************************************************
5821 * api_spoolss_abortprinter
5822 * From MSDN: "Deletes printer's spool file if printer is configured
5824 ********************************************************************/
5826 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5828 POLICY_HND *handle = &q_u->handle;
5829 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5831 struct current_user user;
5832 WERROR errcode = WERR_OK;
5835 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5839 if (!get_printer_snum(p, handle, &snum))
5842 get_current_user( &user, p );
5844 print_job_delete( &user, snum, Printer->jobid, &errcode );
5849 /********************************************************************
5850 * called by spoolss_api_setprinter
5851 * when updating a printer description
5852 ********************************************************************/
5854 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5855 const SPOOL_PRINTER_INFO_LEVEL *info,
5856 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5858 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5859 struct current_user user;
5863 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5865 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5866 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5867 OUR_HANDLE(handle)));
5869 result = WERR_BADFID;
5873 /* NT seems to like setting the security descriptor even though
5874 nothing may have actually changed. */
5876 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5878 if (DEBUGLEVEL >= 10) {
5882 the_acl = old_secdesc_ctr->sec->dacl;
5883 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5884 PRINTERNAME(snum), the_acl->num_aces));
5886 for (i = 0; i < the_acl->num_aces; i++) {
5889 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5891 DEBUG(10, ("%s 0x%08x\n", sid_str,
5892 the_acl->ace[i].info.mask));
5895 the_acl = secdesc_ctr->sec->dacl;
5898 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5899 PRINTERNAME(snum), the_acl->num_aces));
5901 for (i = 0; i < the_acl->num_aces; i++) {
5904 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5906 DEBUG(10, ("%s 0x%08x\n", sid_str,
5907 the_acl->ace[i].info.mask));
5910 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5914 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5916 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5921 /* Work out which user is performing the operation */
5923 get_current_user(&user, p);
5925 /* Check the user has permissions to change the security
5926 descriptor. By experimentation with two NT machines, the user
5927 requires Full Access to the printer to change security
5930 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5931 result = WERR_ACCESS_DENIED;
5935 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5942 /********************************************************************
5943 Canonicalize printer info from a client
5945 ATTN: It does not matter what we set the servername to hear
5946 since we do the necessary work in get_a_printer() to set it to
5947 the correct value based on what the client sent in the
5948 _spoolss_open_printer_ex().
5949 ********************************************************************/
5951 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5953 fstring printername;
5956 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5957 "portname=%s drivername=%s comment=%s location=%s\n",
5958 info->servername, info->printername, info->sharename,
5959 info->portname, info->drivername, info->comment, info->location));
5961 /* we force some elements to "correct" values */
5962 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5963 fstrcpy(info->sharename, lp_servicename(snum));
5965 /* make sure printername is in \\server\printername format */
5967 fstrcpy( printername, info->printername );
5969 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5970 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5974 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5975 global_myname(), p );
5977 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5978 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5985 /****************************************************************************
5986 ****************************************************************************/
5988 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5990 extern userdom_struct current_user_info;
5991 char *cmd = lp_addprinter_cmd();
5997 fstring remote_machine = "%m";
5999 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6001 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6002 cmd, printer->info_2->printername, printer->info_2->sharename,
6003 printer->info_2->portname, printer->info_2->drivername,
6004 printer->info_2->location, printer->info_2->comment, remote_machine);
6006 DEBUG(10,("Running [%s]\n", command));
6007 ret = smbrun(command, &fd);
6008 DEBUGADD(10,("returned [%d]\n", ret));
6017 /* Get lines and convert them back to dos-codepage */
6018 qlines = fd_lines_load(fd, &numlines);
6019 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6023 /* Set the portname to what the script says the portname should be. */
6024 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6025 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6027 /* Send SIGHUP to process group... is there a better way? */
6030 /* reload our services immediately */
6031 reload_services( False );
6034 file_lines_free(qlines);
6038 /********************************************************************
6039 * Called by spoolss_api_setprinter
6040 * when updating a printer description.
6041 ********************************************************************/
6043 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6044 const SPOOL_PRINTER_INFO_LEVEL *info,
6045 DEVICEMODE *devmode)
6048 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6049 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6054 DEBUG(8,("update_printer\n"));
6059 result = WERR_BADFID;
6063 if (!get_printer_snum(p, handle, &snum)) {
6064 result = WERR_BADFID;
6068 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6069 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6070 result = WERR_BADFID;
6074 DEBUGADD(8,("Converting info_2 struct\n"));
6077 * convert_printer_info converts the incoming
6078 * info from the client and overwrites the info
6079 * just read from the tdb in the pointer 'printer'.
6082 if (!convert_printer_info(info, printer, level)) {
6083 result = WERR_NOMEM;
6088 /* we have a valid devmode
6089 convert it and link it*/
6091 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6092 if (!convert_devicemode(printer->info_2->printername, devmode,
6093 &printer->info_2->devmode)) {
6094 result = WERR_NOMEM;
6099 /* Do sanity check on the requested changes for Samba */
6101 if (!check_printer_ok(printer->info_2, snum)) {
6102 result = WERR_INVALID_PARAM;
6106 /* FIXME!!! If the driver has changed we really should verify that
6107 it is installed before doing much else --jerry */
6109 /* Check calling user has permission to update printer description */
6111 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6112 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6113 result = WERR_ACCESS_DENIED;
6117 /* Call addprinter hook */
6118 /* Check changes to see if this is really needed */
6120 if ( *lp_addprinter_cmd()
6121 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6122 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6123 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6124 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6126 if ( !add_printer_hook(printer) ) {
6127 result = WERR_ACCESS_DENIED;
6132 * make sure we actually reload the services after
6133 * this as smb.conf could have a new section in it
6134 * .... shouldn't .... but could
6136 reload_services(False);
6140 * When a *new* driver is bound to a printer, the drivername is used to
6141 * lookup previously saved driver initialization info, which is then
6142 * bound to the printer, simulating what happens in the Windows arch.
6144 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6146 if (!set_driver_init(printer, 2))
6148 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6149 printer->info_2->drivername));
6152 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6153 printer->info_2->drivername));
6155 notify_printer_driver(snum, printer->info_2->drivername);
6159 * flag which changes actually occured. This is a small subset of
6160 * all the possible changes. We also have to update things in the
6164 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6165 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6166 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6167 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6169 notify_printer_comment(snum, printer->info_2->comment);
6172 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6173 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6174 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6175 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6177 notify_printer_sharename(snum, printer->info_2->sharename);
6180 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6183 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6186 pname = printer->info_2->printername;
6189 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6190 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6191 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6193 notify_printer_printername( snum, pname );
6196 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6197 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6198 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6199 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6201 notify_printer_port(snum, printer->info_2->portname);
6204 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6205 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6206 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6207 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6209 notify_printer_location(snum, printer->info_2->location);
6212 /* here we need to update some more DsSpooler keys */
6213 /* uNCName, serverName, shortServerName */
6215 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6216 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6217 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6218 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6219 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6221 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6222 global_myname(), printer->info_2->sharename );
6223 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6224 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6225 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6227 /* Update printer info */
6228 result = mod_a_printer(printer, 2);
6231 free_a_printer(&printer, 2);
6232 free_a_printer(&old_printer, 2);
6238 /****************************************************************************
6239 ****************************************************************************/
6240 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6241 const SPOOL_PRINTER_INFO_LEVEL *info)
6244 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6246 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6248 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6253 if (!get_printer_snum(p, handle, &snum))
6256 nt_printer_publish(Printer, snum, info7->action);
6260 return WERR_UNKNOWN_LEVEL;
6263 /****************************************************************************
6264 ****************************************************************************/
6266 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6268 POLICY_HND *handle = &q_u->handle;
6269 uint32 level = q_u->level;
6270 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6271 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6272 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6273 uint32 command = q_u->command;
6276 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6279 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6283 /* check the level */
6286 return control_printer(handle, command, p);
6288 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6289 if (!W_ERROR_IS_OK(result))
6292 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6295 return update_printer_sec(handle, level, info, p,
6298 return publish_or_unpublish_printer(p, handle, info);
6300 return WERR_UNKNOWN_LEVEL;
6304 /****************************************************************************
6305 ****************************************************************************/
6307 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6309 POLICY_HND *handle = &q_u->handle;
6310 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6313 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6317 if (Printer->notify.client_connected==True) {
6320 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6322 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6323 !get_printer_snum(p, handle, &snum) )
6326 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6329 Printer->notify.flags=0;
6330 Printer->notify.options=0;
6331 Printer->notify.localmachine[0]='\0';
6332 Printer->notify.printerlocal=0;
6333 if (Printer->notify.option)
6334 free_spool_notify_option(&Printer->notify.option);
6335 Printer->notify.client_connected=False;
6340 /****************************************************************************
6341 ****************************************************************************/
6343 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6345 /* that's an [in out] buffer (despite appearences to the contrary) */
6346 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6349 return WERR_INVALID_PARAM; /* this is what a NT server
6350 returns for AddJob. AddJob
6351 must fail on non-local
6355 /****************************************************************************
6356 ****************************************************************************/
6358 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6359 int position, int snum,
6360 NT_PRINTER_INFO_LEVEL *ntprinter)
6364 t=gmtime(&queue->time);
6366 job_info->jobid=queue->job;
6367 init_unistr(&job_info->printername, lp_servicename(snum));
6368 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6369 init_unistr(&job_info->username, queue->fs_user);
6370 init_unistr(&job_info->document, queue->fs_file);
6371 init_unistr(&job_info->datatype, "RAW");
6372 init_unistr(&job_info->text_status, "");
6373 job_info->status=nt_printj_status(queue->status);
6374 job_info->priority=queue->priority;
6375 job_info->position=position;
6376 job_info->totalpages=queue->page_count;
6377 job_info->pagesprinted=0;
6379 make_systemtime(&job_info->submitted, t);
6382 /****************************************************************************
6383 ****************************************************************************/
6385 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6386 int position, int snum,
6387 NT_PRINTER_INFO_LEVEL *ntprinter,
6388 DEVICEMODE *devmode)
6392 t=gmtime(&queue->time);
6394 job_info->jobid=queue->job;
6396 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6398 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6399 init_unistr(&job_info->username, queue->fs_user);
6400 init_unistr(&job_info->document, queue->fs_file);
6401 init_unistr(&job_info->notifyname, queue->fs_user);
6402 init_unistr(&job_info->datatype, "RAW");
6403 init_unistr(&job_info->printprocessor, "winprint");
6404 init_unistr(&job_info->parameters, "");
6405 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6406 init_unistr(&job_info->text_status, "");
6408 /* and here the security descriptor */
6410 job_info->status=nt_printj_status(queue->status);
6411 job_info->priority=queue->priority;
6412 job_info->position=position;
6413 job_info->starttime=0;
6414 job_info->untiltime=0;
6415 job_info->totalpages=queue->page_count;
6416 job_info->size=queue->size;
6417 make_systemtime(&(job_info->submitted), t);
6418 job_info->timeelapsed=0;
6419 job_info->pagesprinted=0;
6421 job_info->devmode = devmode;
6426 /****************************************************************************
6427 Enumjobs at level 1.
6428 ****************************************************************************/
6430 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6431 NT_PRINTER_INFO_LEVEL *ntprinter,
6432 NEW_BUFFER *buffer, uint32 offered,
6433 uint32 *needed, uint32 *returned)
6438 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6445 for (i=0; i<*returned; i++)
6446 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6450 /* check the required size. */
6451 for (i=0; i<*returned; i++)
6452 (*needed) += spoolss_size_job_info_1(&info[i]);
6454 if (!alloc_buffer_size(buffer, *needed)) {
6456 return WERR_INSUFFICIENT_BUFFER;
6459 /* fill the buffer with the structures */
6460 for (i=0; i<*returned; i++)
6461 smb_io_job_info_1("", buffer, &info[i], 0);
6466 if (*needed > offered) {
6468 return WERR_INSUFFICIENT_BUFFER;
6474 /****************************************************************************
6475 Enumjobs at level 2.
6476 ****************************************************************************/
6478 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6479 NT_PRINTER_INFO_LEVEL *ntprinter,
6480 NEW_BUFFER *buffer, uint32 offered,
6481 uint32 *needed, uint32 *returned)
6483 JOB_INFO_2 *info = NULL;
6486 DEVICEMODE *devmode = NULL;
6488 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6491 result = WERR_NOMEM;
6495 /* this should not be a failure condition if the devmode is NULL */
6497 devmode = construct_dev_mode(snum);
6499 for (i=0; i<*returned; i++)
6500 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6503 free_a_printer(&ntprinter, 2);
6506 /* check the required size. */
6507 for (i=0; i<*returned; i++)
6508 (*needed) += spoolss_size_job_info_2(&info[i]);
6510 if (*needed > offered) {
6512 result = WERR_INSUFFICIENT_BUFFER;
6516 if (!alloc_buffer_size(buffer, *needed)) {
6518 result = WERR_INSUFFICIENT_BUFFER;
6522 /* fill the buffer with the structures */
6523 for (i=0; i<*returned; i++)
6524 smb_io_job_info_2("", buffer, &info[i], 0);
6529 free_a_printer(&ntprinter, 2);
6530 free_devmode(devmode);
6538 /****************************************************************************
6540 ****************************************************************************/
6542 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6544 POLICY_HND *handle = &q_u->handle;
6545 uint32 level = q_u->level;
6546 NEW_BUFFER *buffer = NULL;
6547 uint32 offered = q_u->offered;
6548 uint32 *needed = &r_u->needed;
6549 uint32 *returned = &r_u->returned;
6551 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6553 print_status_struct prt_status;
6554 print_queue_struct *queue=NULL;
6556 /* that's an [in out] buffer */
6557 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6558 buffer = r_u->buffer;
6560 DEBUG(4,("_spoolss_enumjobs\n"));
6565 /* lookup the printer snum and tdb entry */
6567 if (!get_printer_snum(p, handle, &snum))
6570 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6571 if ( !W_ERROR_IS_OK(wret) )
6574 *returned = print_queue_status(snum, &queue, &prt_status);
6575 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6577 if (*returned == 0) {
6584 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6587 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6592 wret = WERR_UNKNOWN_LEVEL;
6595 free_a_printer( &ntprinter, 2 );
6599 /****************************************************************************
6600 ****************************************************************************/
6602 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6607 /****************************************************************************
6608 ****************************************************************************/
6610 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6612 POLICY_HND *handle = &q_u->handle;
6613 uint32 jobid = q_u->jobid;
6614 uint32 command = q_u->command;
6616 struct current_user user;
6618 WERROR errcode = WERR_BADFUNC;
6620 if (!get_printer_snum(p, handle, &snum)) {
6624 if (!print_job_exists(snum, jobid)) {
6625 return WERR_INVALID_PRINTER_NAME;
6628 get_current_user(&user, p);
6631 case JOB_CONTROL_CANCEL:
6632 case JOB_CONTROL_DELETE:
6633 if (print_job_delete(&user, snum, jobid, &errcode)) {
6637 case JOB_CONTROL_PAUSE:
6638 if (print_job_pause(&user, snum, jobid, &errcode)) {
6642 case JOB_CONTROL_RESTART:
6643 case JOB_CONTROL_RESUME:
6644 if (print_job_resume(&user, snum, jobid, &errcode)) {
6649 return WERR_UNKNOWN_LEVEL;
6655 /****************************************************************************
6656 Enumerates all printer drivers at level 1.
6657 ****************************************************************************/
6659 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6664 fstring *list = NULL;
6666 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6667 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6671 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6673 ndrivers=get_ntdrivers(&list, architecture, version);
6674 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6680 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6681 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6682 SAFE_FREE(driver_info_1);
6686 else driver_info_1 = tdi1;
6689 for (i=0; i<ndrivers; i++) {
6691 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6692 ZERO_STRUCT(driver);
6693 status = get_a_printer_driver(&driver, 3, list[i],
6694 architecture, version);
6695 if (!W_ERROR_IS_OK(status)) {
6699 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6700 free_a_printer_driver(driver, 3);
6703 *returned+=ndrivers;
6707 /* check the required size. */
6708 for (i=0; i<*returned; i++) {
6709 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6710 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6713 if (!alloc_buffer_size(buffer, *needed)) {
6714 SAFE_FREE(driver_info_1);
6715 return WERR_INSUFFICIENT_BUFFER;
6718 /* fill the buffer with the driver structures */
6719 for (i=0; i<*returned; i++) {
6720 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6721 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6724 SAFE_FREE(driver_info_1);
6726 if (*needed > offered) {
6728 return WERR_INSUFFICIENT_BUFFER;
6734 /****************************************************************************
6735 Enumerates all printer drivers at level 2.
6736 ****************************************************************************/
6738 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6743 fstring *list = NULL;
6745 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6746 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6750 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6752 ndrivers=get_ntdrivers(&list, architecture, version);
6753 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6759 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6760 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6761 SAFE_FREE(driver_info_2);
6765 else driver_info_2 = tdi2;
6768 for (i=0; i<ndrivers; i++) {
6771 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6772 ZERO_STRUCT(driver);
6773 status = get_a_printer_driver(&driver, 3, list[i],
6774 architecture, version);
6775 if (!W_ERROR_IS_OK(status)) {
6779 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6780 free_a_printer_driver(driver, 3);
6783 *returned+=ndrivers;
6787 /* check the required size. */
6788 for (i=0; i<*returned; i++) {
6789 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6790 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6793 if (!alloc_buffer_size(buffer, *needed)) {
6794 SAFE_FREE(driver_info_2);
6795 return WERR_INSUFFICIENT_BUFFER;
6798 /* fill the buffer with the form structures */
6799 for (i=0; i<*returned; i++) {
6800 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6801 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6804 SAFE_FREE(driver_info_2);
6806 if (*needed > offered) {
6808 return WERR_INSUFFICIENT_BUFFER;
6814 /****************************************************************************
6815 Enumerates all printer drivers at level 3.
6816 ****************************************************************************/
6818 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6823 fstring *list = NULL;
6825 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6826 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6830 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6832 ndrivers=get_ntdrivers(&list, architecture, version);
6833 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6839 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6840 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6841 SAFE_FREE(driver_info_3);
6845 else driver_info_3 = tdi3;
6848 for (i=0; i<ndrivers; i++) {
6851 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6852 ZERO_STRUCT(driver);
6853 status = get_a_printer_driver(&driver, 3, list[i],
6854 architecture, version);
6855 if (!W_ERROR_IS_OK(status)) {
6859 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6860 free_a_printer_driver(driver, 3);
6863 *returned+=ndrivers;
6867 /* check the required size. */
6868 for (i=0; i<*returned; i++) {
6869 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6870 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6873 if (!alloc_buffer_size(buffer, *needed)) {
6874 SAFE_FREE(driver_info_3);
6875 return WERR_INSUFFICIENT_BUFFER;
6878 /* fill the buffer with the driver structures */
6879 for (i=0; i<*returned; i++) {
6880 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6881 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6884 for (i=0; i<*returned; i++)
6885 SAFE_FREE(driver_info_3[i].dependentfiles);
6887 SAFE_FREE(driver_info_3);
6889 if (*needed > offered) {
6891 return WERR_INSUFFICIENT_BUFFER;
6897 /****************************************************************************
6898 Enumerates all printer drivers.
6899 ****************************************************************************/
6901 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6903 uint32 level = q_u->level;
6904 NEW_BUFFER *buffer = NULL;
6905 uint32 offered = q_u->offered;
6906 uint32 *needed = &r_u->needed;
6907 uint32 *returned = &r_u->returned;
6909 fstring *list = NULL;
6911 fstring architecture;
6913 /* that's an [in out] buffer */
6914 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6915 buffer = r_u->buffer;
6917 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6921 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6922 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6924 if ( !is_myname_or_ipaddr( servername ) )
6925 return WERR_UNKNOWN_PRINTER_DRIVER;
6929 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6931 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6933 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6937 return WERR_UNKNOWN_LEVEL;
6941 /****************************************************************************
6942 ****************************************************************************/
6944 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6946 form->flag=list->flag;
6947 init_unistr(&form->name, list->name);
6948 form->width=list->width;
6949 form->length=list->length;
6950 form->left=list->left;
6951 form->top=list->top;
6952 form->right=list->right;
6953 form->bottom=list->bottom;
6956 /****************************************************************************
6957 ****************************************************************************/
6959 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6961 uint32 level = q_u->level;
6962 NEW_BUFFER *buffer = NULL;
6963 uint32 offered = q_u->offered;
6964 uint32 *needed = &r_u->needed;
6965 uint32 *numofforms = &r_u->numofforms;
6966 uint32 numbuiltinforms;
6968 nt_forms_struct *list=NULL;
6969 nt_forms_struct *builtinlist=NULL;
6974 /* that's an [in out] buffer */
6975 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6976 buffer = r_u->buffer;
6978 DEBUG(4,("_spoolss_enumforms\n"));
6979 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6980 DEBUGADD(5,("Info level [%d]\n", level));
6982 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6983 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6984 *numofforms = get_ntforms(&list);
6985 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6986 *numofforms += numbuiltinforms;
6988 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6992 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6997 /* construct the list of form structures */
6998 for (i=0; i<numbuiltinforms; i++) {
6999 DEBUGADD(6,("Filling form number [%d]\n",i));
7000 fill_form_1(&forms_1[i], &builtinlist[i]);
7003 SAFE_FREE(builtinlist);
7005 for (; i<*numofforms; i++) {
7006 DEBUGADD(6,("Filling form number [%d]\n",i));
7007 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7012 /* check the required size. */
7013 for (i=0; i<numbuiltinforms; i++) {
7014 DEBUGADD(6,("adding form [%d]'s size\n",i));
7015 buffer_size += spoolss_size_form_1(&forms_1[i]);
7017 for (; i<*numofforms; i++) {
7018 DEBUGADD(6,("adding form [%d]'s size\n",i));
7019 buffer_size += spoolss_size_form_1(&forms_1[i]);
7022 *needed=buffer_size;
7024 if (!alloc_buffer_size(buffer, buffer_size)){
7026 return WERR_INSUFFICIENT_BUFFER;
7029 /* fill the buffer with the form structures */
7030 for (i=0; i<numbuiltinforms; i++) {
7031 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7032 smb_io_form_1("", buffer, &forms_1[i], 0);
7034 for (; i<*numofforms; i++) {
7035 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7036 smb_io_form_1("", buffer, &forms_1[i], 0);
7041 if (*needed > offered) {
7043 return WERR_INSUFFICIENT_BUFFER;
7050 SAFE_FREE(builtinlist);
7051 return WERR_UNKNOWN_LEVEL;
7056 /****************************************************************************
7057 ****************************************************************************/
7059 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7061 uint32 level = q_u->level;
7062 UNISTR2 *uni_formname = &q_u->formname;
7063 NEW_BUFFER *buffer = NULL;
7064 uint32 offered = q_u->offered;
7065 uint32 *needed = &r_u->needed;
7067 nt_forms_struct *list=NULL;
7068 nt_forms_struct builtin_form;
7073 int numofforms=0, i=0;
7075 /* that's an [in out] buffer */
7076 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7077 buffer = r_u->buffer;
7079 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7081 DEBUG(4,("_spoolss_getform\n"));
7082 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7083 DEBUGADD(5,("Info level [%d]\n", level));
7085 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7086 if (!foundBuiltin) {
7087 numofforms = get_ntforms(&list);
7088 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7090 if (numofforms == 0)
7097 fill_form_1(&form_1, &builtin_form);
7100 /* Check if the requested name is in the list of form structures */
7101 for (i=0; i<numofforms; i++) {
7103 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7105 if (strequal(form_name, list[i].name)) {
7106 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7107 fill_form_1(&form_1, &list[i]);
7113 if (i == numofforms) {
7117 /* check the required size. */
7119 *needed=spoolss_size_form_1(&form_1);
7121 if (!alloc_buffer_size(buffer, buffer_size)){
7122 return WERR_INSUFFICIENT_BUFFER;
7125 if (*needed > offered) {
7126 return WERR_INSUFFICIENT_BUFFER;
7129 /* fill the buffer with the form structures */
7130 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7131 smb_io_form_1("", buffer, &form_1, 0);
7137 return WERR_UNKNOWN_LEVEL;
7141 /****************************************************************************
7142 ****************************************************************************/
7144 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7146 init_unistr(&port->port_name, name);
7149 /****************************************************************************
7150 ****************************************************************************/
7152 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7154 init_unistr(&port->port_name, name);
7155 init_unistr(&port->monitor_name, "Local Monitor");
7156 init_unistr(&port->description, "Local Port");
7157 port->port_type=PORT_TYPE_WRITE;
7161 /****************************************************************************
7163 ****************************************************************************/
7165 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7167 PORT_INFO_1 *ports=NULL;
7170 if (*lp_enumports_cmd()) {
7171 char *cmd = lp_enumports_cmd();
7178 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7180 DEBUG(10,("Running [%s]\n", command));
7181 ret = smbrun(command, &fd);
7182 DEBUG(10,("Returned [%d]\n", ret));
7186 /* Is this the best error to return here? */
7187 return WERR_ACCESS_DENIED;
7191 qlines = fd_lines_load(fd, &numlines);
7192 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7196 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7197 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7198 dos_errstr(WERR_NOMEM)));
7199 file_lines_free(qlines);
7203 for (i=0; i<numlines; i++) {
7204 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7205 fill_port_1(&ports[i], qlines[i]);
7208 file_lines_free(qlines);
7211 *returned = numlines;
7214 *returned = 1; /* Sole Samba port returned. */
7216 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7219 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7221 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7224 /* check the required size. */
7225 for (i=0; i<*returned; i++) {
7226 DEBUGADD(6,("adding port [%d]'s size\n", i));
7227 *needed += spoolss_size_port_info_1(&ports[i]);
7230 if (!alloc_buffer_size(buffer, *needed)) {
7232 return WERR_INSUFFICIENT_BUFFER;
7235 /* fill the buffer with the ports structures */
7236 for (i=0; i<*returned; i++) {
7237 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7238 smb_io_port_1("", buffer, &ports[i], 0);
7243 if (*needed > offered) {
7245 return WERR_INSUFFICIENT_BUFFER;
7251 /****************************************************************************
7253 ****************************************************************************/
7255 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7257 PORT_INFO_2 *ports=NULL;
7260 if (*lp_enumports_cmd()) {
7261 char *cmd = lp_enumports_cmd();
7270 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7271 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7273 path = lp_lockdir();
7275 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7276 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7279 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7280 ret = smbrun(command, &fd);
7281 DEBUGADD(10,("returned [%d]\n", ret));
7285 /* Is this the best error to return here? */
7286 return WERR_ACCESS_DENIED;
7290 qlines = fd_lines_load(fd, &numlines);
7291 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7295 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7296 file_lines_free(qlines);
7300 for (i=0; i<numlines; i++) {
7301 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7302 fill_port_2(&(ports[i]), qlines[i]);
7305 file_lines_free(qlines);
7308 *returned = numlines;
7314 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7317 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7319 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7322 /* check the required size. */
7323 for (i=0; i<*returned; i++) {
7324 DEBUGADD(6,("adding port [%d]'s size\n", i));
7325 *needed += spoolss_size_port_info_2(&ports[i]);
7328 if (!alloc_buffer_size(buffer, *needed)) {
7330 return WERR_INSUFFICIENT_BUFFER;
7333 /* fill the buffer with the ports structures */
7334 for (i=0; i<*returned; i++) {
7335 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7336 smb_io_port_2("", buffer, &ports[i], 0);
7341 if (*needed > offered) {
7343 return WERR_INSUFFICIENT_BUFFER;
7349 /****************************************************************************
7351 ****************************************************************************/
7353 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7355 uint32 level = q_u->level;
7356 NEW_BUFFER *buffer = NULL;
7357 uint32 offered = q_u->offered;
7358 uint32 *needed = &r_u->needed;
7359 uint32 *returned = &r_u->returned;
7361 /* that's an [in out] buffer */
7362 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7363 buffer = r_u->buffer;
7365 DEBUG(4,("_spoolss_enumports\n"));
7372 return enumports_level_1(buffer, offered, needed, returned);
7374 return enumports_level_2(buffer, offered, needed, returned);
7376 return WERR_UNKNOWN_LEVEL;
7380 /****************************************************************************
7381 ****************************************************************************/
7383 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7384 const SPOOL_PRINTER_INFO_LEVEL *info,
7385 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7386 uint32 user_switch, const SPOOL_USER_CTR *user,
7389 NT_PRINTER_INFO_LEVEL *printer = NULL;
7392 WERROR err = WERR_OK;
7394 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7395 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7399 ZERO_STRUCTP(printer);
7401 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7402 if (!convert_printer_info(info, printer, 2)) {
7403 free_a_printer(&printer, 2);
7407 /* check to see if the printer already exists */
7409 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7410 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7411 printer->info_2->sharename));
7412 free_a_printer(&printer, 2);
7413 return WERR_PRINTER_ALREADY_EXISTS;
7416 /* FIXME!!! smbd should check to see if the driver is installed before
7417 trying to add a printer like this --jerry */
7419 if (*lp_addprinter_cmd() ) {
7420 if ( !add_printer_hook(printer) ) {
7421 free_a_printer(&printer,2);
7422 return WERR_ACCESS_DENIED;
7426 /* use our primary netbios name since get_a_printer() will convert
7427 it to what the client expects on a case by case basis */
7429 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7430 printer->info_2->sharename);
7433 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7434 free_a_printer(&printer,2);
7435 return WERR_ACCESS_DENIED;
7438 /* you must be a printer admin to add a new printer */
7439 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7440 free_a_printer(&printer,2);
7441 return WERR_ACCESS_DENIED;
7445 * Do sanity check on the requested changes for Samba.
7448 if (!check_printer_ok(printer->info_2, snum)) {
7449 free_a_printer(&printer,2);
7450 return WERR_INVALID_PARAM;
7454 * When a printer is created, the drivername bound to the printer is used
7455 * to lookup previously saved driver initialization info, which is then
7456 * bound to the new printer, simulating what happens in the Windows arch.
7461 set_driver_init(printer, 2);
7465 /* A valid devmode was included, convert and link it
7467 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7469 if (!convert_devicemode(printer->info_2->printername, devmode,
7470 &printer->info_2->devmode))
7474 /* write the ASCII on disk */
7475 err = mod_a_printer(printer, 2);
7476 if (!W_ERROR_IS_OK(err)) {
7477 free_a_printer(&printer,2);
7481 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7482 /* Handle open failed - remove addition. */
7483 del_a_printer(printer->info_2->sharename);
7484 free_a_printer(&printer,2);
7485 return WERR_ACCESS_DENIED;
7488 update_c_setprinter(False);
7489 free_a_printer(&printer,2);
7494 /****************************************************************************
7495 ****************************************************************************/
7497 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7499 UNISTR2 *uni_srv_name = &q_u->server_name;
7500 uint32 level = q_u->level;
7501 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7502 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7503 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7504 uint32 user_switch = q_u->user_switch;
7505 SPOOL_USER_CTR *user = &q_u->user_ctr;
7506 POLICY_HND *handle = &r_u->handle;
7510 /* we don't handle yet */
7511 /* but I know what to do ... */
7512 return WERR_UNKNOWN_LEVEL;
7514 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7516 user_switch, user, handle);
7518 return WERR_UNKNOWN_LEVEL;
7522 /****************************************************************************
7523 ****************************************************************************/
7525 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7527 uint32 level = q_u->level;
7528 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7529 WERROR err = WERR_OK;
7530 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7531 struct current_user user;
7532 fstring driver_name;
7535 ZERO_STRUCT(driver);
7537 get_current_user(&user, p);
7539 if (!convert_printer_driver_info(info, &driver, level)) {
7544 DEBUG(5,("Cleaning driver's information\n"));
7545 err = clean_up_driver_struct(driver, level, &user);
7546 if (!W_ERROR_IS_OK(err))
7549 DEBUG(5,("Moving driver to final destination\n"));
7550 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7551 if (W_ERROR_IS_OK(err))
7552 err = WERR_ACCESS_DENIED;
7556 if (add_a_printer_driver(driver, level)!=0) {
7557 err = WERR_ACCESS_DENIED;
7561 /* BEGIN_ADMIN_LOG */
7564 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7565 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7566 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7569 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7570 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7571 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7577 * I think this is where he DrvUpgradePrinter() hook would be
7578 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7579 * server. Right now, we just need to send ourselves a message
7580 * to update each printer bound to this driver. --jerry
7583 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7584 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7589 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7590 * decide if the driver init data should be deleted. The rules are:
7591 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7592 * 2) delete init data only if there is no 2k/Xp driver
7593 * 3) always delete init data
7594 * The generalized rule is always use init data from the highest order driver.
7595 * It is necessary to follow the driver install by an initialization step to
7596 * finish off this process.
7599 version = driver.info_3->cversion;
7600 else if (level == 6)
7601 version = driver.info_6->version;
7606 * 9x printer driver - never delete init data
7609 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7614 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7615 * there is no 2k/Xp driver init data for this driver name.
7619 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7621 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7623 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7625 if (!del_driver_init(driver_name))
7626 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7629 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7631 free_a_printer_driver(driver1,3);
7632 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7639 * 2k or Xp printer driver - always delete init data
7642 if (!del_driver_init(driver_name))
7643 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7647 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7653 free_a_printer_driver(driver, level);
7657 /********************************************************************
7658 * spoolss_addprinterdriverex
7659 ********************************************************************/
7661 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7663 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7664 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7667 * we only support the semantics of AddPrinterDriver()
7668 * i.e. only copy files that are newer than existing ones
7671 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7672 return WERR_ACCESS_DENIED;
7674 ZERO_STRUCT(q_u_local);
7675 ZERO_STRUCT(r_u_local);
7677 /* just pass the information off to _spoolss_addprinterdriver() */
7678 q_u_local.server_name_ptr = q_u->server_name_ptr;
7679 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7680 q_u_local.level = q_u->level;
7681 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7683 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7686 /****************************************************************************
7687 ****************************************************************************/
7689 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7691 init_unistr(&info->name, name);
7694 /****************************************************************************
7695 ****************************************************************************/
7697 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7702 const char *short_archi;
7703 DRIVER_DIRECTORY_1 *info=NULL;
7705 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7706 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7708 if ( !is_myname_or_ipaddr( servername ) )
7709 return WERR_INVALID_PARAM;
7711 if (!(short_archi = get_short_archi(long_archi)))
7712 return WERR_INVALID_ENVIRONMENT;
7714 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7717 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", servername, short_archi);
7719 DEBUG(4,("printer driver directory: [%s]\n", path));
7721 fill_driverdir_1(info, path);
7723 *needed += spoolss_size_driverdir_info_1(info);
7725 if (!alloc_buffer_size(buffer, *needed)) {
7727 return WERR_INSUFFICIENT_BUFFER;
7730 smb_io_driverdir_1("", buffer, info, 0);
7734 if (*needed > offered)
7735 return WERR_INSUFFICIENT_BUFFER;
7740 /****************************************************************************
7741 ****************************************************************************/
7743 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7745 UNISTR2 *name = &q_u->name;
7746 UNISTR2 *uni_environment = &q_u->environment;
7747 uint32 level = q_u->level;
7748 NEW_BUFFER *buffer = NULL;
7749 uint32 offered = q_u->offered;
7750 uint32 *needed = &r_u->needed;
7752 /* that's an [in out] buffer */
7753 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7754 buffer = r_u->buffer;
7756 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7762 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7764 return WERR_UNKNOWN_LEVEL;
7768 /****************************************************************************
7769 ****************************************************************************/
7771 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7773 POLICY_HND *handle = &q_u->handle;
7774 uint32 idx = q_u->index;
7775 uint32 in_value_len = q_u->valuesize;
7776 uint32 in_data_len = q_u->datasize;
7777 uint32 *out_max_value_len = &r_u->valuesize;
7778 uint16 **out_value = &r_u->value;
7779 uint32 *out_value_len = &r_u->realvaluesize;
7780 uint32 *out_type = &r_u->type;
7781 uint32 *out_max_data_len = &r_u->datasize;
7782 uint8 **data_out = &r_u->data;
7783 uint32 *out_data_len = &r_u->realdatasize;
7785 NT_PRINTER_INFO_LEVEL *printer = NULL;
7787 uint32 biggest_valuesize;
7788 uint32 biggest_datasize;
7790 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7793 REGISTRY_VALUE *val = NULL;
7794 NT_PRINTER_DATA *p_data;
7795 int i, key_index, num_values;
7798 ZERO_STRUCT( printer );
7802 *out_max_data_len = 0;
7806 DEBUG(5,("spoolss_enumprinterdata\n"));
7809 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7813 if (!get_printer_snum(p,handle, &snum))
7816 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7817 if (!W_ERROR_IS_OK(result))
7820 p_data = &printer->info_2->data;
7821 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7826 * The NT machine wants to know the biggest size of value and data
7828 * cf: MSDN EnumPrinterData remark section
7831 if ( !in_value_len && !in_data_len && (key_index != -1) )
7833 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7835 biggest_valuesize = 0;
7836 biggest_datasize = 0;
7838 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7840 for ( i=0; i<num_values; i++ )
7842 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7844 name_length = strlen(val->valuename);
7845 if ( strlen(val->valuename) > biggest_valuesize )
7846 biggest_valuesize = name_length;
7848 if ( val->size > biggest_datasize )
7849 biggest_datasize = val->size;
7851 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7855 /* the value is an UNICODE string but real_value_size is the length
7856 in bytes including the trailing 0 */
7858 *out_value_len = 2 * (1+biggest_valuesize);
7859 *out_data_len = biggest_datasize;
7861 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7867 * the value len is wrong in NT sp3
7868 * that's the number of bytes not the number of unicode chars
7871 if ( key_index != -1 )
7872 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7877 /* out_value should default to "" or else NT4 has
7878 problems unmarshalling the response */
7880 *out_max_value_len=(in_value_len/sizeof(uint16));
7882 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7884 result = WERR_NOMEM;
7888 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7890 /* the data is counted in bytes */
7892 *out_max_data_len = in_data_len;
7893 *out_data_len = in_data_len;
7895 /* only allocate when given a non-zero data_len */
7897 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7899 result = WERR_NOMEM;
7903 result = WERR_NO_MORE_ITEMS;
7909 * - counted in bytes in the request
7910 * - counted in UNICODE chars in the max reply
7911 * - counted in bytes in the real size
7913 * take a pause *before* coding not *during* coding
7917 *out_max_value_len=(in_value_len/sizeof(uint16));
7918 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7920 result = WERR_NOMEM;
7924 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7928 *out_type = regval_type( val );
7930 /* data - counted in bytes */
7932 *out_max_data_len = in_data_len;
7933 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7935 result = WERR_NOMEM;
7938 data_len = (size_t)regval_size(val);
7939 memcpy( *data_out, regval_data_p(val), data_len );
7940 *out_data_len = data_len;
7944 free_a_printer(&printer, 2);
7948 /****************************************************************************
7949 ****************************************************************************/
7951 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7953 POLICY_HND *handle = &q_u->handle;
7954 UNISTR2 *value = &q_u->value;
7955 uint32 type = q_u->type;
7956 uint8 *data = q_u->data;
7957 uint32 real_len = q_u->real_len;
7959 NT_PRINTER_INFO_LEVEL *printer = NULL;
7961 WERROR status = WERR_OK;
7962 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7965 DEBUG(5,("spoolss_setprinterdata\n"));
7968 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7972 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7973 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7974 return WERR_INVALID_PARAM;
7977 if (!get_printer_snum(p,handle, &snum))
7981 * Access check : NT returns "access denied" if you make a
7982 * SetPrinterData call without the necessary privildge.
7983 * we were originally returning OK if nothing changed
7984 * which made Win2k issue **a lot** of SetPrinterData
7985 * when connecting to a printer --jerry
7988 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7990 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7991 status = WERR_ACCESS_DENIED;
7995 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7996 if (!W_ERROR_IS_OK(status))
7999 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8002 * When client side code sets a magic printer data key, detect it and save
8003 * the current printer data and the magic key's data (its the DEVMODE) for
8004 * future printer/driver initializations.
8006 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8008 /* Set devmode and printer initialization info */
8009 status = save_driver_init( printer, 2, data, real_len );
8011 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8015 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8016 type, data, real_len );
8017 if ( W_ERROR_IS_OK(status) )
8018 status = mod_a_printer(printer, 2);
8022 free_a_printer(&printer, 2);
8027 /****************************************************************************
8028 ****************************************************************************/
8030 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8032 POLICY_HND *handle = &q_u->handle;
8033 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8036 DEBUG(5,("_spoolss_resetprinter\n"));
8039 * All we do is to check to see if the handle and queue is valid.
8040 * This call really doesn't mean anything to us because we only
8041 * support RAW printing. --jerry
8045 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8049 if (!get_printer_snum(p,handle, &snum))
8053 /* blindly return success */
8058 /****************************************************************************
8059 ****************************************************************************/
8061 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8063 POLICY_HND *handle = &q_u->handle;
8064 UNISTR2 *value = &q_u->valuename;
8066 NT_PRINTER_INFO_LEVEL *printer = NULL;
8068 WERROR status = WERR_OK;
8069 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8072 DEBUG(5,("spoolss_deleteprinterdata\n"));
8075 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8079 if (!get_printer_snum(p, handle, &snum))
8082 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8083 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8084 return WERR_ACCESS_DENIED;
8087 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8088 if (!W_ERROR_IS_OK(status))
8091 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8093 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8095 if ( W_ERROR_IS_OK(status) )
8096 mod_a_printer( printer, 2 );
8098 free_a_printer(&printer, 2);
8103 /****************************************************************************
8104 ****************************************************************************/
8106 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8108 POLICY_HND *handle = &q_u->handle;
8109 FORM *form = &q_u->form;
8110 nt_forms_struct tmpForm;
8112 WERROR status = WERR_OK;
8113 NT_PRINTER_INFO_LEVEL *printer = NULL;
8116 nt_forms_struct *list=NULL;
8117 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8119 DEBUG(5,("spoolss_addform\n"));
8122 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8127 /* forms can be added on printer of on the print server handle */
8129 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8131 if (!get_printer_snum(p,handle, &snum))
8134 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8135 if (!W_ERROR_IS_OK(status))
8139 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8140 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8141 status = WERR_ACCESS_DENIED;
8145 /* can't add if builtin */
8147 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8148 status = WERR_ALREADY_EXISTS;
8152 count = get_ntforms(&list);
8154 if(!add_a_form(&list, form, &count)) {
8155 status = WERR_NOMEM;
8159 write_ntforms(&list, count);
8162 * ChangeID must always be set if this is a printer
8165 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8166 status = mod_a_printer(printer, 2);
8170 free_a_printer(&printer, 2);
8176 /****************************************************************************
8177 ****************************************************************************/
8179 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8181 POLICY_HND *handle = &q_u->handle;
8182 UNISTR2 *form_name = &q_u->name;
8183 nt_forms_struct tmpForm;
8185 nt_forms_struct *list=NULL;
8186 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8188 WERROR status = WERR_OK;
8189 NT_PRINTER_INFO_LEVEL *printer = NULL;
8191 DEBUG(5,("spoolss_deleteform\n"));
8194 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8198 /* forms can be deleted on printer of on the print server handle */
8200 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8202 if (!get_printer_snum(p,handle, &snum))
8205 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8206 if (!W_ERROR_IS_OK(status))
8210 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8211 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8212 status = WERR_ACCESS_DENIED;
8216 /* can't delete if builtin */
8218 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8219 status = WERR_INVALID_PARAM;
8223 count = get_ntforms(&list);
8225 if ( !delete_a_form(&list, form_name, &count, &status ))
8229 * ChangeID must always be set if this is a printer
8232 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8233 status = mod_a_printer(printer, 2);
8237 free_a_printer(&printer, 2);
8243 /****************************************************************************
8244 ****************************************************************************/
8246 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8248 POLICY_HND *handle = &q_u->handle;
8249 FORM *form = &q_u->form;
8250 nt_forms_struct tmpForm;
8252 WERROR status = WERR_OK;
8253 NT_PRINTER_INFO_LEVEL *printer = NULL;
8256 nt_forms_struct *list=NULL;
8257 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8259 DEBUG(5,("spoolss_setform\n"));
8262 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8266 /* forms can be modified on printer of on the print server handle */
8268 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8270 if (!get_printer_snum(p,handle, &snum))
8273 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8274 if (!W_ERROR_IS_OK(status))
8278 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8279 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8280 status = WERR_ACCESS_DENIED;
8284 /* can't set if builtin */
8285 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8286 status = WERR_INVALID_PARAM;
8290 count = get_ntforms(&list);
8291 update_a_form(&list, form, count);
8292 write_ntforms(&list, count);
8295 * ChangeID must always be set if this is a printer
8298 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8299 status = mod_a_printer(printer, 2);
8304 free_a_printer(&printer, 2);
8310 /****************************************************************************
8311 enumprintprocessors level 1.
8312 ****************************************************************************/
8314 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8316 PRINTPROCESSOR_1 *info_1=NULL;
8318 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8323 init_unistr(&info_1->name, "winprint");
8325 *needed += spoolss_size_printprocessor_info_1(info_1);
8327 if (!alloc_buffer_size(buffer, *needed))
8328 return WERR_INSUFFICIENT_BUFFER;
8330 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8334 if (*needed > offered) {
8336 return WERR_INSUFFICIENT_BUFFER;
8342 /****************************************************************************
8343 ****************************************************************************/
8345 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8347 uint32 level = q_u->level;
8348 NEW_BUFFER *buffer = NULL;
8349 uint32 offered = q_u->offered;
8350 uint32 *needed = &r_u->needed;
8351 uint32 *returned = &r_u->returned;
8353 /* that's an [in out] buffer */
8354 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8355 buffer = r_u->buffer;
8357 DEBUG(5,("spoolss_enumprintprocessors\n"));
8360 * Enumerate the print processors ...
8362 * Just reply with "winprint", to keep NT happy
8363 * and I can use my nice printer checker.
8371 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8373 return WERR_UNKNOWN_LEVEL;
8377 /****************************************************************************
8378 enumprintprocdatatypes level 1.
8379 ****************************************************************************/
8381 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8383 PRINTPROCDATATYPE_1 *info_1=NULL;
8385 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8390 init_unistr(&info_1->name, "RAW");
8392 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8394 if (!alloc_buffer_size(buffer, *needed))
8395 return WERR_INSUFFICIENT_BUFFER;
8397 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8401 if (*needed > offered) {
8403 return WERR_INSUFFICIENT_BUFFER;
8409 /****************************************************************************
8410 ****************************************************************************/
8412 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8414 uint32 level = q_u->level;
8415 NEW_BUFFER *buffer = NULL;
8416 uint32 offered = q_u->offered;
8417 uint32 *needed = &r_u->needed;
8418 uint32 *returned = &r_u->returned;
8420 /* that's an [in out] buffer */
8421 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8422 buffer = r_u->buffer;
8424 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8431 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8433 return WERR_UNKNOWN_LEVEL;
8437 /****************************************************************************
8438 enumprintmonitors level 1.
8439 ****************************************************************************/
8441 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8443 PRINTMONITOR_1 *info_1=NULL;
8445 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8450 init_unistr(&info_1->name, "Local Port");
8452 *needed += spoolss_size_printmonitor_info_1(info_1);
8454 if (!alloc_buffer_size(buffer, *needed))
8455 return WERR_INSUFFICIENT_BUFFER;
8457 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8461 if (*needed > offered) {
8463 return WERR_INSUFFICIENT_BUFFER;
8469 /****************************************************************************
8470 enumprintmonitors level 2.
8471 ****************************************************************************/
8473 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8475 PRINTMONITOR_2 *info_2=NULL;
8477 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8482 init_unistr(&info_2->name, "Local Port");
8483 init_unistr(&info_2->environment, "Windows NT X86");
8484 init_unistr(&info_2->dll_name, "localmon.dll");
8486 *needed += spoolss_size_printmonitor_info_2(info_2);
8488 if (!alloc_buffer_size(buffer, *needed))
8489 return WERR_INSUFFICIENT_BUFFER;
8491 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8495 if (*needed > offered) {
8497 return WERR_INSUFFICIENT_BUFFER;
8503 /****************************************************************************
8504 ****************************************************************************/
8506 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8508 uint32 level = q_u->level;
8509 NEW_BUFFER *buffer = NULL;
8510 uint32 offered = q_u->offered;
8511 uint32 *needed = &r_u->needed;
8512 uint32 *returned = &r_u->returned;
8514 /* that's an [in out] buffer */
8515 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8516 buffer = r_u->buffer;
8518 DEBUG(5,("spoolss_enumprintmonitors\n"));
8521 * Enumerate the print monitors ...
8523 * Just reply with "Local Port", to keep NT happy
8524 * and I can use my nice printer checker.
8532 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8534 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8536 return WERR_UNKNOWN_LEVEL;
8540 /****************************************************************************
8541 ****************************************************************************/
8543 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8544 NT_PRINTER_INFO_LEVEL *ntprinter,
8545 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8550 JOB_INFO_1 *info_1=NULL;
8552 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8554 if (info_1 == NULL) {
8558 for (i=0; i<count && found==False; i++) {
8559 if ((*queue)[i].job==(int)jobid)
8565 /* NT treats not found as bad param... yet another bad choice */
8566 return WERR_INVALID_PARAM;
8569 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8571 *needed += spoolss_size_job_info_1(info_1);
8573 if (!alloc_buffer_size(buffer, *needed)) {
8575 return WERR_INSUFFICIENT_BUFFER;
8578 smb_io_job_info_1("", buffer, info_1, 0);
8582 if (*needed > offered)
8583 return WERR_INSUFFICIENT_BUFFER;
8588 /****************************************************************************
8589 ****************************************************************************/
8591 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8592 NT_PRINTER_INFO_LEVEL *ntprinter,
8593 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8600 DEVICEMODE *devmode = NULL;
8601 NT_DEVICEMODE *nt_devmode = NULL;
8603 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8605 ZERO_STRUCTP(info_2);
8607 if (info_2 == NULL) {
8612 for ( i=0; i<count && found==False; i++ )
8614 if ((*queue)[i].job == (int)jobid)
8620 /* NT treats not found as bad param... yet another bad
8622 ret = WERR_INVALID_PARAM;
8627 * if the print job does not have a DEVMODE associated with it,
8628 * just use the one for the printer. A NULL devicemode is not
8629 * a failure condition
8632 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8633 devmode = construct_dev_mode(snum);
8635 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8636 ZERO_STRUCTP( devmode );
8637 convert_nt_devicemode( devmode, nt_devmode );
8641 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8643 *needed += spoolss_size_job_info_2(info_2);
8645 if (!alloc_buffer_size(buffer, *needed)) {
8646 ret = WERR_INSUFFICIENT_BUFFER;
8650 smb_io_job_info_2("", buffer, info_2, 0);
8652 if (*needed > offered) {
8653 ret = WERR_INSUFFICIENT_BUFFER;
8660 /* Cleanup allocated memory */
8662 free_job_info_2(info_2); /* Also frees devmode */
8664 free_a_printer(&ntprinter, 2);
8669 /****************************************************************************
8670 ****************************************************************************/
8672 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8674 POLICY_HND *handle = &q_u->handle;
8675 uint32 jobid = q_u->jobid;
8676 uint32 level = q_u->level;
8677 NEW_BUFFER *buffer = NULL;
8678 uint32 offered = q_u->offered;
8679 uint32 *needed = &r_u->needed;
8680 WERROR wstatus = WERR_OK;
8681 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8684 print_queue_struct *queue = NULL;
8685 print_status_struct prt_status;
8687 /* that's an [in out] buffer */
8688 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8689 buffer = r_u->buffer;
8691 DEBUG(5,("spoolss_getjob\n"));
8695 if (!get_printer_snum(p, handle, &snum))
8698 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8699 if ( !W_ERROR_IS_OK(wstatus) )
8702 count = print_queue_status(snum, &queue, &prt_status);
8704 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8705 count, prt_status.status, prt_status.message));
8709 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8710 buffer, offered, needed);
8713 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8714 buffer, offered, needed);
8717 wstatus = WERR_UNKNOWN_LEVEL;
8722 free_a_printer( &ntprinter, 2 );
8727 /********************************************************************
8728 spoolss_getprinterdataex
8730 From MSDN documentation of GetPrinterDataEx: pass request
8731 to GetPrinterData if key is "PrinterDriverData".
8732 ********************************************************************/
8734 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8736 POLICY_HND *handle = &q_u->handle;
8737 uint32 in_size = q_u->size;
8738 uint32 *type = &r_u->type;
8739 uint32 *out_size = &r_u->size;
8740 uint8 **data = &r_u->data;
8741 uint32 *needed = &r_u->needed;
8742 fstring keyname, valuename;
8744 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8746 NT_PRINTER_INFO_LEVEL *printer = NULL;
8748 WERROR status = WERR_OK;
8750 DEBUG(4,("_spoolss_getprinterdataex\n"));
8752 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8753 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8755 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8756 keyname, valuename));
8758 /* in case of problem, return some default values */
8762 *out_size = in_size;
8765 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8766 status = WERR_BADFID;
8770 /* Is the handle to a printer or to the server? */
8772 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8773 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8774 status = WERR_INVALID_PARAM;
8778 if ( !get_printer_snum(p,handle, &snum) )
8781 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8782 if ( !W_ERROR_IS_OK(status) )
8785 /* check to see if the keyname is valid */
8786 if ( !strlen(keyname) ) {
8787 status = WERR_INVALID_PARAM;
8791 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8792 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8793 free_a_printer( &printer, 2 );
8794 status = WERR_BADFILE;
8798 /* When given a new keyname, we should just create it */
8800 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8802 if (*needed > *out_size)
8803 status = WERR_MORE_DATA;
8806 if ( !W_ERROR_IS_OK(status) )
8808 DEBUG(5, ("error: allocating %d\n", *out_size));
8810 /* reply this param doesn't exist */
8814 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8815 status = WERR_NOMEM;
8825 free_a_printer( &printer, 2 );
8830 /********************************************************************
8831 * spoolss_setprinterdataex
8832 ********************************************************************/
8834 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8836 POLICY_HND *handle = &q_u->handle;
8837 uint32 type = q_u->type;
8838 uint8 *data = q_u->data;
8839 uint32 real_len = q_u->real_len;
8841 NT_PRINTER_INFO_LEVEL *printer = NULL;
8843 WERROR status = WERR_OK;
8844 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8849 DEBUG(4,("_spoolss_setprinterdataex\n"));
8851 /* From MSDN documentation of SetPrinterDataEx: pass request to
8852 SetPrinterData if key is "PrinterDriverData" */
8855 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8859 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8860 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8861 return WERR_INVALID_PARAM;
8864 if ( !get_printer_snum(p,handle, &snum) )
8868 * Access check : NT returns "access denied" if you make a
8869 * SetPrinterData call without the necessary privildge.
8870 * we were originally returning OK if nothing changed
8871 * which made Win2k issue **a lot** of SetPrinterData
8872 * when connecting to a printer --jerry
8875 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8877 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8878 return WERR_ACCESS_DENIED;
8881 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8882 if (!W_ERROR_IS_OK(status))
8885 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8886 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8888 /* check for OID in valuename */
8890 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8896 /* save the registry data */
8898 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8900 if ( W_ERROR_IS_OK(status) )
8902 /* save the OID if one was specified */
8904 fstrcat( keyname, "\\" );
8905 fstrcat( keyname, SPOOL_OID_KEY );
8908 * I'm not checking the status here on purpose. Don't know
8909 * if this is right, but I'm returning the status from the
8910 * previous set_printer_dataex() call. I have no idea if
8911 * this is right. --jerry
8914 set_printer_dataex( printer, keyname, valuename,
8915 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8918 status = mod_a_printer(printer, 2);
8921 free_a_printer(&printer, 2);
8927 /********************************************************************
8928 * spoolss_deleteprinterdataex
8929 ********************************************************************/
8931 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8933 POLICY_HND *handle = &q_u->handle;
8934 UNISTR2 *value = &q_u->valuename;
8935 UNISTR2 *key = &q_u->keyname;
8937 NT_PRINTER_INFO_LEVEL *printer = NULL;
8939 WERROR status = WERR_OK;
8940 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8941 pstring valuename, keyname;
8943 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8946 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8950 if (!get_printer_snum(p, handle, &snum))
8953 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8954 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8955 return WERR_ACCESS_DENIED;
8958 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8959 if (!W_ERROR_IS_OK(status))
8962 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8963 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8965 status = delete_printer_dataex( printer, keyname, valuename );
8967 if ( W_ERROR_IS_OK(status) )
8968 mod_a_printer( printer, 2 );
8970 free_a_printer(&printer, 2);
8975 /********************************************************************
8976 * spoolss_enumprinterkey
8977 ********************************************************************/
8980 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8983 fstring *keynames = NULL;
8984 uint16 *enumkeys = NULL;
8987 POLICY_HND *handle = &q_u->handle;
8988 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8989 NT_PRINTER_DATA *data;
8990 NT_PRINTER_INFO_LEVEL *printer = NULL;
8992 WERROR status = WERR_BADFILE;
8995 DEBUG(4,("_spoolss_enumprinterkey\n"));
8998 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9002 if ( !get_printer_snum(p,handle, &snum) )
9005 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9006 if (!W_ERROR_IS_OK(status))
9009 /* get the list of subkey names */
9011 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9012 data = &printer->info_2->data;
9014 num_keys = get_printer_subkeys( data, key, &keynames );
9016 if ( num_keys == -1 ) {
9017 status = WERR_BADFILE;
9021 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9023 r_u->needed = printerkey_len*2;
9025 if ( q_u->size < r_u->needed ) {
9026 status = WERR_MORE_DATA;
9030 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9031 status = WERR_NOMEM;
9037 if ( q_u->size < r_u->needed )
9038 status = WERR_MORE_DATA;
9041 free_a_printer( &printer, 2 );
9042 SAFE_FREE( keynames );
9047 /********************************************************************
9048 * spoolss_deleteprinterkey
9049 ********************************************************************/
9051 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9053 POLICY_HND *handle = &q_u->handle;
9054 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9056 NT_PRINTER_INFO_LEVEL *printer = NULL;
9060 DEBUG(5,("spoolss_deleteprinterkey\n"));
9063 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9067 /* if keyname == NULL, return error */
9069 if ( !q_u->keyname.buffer )
9070 return WERR_INVALID_PARAM;
9072 if (!get_printer_snum(p, handle, &snum))
9075 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9076 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9077 return WERR_ACCESS_DENIED;
9080 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9081 if (!W_ERROR_IS_OK(status))
9084 /* delete the key and all subneys */
9086 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9088 status = delete_all_printer_data( printer->info_2, key );
9090 if ( W_ERROR_IS_OK(status) )
9091 status = mod_a_printer(printer, 2);
9093 free_a_printer( &printer, 2 );
9099 /********************************************************************
9100 * spoolss_enumprinterdataex
9101 ********************************************************************/
9103 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9105 POLICY_HND *handle = &q_u->handle;
9106 uint32 in_size = q_u->size;
9109 NT_PRINTER_INFO_LEVEL *printer = NULL;
9110 PRINTER_ENUM_VALUES *enum_values = NULL;
9111 NT_PRINTER_DATA *p_data;
9113 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9118 REGISTRY_VALUE *val;
9123 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9126 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9131 * first check for a keyname of NULL or "". Win2k seems to send
9132 * this a lot and we should send back WERR_INVALID_PARAM
9133 * no need to spend time looking up the printer in this case.
9137 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9138 if ( !strlen(key) ) {
9139 result = WERR_INVALID_PARAM;
9143 /* get the printer off of disk */
9145 if (!get_printer_snum(p,handle, &snum))
9148 ZERO_STRUCT(printer);
9149 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9150 if (!W_ERROR_IS_OK(result))
9153 /* now look for a match on the key name */
9155 p_data = &printer->info_2->data;
9157 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9158 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9160 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9161 result = WERR_INVALID_PARAM;
9168 /* allocate the memory for the array of pointers -- if necessary */
9170 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9173 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9175 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9176 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9177 result = WERR_NOMEM;
9181 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9185 * loop through all params and build the array to pass
9186 * back to the client
9189 for ( i=0; i<num_entries; i++ )
9191 /* lookup the registry value */
9193 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9194 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9198 value_name = regval_name( val );
9199 init_unistr( &enum_values[i].valuename, value_name );
9200 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9201 enum_values[i].type = regval_type( val );
9203 data_len = regval_size( val );
9205 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9207 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9209 result = WERR_NOMEM;
9213 enum_values[i].data_len = data_len;
9215 /* keep track of the size of the array in bytes */
9217 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9220 /* housekeeping information in the reply */
9222 r_u->needed = needed;
9223 r_u->returned = num_entries;
9225 if (needed > in_size) {
9226 result = WERR_MORE_DATA;
9230 /* copy data into the reply */
9232 r_u->ctr.size = r_u->needed;
9233 r_u->ctr.size_of_array = r_u->returned;
9234 r_u->ctr.values = enum_values;
9240 free_a_printer(&printer, 2);
9245 /****************************************************************************
9246 ****************************************************************************/
9248 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9250 init_unistr(&info->name, name);
9253 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9254 UNISTR2 *environment,
9261 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9263 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9265 if (!get_short_archi(long_archi))
9266 return WERR_INVALID_ENVIRONMENT;
9268 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9271 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9273 fill_printprocessordirectory_1(info, path);
9275 *needed += spoolss_size_printprocessordirectory_info_1(info);
9277 if (!alloc_buffer_size(buffer, *needed)) {
9279 return WERR_INSUFFICIENT_BUFFER;
9282 smb_io_printprocessordirectory_1("", buffer, info, 0);
9286 if (*needed > offered)
9287 return WERR_INSUFFICIENT_BUFFER;
9292 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9294 uint32 level = q_u->level;
9295 NEW_BUFFER *buffer = NULL;
9296 uint32 offered = q_u->offered;
9297 uint32 *needed = &r_u->needed;
9300 /* that's an [in out] buffer */
9301 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9302 buffer = r_u->buffer;
9304 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9310 result = getprintprocessordirectory_level_1
9311 (&q_u->name, &q_u->environment, buffer, offered, needed);
9314 result = WERR_UNKNOWN_LEVEL;
9322 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9323 SPOOL_R_REPLYOPENPRINTER *r_u)
9325 DEBUG(5,("_spoolss_replyopenprinter\n"));
9327 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9332 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9333 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9335 DEBUG(5,("_spoolss_replycloseprinter\n"));