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->dev.handlename);
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 *printername )
284 DEBUG(10,("find_printer_in_print_hnd_cache: printer [%s]\n", printername));
286 for ( p=printers_list; p; p=p->next )
288 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
290 && StrCaseCmp(p->dev.handlename, printername) == 0 )
292 DEBUG(10,("Found printer\n"));
293 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
299 return WERR_INVALID_PRINTER_NAME;
302 /****************************************************************************
303 destroy any cached printer_info_2 structures on open handles
304 ****************************************************************************/
306 void invalidate_printer_hnd_cache( char *printername )
310 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
312 for ( p=printers_list; p; p=p->next )
314 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
316 && StrCaseCmp(p->dev.handlename, printername)==0)
318 DEBUG(10,("invalidating printer_info cache for handl:\n"));
319 free_a_printer( &p->printer_info, 2 );
320 p->printer_info = NULL;
326 /****************************************************************************
327 Close printer index by handle.
328 ****************************************************************************/
330 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
332 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
335 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
339 close_policy_hnd(p, hnd);
344 /****************************************************************************
345 Delete a printer given a handle.
346 ****************************************************************************/
348 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
350 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
353 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
358 * It turns out that Windows allows delete printer on a handle
359 * opened by an admin user, then used on a pipe handle created
360 * by an anonymous user..... but they're working on security.... riiight !
364 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
365 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
366 return WERR_ACCESS_DENIED;
370 /* Check calling user has permission to delete printer. Note that
371 since we set the snum parameter to -1 only administrators can
372 delete the printer. This stops people with the Full Control
373 permission from deleting the printer. */
375 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
376 DEBUG(3, ("printer delete denied by security descriptor\n"));
377 return WERR_ACCESS_DENIED;
381 if (del_a_printer(Printer->dev.handlename) != 0) {
382 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
386 if (*lp_deleteprinter_cmd()) {
388 char *cmd = lp_deleteprinter_cmd();
392 /* Printer->dev.handlename equals portname equals sharename */
393 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
394 Printer->dev.handlename);
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->dev.handlename ) < 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->dev.handlename));
432 *number = print_queue_snum(Printer->dev.handlename);
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;
480 NT_PRINTER_INFO_LEVEL *printer;
483 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
485 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
486 ZERO_STRUCT(Printer->dev.printerservername);
487 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
491 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
494 if (*handlename=='\\') {
495 aprinter=strchr_m(handlename+2, '\\');
502 DEBUGADD(5, ("searching for [%s] (len=%lu)\n", aprinter, (unsigned long)strlen(aprinter)));
504 /* have to search on sharename and PRINTER_INFO2->printername */
506 for (snum=0; snum<n_services; snum++) {
508 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
511 /* ------ sharename ------ */
513 fstrcpy(sname, lp_servicename(snum));
515 DEBUGADD(10, ("share: %s\n",sname));
517 if ( strequal(sname, aprinter) ) {
522 /* ------ printername ------ */
525 result = get_a_printer( NULL, &printer, 2, sname );
526 if ( !W_ERROR_IS_OK(result) ) {
527 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
528 sname, dos_errstr(result)));
532 /* printername is always returned as \\server\printername */
533 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
534 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
535 printer->info_2->printername));
536 free_a_printer( &printer, 2);
542 if ( strequal(printername, aprinter) ) {
546 DEBUGADD(10, ("printername: %s\n", printername));
548 free_a_printer( &printer, 2);
556 DEBUGADD(4,("Printer not found\n"));
560 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
562 ZERO_STRUCT(Printer->dev.handlename);
563 fstrcpy(Printer->dev.handlename, sname);
568 /****************************************************************************
569 Find first available printer slot. creates a printer handle for you.
570 ****************************************************************************/
572 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
574 Printer_entry *new_printer;
576 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
578 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
581 ZERO_STRUCTP(new_printer);
583 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
584 SAFE_FREE(new_printer);
588 /* Add to the internal list. */
589 DLIST_ADD(printers_list, new_printer);
591 new_printer->notify.option=NULL;
593 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
594 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
595 close_printer_handle(p, hnd);
599 if (!set_printer_hnd_printertype(new_printer, name)) {
600 close_printer_handle(p, hnd);
604 if (!set_printer_hnd_name(new_printer, name)) {
605 close_printer_handle(p, hnd);
609 new_printer->access_granted = access_granted;
611 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
616 /****************************************************************************
617 Allocate more memory for a BUFFER.
618 ****************************************************************************/
620 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
628 /* damn, I'm doing the reverse operation of prs_grow() :) */
629 if (buffer_size < prs_data_size(ps))
632 extra_space = buffer_size - prs_data_size(ps);
635 * save the offset and move to the end of the buffer
636 * prs_grow() checks the extra_space against the offset
638 old_offset=prs_offset(ps);
639 prs_set_offset(ps, prs_data_size(ps));
641 if (!prs_grow(ps, extra_space))
644 prs_set_offset(ps, old_offset);
646 buffer->string_at_end=prs_data_size(ps);
651 /***************************************************************************
652 check to see if the client motify handle is monitoring the notification
653 given by (notify_type, notify_field).
654 **************************************************************************/
656 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
662 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
665 SPOOL_NOTIFY_OPTION *option = p->notify.option;
669 * Flags should always be zero when the change notify
670 * is registered by the client's spooler. A user Win32 app
671 * might use the flags though instead of the NOTIFY_OPTION_INFO
680 return is_monitoring_event_flags(
681 p->notify.flags, notify_type, notify_field);
683 for (i = 0; i < option->count; i++) {
685 /* Check match for notify_type */
687 if (option->ctr.type[i].type != notify_type)
690 /* Check match for field */
692 for (j = 0; j < option->ctr.type[i].count; j++) {
693 if (option->ctr.type[i].fields[j] == notify_field) {
699 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
700 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
701 p->dev.handlename : p->dev.printerservername,
702 notify_type, notify_field));
707 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
709 static void notify_one_value(struct spoolss_notify_msg *msg,
710 SPOOL_NOTIFY_INFO_DATA *data,
713 data->notify_data.value[0] = msg->notify.value[0];
714 data->notify_data.value[1] = 0;
717 static void notify_string(struct spoolss_notify_msg *msg,
718 SPOOL_NOTIFY_INFO_DATA *data,
723 /* The length of the message includes the trailing \0 */
725 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
727 data->notify_data.data.length = msg->len * 2;
728 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
730 if (!data->notify_data.data.string) {
731 data->notify_data.data.length = 0;
735 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
738 static void notify_system_time(struct spoolss_notify_msg *msg,
739 SPOOL_NOTIFY_INFO_DATA *data,
745 if (msg->len != sizeof(time_t)) {
746 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
751 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
752 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
756 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
757 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
761 if (!spoolss_io_system_time("", &ps, 0, &systime))
764 data->notify_data.data.length = prs_offset(&ps);
765 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
767 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
772 struct notify2_message_table {
774 void (*fn)(struct spoolss_notify_msg *msg,
775 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
778 static struct notify2_message_table printer_notify_table[] = {
779 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
780 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
781 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
782 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
783 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
784 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
785 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
786 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
787 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
788 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
789 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
790 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
791 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
792 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
793 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
794 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
795 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
796 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
797 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
800 static struct notify2_message_table job_notify_table[] = {
801 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
802 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
803 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
804 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
805 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
806 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
807 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
808 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
809 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
810 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
811 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
812 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
813 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
814 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
815 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
816 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
817 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
818 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
819 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
820 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
821 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
822 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
823 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
824 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
828 /***********************************************************************
829 Allocate talloc context for container object
830 **********************************************************************/
832 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
837 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
842 /***********************************************************************
843 release all allocated memory and zero out structure
844 **********************************************************************/
846 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
852 talloc_destroy(ctr->ctx);
859 /***********************************************************************
860 **********************************************************************/
862 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
870 /***********************************************************************
871 **********************************************************************/
873 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
875 if ( !ctr || !ctr->msg_groups )
878 if ( idx >= ctr->num_groups )
881 return &ctr->msg_groups[idx];
885 /***********************************************************************
886 How many groups of change messages do we have ?
887 **********************************************************************/
889 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
894 return ctr->num_groups;
897 /***********************************************************************
898 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
899 **********************************************************************/
901 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
903 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
904 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
905 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
911 /* loop over all groups looking for a matching printer name */
913 for ( i=0; i<ctr->num_groups; i++ ) {
914 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
918 /* add a new group? */
920 if ( i == ctr->num_groups ) {
923 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
924 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
927 ctr->msg_groups = groups;
929 /* clear the new entry and set the printer name */
931 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
932 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
935 /* add the change messages; 'i' is the correct index now regardless */
937 msg_grp = &ctr->msg_groups[i];
941 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
942 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
945 msg_grp->msgs = msg_list;
947 new_slot = msg_grp->num_msgs-1;
948 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
950 /* need to allocate own copy of data */
953 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
955 return ctr->num_groups;
958 /***********************************************************************
959 Send a change notication message on all handles which have a call
961 **********************************************************************/
963 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
966 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
967 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
968 SPOOLSS_NOTIFY_MSG *messages;
969 int sending_msg_count;
972 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
976 messages = msg_group->msgs;
979 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
983 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
985 /* loop over all printers */
987 for (p = printers_list; p; p = p->next) {
988 SPOOL_NOTIFY_INFO_DATA *data;
993 /* Is there notification on this handle? */
995 if ( !p->notify.client_connected )
998 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
1000 /* For this printer? Print servers always receive
1003 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1004 ( !strequal(msg_group->printername, p->dev.handlename) ) )
1007 DEBUG(10,("Our printer\n"));
1009 /* allocate the max entries possible */
1011 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
1014 /* build the array of change notifications */
1016 sending_msg_count = 0;
1018 for ( i=0; i<msg_group->num_msgs; i++ ) {
1019 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1021 /* Are we monitoring this event? */
1023 if (!is_monitoring_event(p, msg->type, msg->field))
1026 sending_msg_count++;
1029 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1030 msg->type, msg->field, p->dev.handlename));
1033 * if the is a printer notification handle and not a job notification
1034 * type, then set the id to 0. Other wise just use what was specified
1037 * When registering change notification on a print server handle
1038 * we always need to send back the id (snum) matching the printer
1039 * for which the change took place. For change notify registered
1040 * on a printer handle, this does not matter and the id should be 0.
1045 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1051 /* Convert unix jobid to smb jobid */
1053 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1054 id = sysjob_to_jobid(msg->id);
1057 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1062 construct_info_data( &data[data_len], msg->type, msg->field, id );
1065 case PRINTER_NOTIFY_TYPE:
1066 if ( printer_notify_table[msg->field].fn )
1067 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1070 case JOB_NOTIFY_TYPE:
1071 if ( job_notify_table[msg->field].fn )
1072 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1076 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1083 if ( sending_msg_count ) {
1084 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1085 data_len, data, p->notify.change, 0 );
1090 DEBUG(8,("send_notify2_changes: Exit...\n"));
1094 /***********************************************************************
1095 **********************************************************************/
1097 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1100 uint32 tv_sec, tv_usec;
1103 /* Unpack message */
1105 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1108 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1110 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1113 tdb_unpack((char *)buf + offset, len - offset, "dd",
1114 &msg->notify.value[0], &msg->notify.value[1]);
1116 tdb_unpack((char *)buf + offset, len - offset, "B",
1117 &msg->len, &msg->notify.data);
1119 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1120 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1122 tv->tv_sec = tv_sec;
1123 tv->tv_usec = tv_usec;
1126 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1127 msg->notify.value[1]));
1129 dump_data(3, msg->notify.data, msg->len);
1134 /********************************************************************
1135 Receive a notify2 message list
1136 ********************************************************************/
1138 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1140 size_t msg_count, i;
1141 char *buf = (char *)msg;
1144 SPOOLSS_NOTIFY_MSG notify;
1145 SPOOLSS_NOTIFY_MSG_CTR messages;
1149 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1153 msg_count = IVAL(buf, 0);
1156 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1158 if (msg_count == 0) {
1159 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1163 /* initialize the container */
1165 ZERO_STRUCT( messages );
1166 notify_msg_ctr_init( &messages );
1169 * build message groups for each printer identified
1170 * in a change_notify msg. Remember that a PCN message
1171 * includes the handle returned for the srv_spoolss_replyopenprinter()
1172 * call. Therefore messages are grouped according to printer handle.
1175 for ( i=0; i<msg_count; i++ ) {
1176 struct timeval msg_tv;
1178 if (msg_ptr + 4 - buf > len) {
1179 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1183 msg_len = IVAL(msg_ptr,0);
1186 if (msg_ptr + msg_len - buf > len) {
1187 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1191 /* unpack messages */
1193 ZERO_STRUCT( notify );
1194 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1197 /* add to correct list in container */
1199 notify_msg_ctr_addmsg( &messages, ¬ify );
1201 /* free memory that might have been allocated by notify2_unpack_msg() */
1203 if ( notify.len != 0 )
1204 SAFE_FREE( notify.notify.data );
1207 /* process each group of messages */
1209 num_groups = notify_msg_ctr_numgroups( &messages );
1210 for ( i=0; i<num_groups; i++ )
1211 send_notify2_changes( &messages, i );
1216 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1218 notify_msg_ctr_destroy( &messages );
1223 /********************************************************************
1224 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1225 one smbd, all of processes must clear their printer cache immediately.
1226 ********************************************************************/
1228 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1230 fstring printername;
1232 fstrcpy( printername, buf );
1234 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1236 invalidate_printer_hnd_cache( printername );
1239 /********************************************************************
1240 Send a message to ourself about new driver being installed
1241 so we can upgrade the information for each printer bound to this
1243 ********************************************************************/
1245 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1247 int len = strlen(drivername);
1252 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1255 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1260 /**********************************************************************
1261 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1262 over all printers, upgrading ones as necessary
1263 **********************************************************************/
1265 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1269 int n_services = lp_numservices();
1271 len = MIN(len,sizeof(drivername)-1);
1272 strncpy(drivername, buf, len);
1274 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1276 /* Iterate the printer list */
1278 for (snum=0; snum<n_services; snum++)
1280 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1283 NT_PRINTER_INFO_LEVEL *printer = NULL;
1285 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1286 if (!W_ERROR_IS_OK(result))
1289 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1291 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1293 /* all we care about currently is the change_id */
1295 result = mod_a_printer(printer, 2);
1296 if (!W_ERROR_IS_OK(result)) {
1297 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1298 dos_errstr(result)));
1302 free_a_printer(&printer, 2);
1309 /********************************************************************
1310 Update the cache for all printq's with a registered client
1312 ********************************************************************/
1314 void update_monitored_printq_cache( void )
1316 Printer_entry *printer = printers_list;
1319 /* loop through all printers and update the cache where
1320 client_connected == True */
1323 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1324 && printer->notify.client_connected )
1326 snum = print_queue_snum(printer->dev.handlename);
1327 print_queue_status( snum, NULL, NULL );
1330 printer = printer->next;
1335 /********************************************************************
1336 Send a message to ourself about new driver being installed
1337 so we can upgrade the information for each printer bound to this
1339 ********************************************************************/
1341 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1343 int len = strlen(drivername);
1348 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1351 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1356 /**********************************************************************
1357 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1358 over all printers, resetting printer data as neessary
1359 **********************************************************************/
1361 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1365 int n_services = lp_numservices();
1367 len = MIN( len, sizeof(drivername)-1 );
1368 strncpy( drivername, buf, len );
1370 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1372 /* Iterate the printer list */
1374 for ( snum=0; snum<n_services; snum++ )
1376 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1379 NT_PRINTER_INFO_LEVEL *printer = NULL;
1381 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1382 if ( !W_ERROR_IS_OK(result) )
1386 * if the printer is bound to the driver,
1387 * then reset to the new driver initdata
1390 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1392 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1394 if ( !set_driver_init(printer, 2) ) {
1395 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1396 printer->info_2->printername, printer->info_2->drivername));
1399 result = mod_a_printer( printer, 2 );
1400 if ( !W_ERROR_IS_OK(result) ) {
1401 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1402 get_dos_error_msg(result)));
1406 free_a_printer( &printer, 2 );
1415 /********************************************************************
1416 Copy routines used by convert_to_openprinterex()
1417 *******************************************************************/
1419 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1427 DEBUG (8,("dup_devmode\n"));
1429 /* bulk copy first */
1431 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1435 /* dup the pointer members separately */
1437 len = unistrlen(devmode->devicename.buffer);
1439 d->devicename.buffer = talloc(ctx, len*2);
1440 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1445 len = unistrlen(devmode->formname.buffer);
1447 d->devicename.buffer = talloc(ctx, len*2);
1448 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1452 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1457 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1459 if (!new_ctr || !ctr)
1462 DEBUG(8,("copy_devmode_ctr\n"));
1464 new_ctr->size = ctr->size;
1465 new_ctr->devmode_ptr = ctr->devmode_ptr;
1467 if(ctr->devmode_ptr)
1468 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1471 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1473 if (!new_def || !def)
1476 DEBUG(8,("copy_printer_defaults\n"));
1478 new_def->datatype_ptr = def->datatype_ptr;
1480 if (def->datatype_ptr)
1481 copy_unistr2(&new_def->datatype, &def->datatype);
1483 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1485 new_def->access_required = def->access_required;
1488 /********************************************************************
1489 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1490 * SPOOL_Q_OPEN_PRINTER_EX structure
1491 ********************************************************************/
1493 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1495 if (!q_u_ex || !q_u)
1498 DEBUG(8,("convert_to_openprinterex\n"));
1500 q_u_ex->printername_ptr = q_u->printername_ptr;
1502 if (q_u->printername_ptr)
1503 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1505 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1508 /********************************************************************
1509 * spoolss_open_printer
1511 * called from the spoolss dispatcher
1512 ********************************************************************/
1514 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1516 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1517 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1522 ZERO_STRUCT(q_u_ex);
1523 ZERO_STRUCT(r_u_ex);
1525 /* convert the OpenPrinter() call to OpenPrinterEx() */
1527 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1529 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1531 /* convert back to OpenPrinter() */
1533 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1538 /********************************************************************
1539 * spoolss_open_printer
1541 * If the openprinterex rpc call contains a devmode,
1542 * it's a per-user one. This per-user devmode is derivated
1543 * from the global devmode. Openprinterex() contains a per-user
1544 * devmode for when you do EMF printing and spooling.
1545 * In the EMF case, the NT workstation is only doing half the job
1546 * of rendering the page. The other half is done by running the printer
1547 * driver on the server.
1548 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1549 * The EMF file only contains what is to be printed on the page.
1550 * So in order for the server to know how to print, the NT client sends
1551 * a devicemode attached to the openprinterex call.
1552 * But this devicemode is short lived, it's only valid for the current print job.
1554 * If Samba would have supported EMF spooling, this devicemode would
1555 * have been attached to the handle, to sent it to the driver to correctly
1556 * rasterize the EMF file.
1558 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1559 * we just act as a pass-thru between windows and the printer.
1561 * In order to know that Samba supports only RAW spooling, NT has to call
1562 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1563 * and until NT sends a RAW job, we refuse it.
1565 * But to call getprinter() or startdoc(), you first need a valid handle,
1566 * and to get an handle you have to call openprintex(). Hence why you have
1567 * a devicemode in the openprinterex() call.
1570 * Differences between NT4 and NT 2000.
1573 * On NT4, you only have a global devicemode. This global devicemode can be changed
1574 * by the administrator (or by a user with enough privs). Everytime a user
1575 * wants to print, the devicemode is resetted to the default. In Word, everytime
1576 * you print, the printer's characteristics are always reset to the global devicemode.
1580 * In W2K, there is the notion of per-user devicemode. The first time you use
1581 * a printer, a per-user devicemode is build from the global devicemode.
1582 * If you change your per-user devicemode, it is saved in the registry, under the
1583 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1584 * printer preferences available.
1586 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1587 * on the General Tab of the printer properties windows.
1589 * To change the global devicemode: it's the "Printing Defaults..." button
1590 * on the Advanced Tab of the printer properties window.
1593 ********************************************************************/
1595 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1597 UNISTR2 *printername = NULL;
1598 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1599 POLICY_HND *handle = &r_u->handle;
1603 struct current_user user;
1604 Printer_entry *Printer=NULL;
1606 if (q_u->printername_ptr != 0)
1607 printername = &q_u->printername;
1609 if (printername == NULL)
1610 return WERR_INVALID_PRINTER_NAME;
1612 /* some sanity check because you can open a printer or a print server */
1613 /* aka: \\server\printer or \\server */
1614 unistr2_to_ascii(name, printername, sizeof(name)-1);
1616 DEBUGADD(3,("checking name: %s\n",name));
1618 if (!open_printer_hnd(p, handle, name, 0))
1619 return WERR_INVALID_PRINTER_NAME;
1621 Printer=find_printer_index_by_hnd(p, handle);
1623 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1624 Can't find printer handle we created for printer %s\n", name ));
1625 close_printer_handle(p,handle);
1626 return WERR_INVALID_PRINTER_NAME;
1629 get_current_user(&user, p);
1632 * First case: the user is opening the print server:
1634 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1635 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1637 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1638 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1639 * or if the user is listed in the smb.conf printer admin parameter.
1641 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1642 * client view printer folder, but does not show the MSAPW.
1644 * Note: this test needs code to check access rights here too. Jeremy
1645 * could you look at this?
1647 * Second case: the user is opening a printer:
1648 * NT doesn't let us connect to a printer if the connecting user
1649 * doesn't have print permission.
1652 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1654 /* Printserver handles use global struct... */
1658 /* Map standard access rights to object specific access rights */
1660 se_map_standard(&printer_default->access_required,
1661 &printserver_std_mapping);
1663 /* Deny any object specific bits that don't apply to print
1664 servers (i.e printer and job specific bits) */
1666 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1668 if (printer_default->access_required &
1669 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1670 DEBUG(3, ("access DENIED for non-printserver bits"));
1671 close_printer_handle(p, handle);
1672 return WERR_ACCESS_DENIED;
1675 /* Allow admin access */
1677 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1679 if (!lp_ms_add_printer_wizard()) {
1680 close_printer_handle(p, handle);
1681 return WERR_ACCESS_DENIED;
1684 /* if the user is not root and not a printer admin, then fail */
1687 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1689 close_printer_handle(p, handle);
1690 return WERR_ACCESS_DENIED;
1693 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1697 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1700 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1701 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1703 /* We fall through to return WERR_OK */
1708 /* NT doesn't let us connect to a printer if the connecting user
1709 doesn't have print permission. */
1711 if (!get_printer_snum(p, handle, &snum)) {
1712 close_printer_handle(p, handle);
1716 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1718 /* map an empty access mask to the minimum access mask */
1719 if (printer_default->access_required == 0x0)
1720 printer_default->access_required = PRINTER_ACCESS_USE;
1723 * If we are not serving the printer driver for this printer,
1724 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1725 * will keep NT clients happy --jerry
1728 if (lp_use_client_driver(snum)
1729 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1731 printer_default->access_required = PRINTER_ACCESS_USE;
1734 /* check smb.conf parameters and the the sec_desc */
1736 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1737 DEBUG(3, ("access DENIED for printer open\n"));
1738 close_printer_handle(p, handle);
1739 return WERR_ACCESS_DENIED;
1742 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1743 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1744 close_printer_handle(p, handle);
1745 return WERR_ACCESS_DENIED;
1748 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1749 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1751 printer_default->access_required = PRINTER_ACCESS_USE;
1753 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1754 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1758 Printer->access_granted = printer_default->access_required;
1761 * If the client sent a devmode in the OpenPrinter() call, then
1762 * save it here in case we get a job submission on this handle
1765 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1766 && q_u->printer_default.devmode_cont.devmode_ptr )
1768 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1769 &Printer->nt_devmode );
1772 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1773 optimization in Windows 2000 clients --jerry */
1775 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1776 && (RA_WIN2K == get_remote_arch()) )
1778 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1779 sys_usleep( 500000 );
1785 /****************************************************************************
1786 ****************************************************************************/
1788 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1789 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1795 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1804 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1805 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1811 printer->info_3=NULL;
1812 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1816 printer->info_6=NULL;
1817 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1827 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1828 NT_DEVICEMODE **pp_nt_devmode)
1830 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1833 * Ensure nt_devmode is a valid pointer
1834 * as we will be overwriting it.
1837 if (nt_devmode == NULL) {
1838 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1839 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1843 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1844 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1846 nt_devmode->specversion=devmode->specversion;
1847 nt_devmode->driverversion=devmode->driverversion;
1848 nt_devmode->size=devmode->size;
1849 nt_devmode->fields=devmode->fields;
1850 nt_devmode->orientation=devmode->orientation;
1851 nt_devmode->papersize=devmode->papersize;
1852 nt_devmode->paperlength=devmode->paperlength;
1853 nt_devmode->paperwidth=devmode->paperwidth;
1854 nt_devmode->scale=devmode->scale;
1855 nt_devmode->copies=devmode->copies;
1856 nt_devmode->defaultsource=devmode->defaultsource;
1857 nt_devmode->printquality=devmode->printquality;
1858 nt_devmode->color=devmode->color;
1859 nt_devmode->duplex=devmode->duplex;
1860 nt_devmode->yresolution=devmode->yresolution;
1861 nt_devmode->ttoption=devmode->ttoption;
1862 nt_devmode->collate=devmode->collate;
1864 nt_devmode->logpixels=devmode->logpixels;
1865 nt_devmode->bitsperpel=devmode->bitsperpel;
1866 nt_devmode->pelswidth=devmode->pelswidth;
1867 nt_devmode->pelsheight=devmode->pelsheight;
1868 nt_devmode->displayflags=devmode->displayflags;
1869 nt_devmode->displayfrequency=devmode->displayfrequency;
1870 nt_devmode->icmmethod=devmode->icmmethod;
1871 nt_devmode->icmintent=devmode->icmintent;
1872 nt_devmode->mediatype=devmode->mediatype;
1873 nt_devmode->dithertype=devmode->dithertype;
1874 nt_devmode->reserved1=devmode->reserved1;
1875 nt_devmode->reserved2=devmode->reserved2;
1876 nt_devmode->panningwidth=devmode->panningwidth;
1877 nt_devmode->panningheight=devmode->panningheight;
1880 * Only change private and driverextra if the incoming devmode
1881 * has a new one. JRA.
1884 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1885 SAFE_FREE(nt_devmode->private);
1886 nt_devmode->driverextra=devmode->driverextra;
1887 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1889 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1892 *pp_nt_devmode = nt_devmode;
1897 /********************************************************************
1898 * _spoolss_enddocprinter_internal.
1899 ********************************************************************/
1901 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1903 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1907 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1911 if (!get_printer_snum(p, handle, &snum))
1914 Printer->document_started=False;
1915 print_job_end(snum, Printer->jobid,True);
1916 /* error codes unhandled so far ... */
1921 /********************************************************************
1922 * api_spoolss_closeprinter
1923 ********************************************************************/
1925 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1927 POLICY_HND *handle = &q_u->handle;
1929 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1931 if (Printer && Printer->document_started)
1932 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1934 if (!close_printer_handle(p, handle))
1937 /* clear the returned printer handle. Observed behavior
1938 from Win2k server. Don't think this really matters.
1939 Previous code just copied the value of the closed
1942 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1947 /********************************************************************
1948 * api_spoolss_deleteprinter
1950 ********************************************************************/
1952 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1954 POLICY_HND *handle = &q_u->handle;
1955 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1958 if (Printer && Printer->document_started)
1959 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1961 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1963 result = delete_printer_handle(p, handle);
1965 update_c_setprinter(False);
1970 /*******************************************************************
1971 * static function to lookup the version id corresponding to an
1972 * long architecture string
1973 ******************************************************************/
1975 static int get_version_id (char * arch)
1978 struct table_node archi_table[]= {
1980 {"Windows 4.0", "WIN40", 0 },
1981 {"Windows NT x86", "W32X86", 2 },
1982 {"Windows NT R4000", "W32MIPS", 2 },
1983 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1984 {"Windows NT PowerPC", "W32PPC", 2 },
1985 {"Windows IA64", "IA64", 3 },
1989 for (i=0; archi_table[i].long_archi != NULL; i++)
1991 if (strcmp(arch, archi_table[i].long_archi) == 0)
1992 return (archi_table[i].version);
1998 /********************************************************************
1999 * _spoolss_deleteprinterdriver
2000 ********************************************************************/
2002 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2006 NT_PRINTER_DRIVER_INFO_LEVEL info;
2007 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2009 struct current_user user;
2011 WERROR status_win2k = WERR_ACCESS_DENIED;
2013 get_current_user(&user, p);
2015 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2016 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2018 /* check that we have a valid driver name first */
2020 if ((version=get_version_id(arch)) == -1)
2021 return WERR_INVALID_ENVIRONMENT;
2024 ZERO_STRUCT(info_win2k);
2026 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2028 /* try for Win2k driver if "Windows NT x86" */
2030 if ( version == 2 ) {
2032 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2033 status = WERR_UNKNOWN_PRINTER_DRIVER;
2037 /* otherwise it was a failure */
2039 status = WERR_UNKNOWN_PRINTER_DRIVER;
2045 if (printer_driver_in_use(info.info_3)) {
2046 status = WERR_PRINTER_DRIVER_IN_USE;
2052 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2054 /* if we get to here, we now have 2 driver info structures to remove */
2055 /* remove the Win2k driver first*/
2057 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2058 free_a_printer_driver( info_win2k, 3 );
2060 /* this should not have failed---if it did, report to client */
2061 if ( !W_ERROR_IS_OK(status_win2k) )
2066 status = delete_printer_driver(info.info_3, &user, version, False);
2068 /* if at least one of the deletes succeeded return OK */
2070 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2074 free_a_printer_driver( info, 3 );
2079 /********************************************************************
2080 * spoolss_deleteprinterdriverex
2081 ********************************************************************/
2083 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2087 NT_PRINTER_DRIVER_INFO_LEVEL info;
2088 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2090 uint32 flags = q_u->delete_flags;
2092 struct current_user user;
2094 WERROR status_win2k = WERR_ACCESS_DENIED;
2096 get_current_user(&user, p);
2098 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2099 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2101 /* check that we have a valid driver name first */
2102 if ((version=get_version_id(arch)) == -1) {
2103 /* this is what NT returns */
2104 return WERR_INVALID_ENVIRONMENT;
2107 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2108 version = q_u->version;
2111 ZERO_STRUCT(info_win2k);
2113 status = get_a_printer_driver(&info, 3, driver, arch, version);
2115 if ( !W_ERROR_IS_OK(status) )
2118 * if the client asked for a specific version,
2119 * or this is something other than Windows NT x86,
2123 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2126 /* try for Win2k driver if "Windows NT x86" */
2129 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2130 status = WERR_UNKNOWN_PRINTER_DRIVER;
2135 if ( printer_driver_in_use(info.info_3) ) {
2136 status = WERR_PRINTER_DRIVER_IN_USE;
2141 * we have a couple of cases to consider.
2142 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2143 * then the delete should fail if **any** files overlap with
2145 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2146 * non-overlapping files
2147 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2148 * is set, the do not delete any files
2149 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2152 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2154 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2156 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2157 /* no idea of the correct error here */
2158 status = WERR_ACCESS_DENIED;
2163 /* also check for W32X86/3 if necessary; maybe we already have? */
2165 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2166 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2169 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2170 /* no idea of the correct error here */
2171 free_a_printer_driver( info_win2k, 3 );
2172 status = WERR_ACCESS_DENIED;
2176 /* if we get to here, we now have 2 driver info structures to remove */
2177 /* remove the Win2k driver first*/
2179 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2180 free_a_printer_driver( info_win2k, 3 );
2182 /* this should not have failed---if it did, report to client */
2184 if ( !W_ERROR_IS_OK(status_win2k) )
2189 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2191 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2194 free_a_printer_driver( info, 3 );
2200 /****************************************************************************
2201 Internal routine for retreiving printerdata
2202 ***************************************************************************/
2204 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2205 const char *key, const char *value, uint32 *type, uint8 **data,
2206 uint32 *needed, uint32 in_size )
2208 REGISTRY_VALUE *val;
2211 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2212 return WERR_BADFILE;
2214 *type = regval_type( val );
2216 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2218 size = regval_size( val );
2220 /* copy the min(in_size, len) */
2223 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2225 /* special case for 0 length values */
2227 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2231 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2240 DEBUG(5,("get_printer_dataex: copy done\n"));
2245 /****************************************************************************
2246 Internal routine for removing printerdata
2247 ***************************************************************************/
2249 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2251 return delete_printer_data( printer->info_2, key, value );
2254 /****************************************************************************
2255 Internal routine for storing printerdata
2256 ***************************************************************************/
2258 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2259 uint32 type, uint8 *data, int real_len )
2261 delete_printer_data( printer->info_2, key, value );
2263 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2266 /********************************************************************
2267 GetPrinterData on a printer server Handle.
2268 ********************************************************************/
2270 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2274 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2276 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2278 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2284 if (!StrCaseCmp(value, "BeepEnabled")) {
2286 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2288 SIVAL(*data, 0, 0x00);
2293 if (!StrCaseCmp(value, "EventLog")) {
2295 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2297 /* formally was 0x1b */
2298 SIVAL(*data, 0, 0x0);
2303 if (!StrCaseCmp(value, "NetPopup")) {
2305 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2307 SIVAL(*data, 0, 0x00);
2312 if (!StrCaseCmp(value, "MajorVersion")) {
2314 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2317 /* Windows NT 4.0 seems to not allow uploading of drivers
2318 to a server that reports 0x3 as the MajorVersion.
2319 need to investigate more how Win2k gets around this .
2322 if ( RA_WINNT == get_remote_arch() )
2331 if (!StrCaseCmp(value, "MinorVersion")) {
2333 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2341 * uint32 size = 0x114
2343 * uint32 minor = [0|1]
2344 * uint32 build = [2195|2600]
2345 * extra unicode string = e.g. "Service Pack 3"
2347 if (!StrCaseCmp(value, "OSVersion")) {
2351 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2353 ZERO_STRUCTP( *data );
2355 SIVAL(*data, 0, *needed); /* size */
2356 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2358 SIVAL(*data, 12, 2195); /* build */
2360 /* leave extra string empty */
2366 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2367 const char *string="C:\\PRINTERS";
2369 *needed = 2*(strlen(string)+1);
2370 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2372 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2374 /* it's done by hand ready to go on the wire */
2375 for (i=0; i<strlen(string); i++) {
2376 (*data)[2*i]=string[i];
2377 (*data)[2*i+1]='\0';
2382 if (!StrCaseCmp(value, "Architecture")) {
2383 const char *string="Windows NT x86";
2385 *needed = 2*(strlen(string)+1);
2386 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2388 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2389 for (i=0; i<strlen(string); i++) {
2390 (*data)[2*i]=string[i];
2391 (*data)[2*i+1]='\0';
2396 if (!StrCaseCmp(value, "DsPresent")) {
2398 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2400 SIVAL(*data, 0, 0x01);
2405 if (!StrCaseCmp(value, "DNSMachineName")) {
2408 if (!get_mydnsfullname(hostname))
2409 return WERR_BADFILE;
2411 *needed = 2*(strlen(hostname)+1);
2412 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2414 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2415 for (i=0; i<strlen(hostname); i++) {
2416 (*data)[2*i]=hostname[i];
2417 (*data)[2*i+1]='\0';
2423 return WERR_BADFILE;
2426 /********************************************************************
2427 * spoolss_getprinterdata
2428 ********************************************************************/
2430 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2432 POLICY_HND *handle = &q_u->handle;
2433 UNISTR2 *valuename = &q_u->valuename;
2434 uint32 in_size = q_u->size;
2435 uint32 *type = &r_u->type;
2436 uint32 *out_size = &r_u->size;
2437 uint8 **data = &r_u->data;
2438 uint32 *needed = &r_u->needed;
2441 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2442 NT_PRINTER_INFO_LEVEL *printer = NULL;
2446 * Reminder: when it's a string, the length is in BYTES
2447 * even if UNICODE is negociated.
2452 *out_size = in_size;
2454 /* in case of problem, return some default values */
2459 DEBUG(4,("_spoolss_getprinterdata\n"));
2462 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2463 status = WERR_BADFID;
2467 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2469 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2470 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2473 if ( !get_printer_snum(p,handle, &snum) ) {
2474 status = WERR_BADFID;
2478 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2479 if ( !W_ERROR_IS_OK(status) )
2482 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2484 if ( strequal(value, "ChangeId") ) {
2486 *needed = sizeof(uint32);
2487 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2488 status = WERR_NOMEM;
2491 SIVAL( *data, 0, printer->info_2->changeid );
2495 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2498 if (*needed > *out_size)
2499 status = WERR_MORE_DATA;
2502 if ( !W_ERROR_IS_OK(status) )
2504 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2506 /* reply this param doesn't exist */
2509 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2511 free_a_printer( &printer, 2 );
2520 /* cleanup & exit */
2523 free_a_printer( &printer, 2 );
2528 /*********************************************************
2529 Connect to the client machine.
2530 **********************************************************/
2532 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2533 struct in_addr *client_ip, const char *remote_machine)
2535 ZERO_STRUCTP(the_cli);
2537 if(cli_initialise(the_cli) == NULL) {
2538 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2542 if ( is_zero_ip(*client_ip) ) {
2543 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2544 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2545 cli_shutdown(the_cli);
2549 if (ismyip(the_cli->dest_ip)) {
2550 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2551 cli_shutdown(the_cli);
2556 the_cli->dest_ip.s_addr = client_ip->s_addr;
2557 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2558 inet_ntoa(*client_ip) ));
2561 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2562 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) ));
2563 cli_shutdown(the_cli);
2567 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2568 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2570 cli_shutdown(the_cli);
2574 the_cli->protocol = PROTOCOL_NT1;
2575 cli_setup_signing_state(the_cli, lp_client_signing());
2577 if (!cli_negprot(the_cli)) {
2578 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2579 cli_shutdown(the_cli);
2583 if (the_cli->protocol != PROTOCOL_NT1) {
2584 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2585 cli_shutdown(the_cli);
2590 * Do an anonymous session setup.
2593 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2594 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2595 cli_shutdown(the_cli);
2599 if (!(the_cli->sec_mode & 1)) {
2600 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2601 cli_shutdown(the_cli);
2605 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2606 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) ));
2607 cli_shutdown(the_cli);
2612 * Ok - we have an anonymous connection to the IPC$ share.
2613 * Now start the NT Domain stuff :-).
2616 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2617 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)));
2618 cli_nt_session_close(the_cli);
2619 cli_ulogoff(the_cli);
2620 cli_shutdown(the_cli);
2627 /***************************************************************************
2628 Connect to the client.
2629 ****************************************************************************/
2631 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2632 uint32 localprinter, uint32 type,
2633 POLICY_HND *handle, struct in_addr *client_ip)
2638 * If it's the first connection, contact the client
2639 * and connect to the IPC$ share anonymously
2641 if (smb_connections==0) {
2642 fstring unix_printer;
2644 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2646 ZERO_STRUCT(notify_cli);
2648 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2651 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2652 /* Tell the connections db we're now interested in printer
2653 * notify messages. */
2654 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2658 * Tell the specific printing tdb we want messages for this printer
2659 * by registering our PID.
2662 if (!print_notify_register_pid(snum))
2663 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2667 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2670 if (!W_ERROR_IS_OK(result))
2671 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2672 dos_errstr(result)));
2674 return (W_ERROR_IS_OK(result));
2677 /********************************************************************
2679 * ReplyFindFirstPrinterChangeNotifyEx
2681 * before replying OK: status=0 a rpc call is made to the workstation
2682 * asking ReplyOpenPrinter
2684 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2685 * called from api_spoolss_rffpcnex
2686 ********************************************************************/
2688 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2690 POLICY_HND *handle = &q_u->handle;
2691 uint32 flags = q_u->flags;
2692 uint32 options = q_u->options;
2693 UNISTR2 *localmachine = &q_u->localmachine;
2694 uint32 printerlocal = q_u->printerlocal;
2696 SPOOL_NOTIFY_OPTION *option = q_u->option;
2697 struct in_addr client_ip;
2699 /* store the notify value in the printer struct */
2701 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2704 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2708 Printer->notify.flags=flags;
2709 Printer->notify.options=options;
2710 Printer->notify.printerlocal=printerlocal;
2712 if (Printer->notify.option)
2713 free_spool_notify_option(&Printer->notify.option);
2715 Printer->notify.option=dup_spool_notify_option(option);
2717 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2718 sizeof(Printer->notify.localmachine)-1);
2720 /* Connect to the client machine and send a ReplyOpenPrinter */
2722 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2724 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2725 !get_printer_snum(p, handle, &snum) )
2728 client_ip.s_addr = inet_addr(p->conn->client_address);
2730 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2731 Printer->notify.printerlocal, 1,
2732 &Printer->notify.client_hnd, &client_ip))
2733 return WERR_SERVER_UNAVAILABLE;
2735 Printer->notify.client_connected=True;
2740 /*******************************************************************
2741 * fill a notify_info_data with the servername
2742 ********************************************************************/
2744 void spoolss_notify_server_name(int snum,
2745 SPOOL_NOTIFY_INFO_DATA *data,
2746 print_queue_struct *queue,
2747 NT_PRINTER_INFO_LEVEL *printer,
2748 TALLOC_CTX *mem_ctx)
2750 pstring temp_name, temp;
2753 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2755 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2757 data->notify_data.data.length = len;
2758 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2760 if (!data->notify_data.data.string) {
2761 data->notify_data.data.length = 0;
2765 memcpy(data->notify_data.data.string, temp, len);
2768 /*******************************************************************
2769 * fill a notify_info_data with the printername (not including the servername).
2770 ********************************************************************/
2772 void spoolss_notify_printer_name(int snum,
2773 SPOOL_NOTIFY_INFO_DATA *data,
2774 print_queue_struct *queue,
2775 NT_PRINTER_INFO_LEVEL *printer,
2776 TALLOC_CTX *mem_ctx)
2781 /* the notify name should not contain the \\server\ part */
2782 char *p = strrchr(printer->info_2->printername, '\\');
2785 p = printer->info_2->printername;
2790 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2792 data->notify_data.data.length = len;
2793 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2795 if (!data->notify_data.data.string) {
2796 data->notify_data.data.length = 0;
2800 memcpy(data->notify_data.data.string, temp, len);
2803 /*******************************************************************
2804 * fill a notify_info_data with the servicename
2805 ********************************************************************/
2807 void spoolss_notify_share_name(int snum,
2808 SPOOL_NOTIFY_INFO_DATA *data,
2809 print_queue_struct *queue,
2810 NT_PRINTER_INFO_LEVEL *printer,
2811 TALLOC_CTX *mem_ctx)
2816 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2818 data->notify_data.data.length = len;
2819 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2821 if (!data->notify_data.data.string) {
2822 data->notify_data.data.length = 0;
2826 memcpy(data->notify_data.data.string, temp, len);
2829 /*******************************************************************
2830 * fill a notify_info_data with the port name
2831 ********************************************************************/
2833 void spoolss_notify_port_name(int snum,
2834 SPOOL_NOTIFY_INFO_DATA *data,
2835 print_queue_struct *queue,
2836 NT_PRINTER_INFO_LEVEL *printer,
2837 TALLOC_CTX *mem_ctx)
2842 /* even if it's strange, that's consistant in all the code */
2844 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2846 data->notify_data.data.length = len;
2847 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2849 if (!data->notify_data.data.string) {
2850 data->notify_data.data.length = 0;
2854 memcpy(data->notify_data.data.string, temp, len);
2857 /*******************************************************************
2858 * fill a notify_info_data with the printername
2859 * but it doesn't exist, have to see what to do
2860 ********************************************************************/
2862 void spoolss_notify_driver_name(int snum,
2863 SPOOL_NOTIFY_INFO_DATA *data,
2864 print_queue_struct *queue,
2865 NT_PRINTER_INFO_LEVEL *printer,
2866 TALLOC_CTX *mem_ctx)
2871 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2873 data->notify_data.data.length = len;
2874 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2876 if (!data->notify_data.data.string) {
2877 data->notify_data.data.length = 0;
2881 memcpy(data->notify_data.data.string, temp, len);
2884 /*******************************************************************
2885 * fill a notify_info_data with the comment
2886 ********************************************************************/
2888 void spoolss_notify_comment(int snum,
2889 SPOOL_NOTIFY_INFO_DATA *data,
2890 print_queue_struct *queue,
2891 NT_PRINTER_INFO_LEVEL *printer,
2892 TALLOC_CTX *mem_ctx)
2897 if (*printer->info_2->comment == '\0')
2898 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2900 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2902 data->notify_data.data.length = len;
2903 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2905 if (!data->notify_data.data.string) {
2906 data->notify_data.data.length = 0;
2910 memcpy(data->notify_data.data.string, temp, len);
2913 /*******************************************************************
2914 * fill a notify_info_data with the comment
2915 * location = "Room 1, floor 2, building 3"
2916 ********************************************************************/
2918 void spoolss_notify_location(int snum,
2919 SPOOL_NOTIFY_INFO_DATA *data,
2920 print_queue_struct *queue,
2921 NT_PRINTER_INFO_LEVEL *printer,
2922 TALLOC_CTX *mem_ctx)
2927 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2929 data->notify_data.data.length = len;
2930 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2932 if (!data->notify_data.data.string) {
2933 data->notify_data.data.length = 0;
2937 memcpy(data->notify_data.data.string, temp, len);
2940 /*******************************************************************
2941 * fill a notify_info_data with the device mode
2942 * jfm:xxxx don't to it for know but that's a real problem !!!
2943 ********************************************************************/
2945 static void spoolss_notify_devmode(int snum,
2946 SPOOL_NOTIFY_INFO_DATA *data,
2947 print_queue_struct *queue,
2948 NT_PRINTER_INFO_LEVEL *printer,
2949 TALLOC_CTX *mem_ctx)
2953 /*******************************************************************
2954 * fill a notify_info_data with the separator file name
2955 ********************************************************************/
2957 void spoolss_notify_sepfile(int snum,
2958 SPOOL_NOTIFY_INFO_DATA *data,
2959 print_queue_struct *queue,
2960 NT_PRINTER_INFO_LEVEL *printer,
2961 TALLOC_CTX *mem_ctx)
2966 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2968 data->notify_data.data.length = len;
2969 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2971 if (!data->notify_data.data.string) {
2972 data->notify_data.data.length = 0;
2976 memcpy(data->notify_data.data.string, temp, len);
2979 /*******************************************************************
2980 * fill a notify_info_data with the print processor
2981 * jfm:xxxx return always winprint to indicate we don't do anything to it
2982 ********************************************************************/
2984 void spoolss_notify_print_processor(int snum,
2985 SPOOL_NOTIFY_INFO_DATA *data,
2986 print_queue_struct *queue,
2987 NT_PRINTER_INFO_LEVEL *printer,
2988 TALLOC_CTX *mem_ctx)
2993 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2995 data->notify_data.data.length = len;
2996 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2998 if (!data->notify_data.data.string) {
2999 data->notify_data.data.length = 0;
3003 memcpy(data->notify_data.data.string, temp, len);
3006 /*******************************************************************
3007 * fill a notify_info_data with the print processor options
3008 * jfm:xxxx send an empty string
3009 ********************************************************************/
3011 void spoolss_notify_parameters(int snum,
3012 SPOOL_NOTIFY_INFO_DATA *data,
3013 print_queue_struct *queue,
3014 NT_PRINTER_INFO_LEVEL *printer,
3015 TALLOC_CTX *mem_ctx)
3020 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3022 data->notify_data.data.length = len;
3023 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3025 if (!data->notify_data.data.string) {
3026 data->notify_data.data.length = 0;
3030 memcpy(data->notify_data.data.string, temp, len);
3033 /*******************************************************************
3034 * fill a notify_info_data with the data type
3035 * jfm:xxxx always send RAW as data type
3036 ********************************************************************/
3038 void spoolss_notify_datatype(int snum,
3039 SPOOL_NOTIFY_INFO_DATA *data,
3040 print_queue_struct *queue,
3041 NT_PRINTER_INFO_LEVEL *printer,
3042 TALLOC_CTX *mem_ctx)
3047 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3049 data->notify_data.data.length = len;
3050 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3052 if (!data->notify_data.data.string) {
3053 data->notify_data.data.length = 0;
3057 memcpy(data->notify_data.data.string, temp, len);
3060 /*******************************************************************
3061 * fill a notify_info_data with the security descriptor
3062 * jfm:xxxx send an null pointer to say no security desc
3063 * have to implement security before !
3064 ********************************************************************/
3066 static void spoolss_notify_security_desc(int snum,
3067 SPOOL_NOTIFY_INFO_DATA *data,
3068 print_queue_struct *queue,
3069 NT_PRINTER_INFO_LEVEL *printer,
3070 TALLOC_CTX *mem_ctx)
3072 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3073 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3076 /*******************************************************************
3077 * fill a notify_info_data with the attributes
3078 * jfm:xxxx a samba printer is always shared
3079 ********************************************************************/
3081 void spoolss_notify_attributes(int snum,
3082 SPOOL_NOTIFY_INFO_DATA *data,
3083 print_queue_struct *queue,
3084 NT_PRINTER_INFO_LEVEL *printer,
3085 TALLOC_CTX *mem_ctx)
3087 data->notify_data.value[0] = printer->info_2->attributes;
3088 data->notify_data.value[1] = 0;
3091 /*******************************************************************
3092 * fill a notify_info_data with the priority
3093 ********************************************************************/
3095 static void spoolss_notify_priority(int snum,
3096 SPOOL_NOTIFY_INFO_DATA *data,
3097 print_queue_struct *queue,
3098 NT_PRINTER_INFO_LEVEL *printer,
3099 TALLOC_CTX *mem_ctx)
3101 data->notify_data.value[0] = printer->info_2->priority;
3102 data->notify_data.value[1] = 0;
3105 /*******************************************************************
3106 * fill a notify_info_data with the default priority
3107 ********************************************************************/
3109 static void spoolss_notify_default_priority(int snum,
3110 SPOOL_NOTIFY_INFO_DATA *data,
3111 print_queue_struct *queue,
3112 NT_PRINTER_INFO_LEVEL *printer,
3113 TALLOC_CTX *mem_ctx)
3115 data->notify_data.value[0] = printer->info_2->default_priority;
3116 data->notify_data.value[1] = 0;
3119 /*******************************************************************
3120 * fill a notify_info_data with the start time
3121 ********************************************************************/
3123 static void spoolss_notify_start_time(int snum,
3124 SPOOL_NOTIFY_INFO_DATA *data,
3125 print_queue_struct *queue,
3126 NT_PRINTER_INFO_LEVEL *printer,
3127 TALLOC_CTX *mem_ctx)
3129 data->notify_data.value[0] = printer->info_2->starttime;
3130 data->notify_data.value[1] = 0;
3133 /*******************************************************************
3134 * fill a notify_info_data with the until time
3135 ********************************************************************/
3137 static void spoolss_notify_until_time(int snum,
3138 SPOOL_NOTIFY_INFO_DATA *data,
3139 print_queue_struct *queue,
3140 NT_PRINTER_INFO_LEVEL *printer,
3141 TALLOC_CTX *mem_ctx)
3143 data->notify_data.value[0] = printer->info_2->untiltime;
3144 data->notify_data.value[1] = 0;
3147 /*******************************************************************
3148 * fill a notify_info_data with the status
3149 ********************************************************************/
3151 static void spoolss_notify_status(int snum,
3152 SPOOL_NOTIFY_INFO_DATA *data,
3153 print_queue_struct *queue,
3154 NT_PRINTER_INFO_LEVEL *printer,
3155 TALLOC_CTX *mem_ctx)
3157 print_status_struct status;
3159 print_queue_length(snum, &status);
3160 data->notify_data.value[0]=(uint32) status.status;
3161 data->notify_data.value[1] = 0;
3164 /*******************************************************************
3165 * fill a notify_info_data with the number of jobs queued
3166 ********************************************************************/
3168 void spoolss_notify_cjobs(int snum,
3169 SPOOL_NOTIFY_INFO_DATA *data,
3170 print_queue_struct *queue,
3171 NT_PRINTER_INFO_LEVEL *printer,
3172 TALLOC_CTX *mem_ctx)
3174 data->notify_data.value[0] = print_queue_length(snum, NULL);
3175 data->notify_data.value[1] = 0;
3178 /*******************************************************************
3179 * fill a notify_info_data with the average ppm
3180 ********************************************************************/
3182 static void spoolss_notify_average_ppm(int snum,
3183 SPOOL_NOTIFY_INFO_DATA *data,
3184 print_queue_struct *queue,
3185 NT_PRINTER_INFO_LEVEL *printer,
3186 TALLOC_CTX *mem_ctx)
3188 /* always respond 8 pages per minutes */
3189 /* a little hard ! */
3190 data->notify_data.value[0] = printer->info_2->averageppm;
3191 data->notify_data.value[1] = 0;
3194 /*******************************************************************
3195 * fill a notify_info_data with username
3196 ********************************************************************/
3198 static void spoolss_notify_username(int snum,
3199 SPOOL_NOTIFY_INFO_DATA *data,
3200 print_queue_struct *queue,
3201 NT_PRINTER_INFO_LEVEL *printer,
3202 TALLOC_CTX *mem_ctx)
3207 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3209 data->notify_data.data.length = len;
3210 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3212 if (!data->notify_data.data.string) {
3213 data->notify_data.data.length = 0;
3217 memcpy(data->notify_data.data.string, temp, len);
3220 /*******************************************************************
3221 * fill a notify_info_data with job status
3222 ********************************************************************/
3224 static void spoolss_notify_job_status(int snum,
3225 SPOOL_NOTIFY_INFO_DATA *data,
3226 print_queue_struct *queue,
3227 NT_PRINTER_INFO_LEVEL *printer,
3228 TALLOC_CTX *mem_ctx)
3230 data->notify_data.value[0]=nt_printj_status(queue->status);
3231 data->notify_data.value[1] = 0;
3234 /*******************************************************************
3235 * fill a notify_info_data with job name
3236 ********************************************************************/
3238 static void spoolss_notify_job_name(int snum,
3239 SPOOL_NOTIFY_INFO_DATA *data,
3240 print_queue_struct *queue,
3241 NT_PRINTER_INFO_LEVEL *printer,
3242 TALLOC_CTX *mem_ctx)
3247 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3249 data->notify_data.data.length = len;
3250 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3252 if (!data->notify_data.data.string) {
3253 data->notify_data.data.length = 0;
3257 memcpy(data->notify_data.data.string, temp, len);
3260 /*******************************************************************
3261 * fill a notify_info_data with job status
3262 ********************************************************************/
3264 static void spoolss_notify_job_status_string(int snum,
3265 SPOOL_NOTIFY_INFO_DATA *data,
3266 print_queue_struct *queue,
3267 NT_PRINTER_INFO_LEVEL *printer,
3268 TALLOC_CTX *mem_ctx)
3271 * Now we're returning job status codes we just return a "" here. JRA.
3278 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3281 switch (queue->status) {
3286 p = ""; /* NT provides the paused string */
3295 #endif /* NO LONGER NEEDED. */
3297 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3299 data->notify_data.data.length = len;
3300 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3302 if (!data->notify_data.data.string) {
3303 data->notify_data.data.length = 0;
3307 memcpy(data->notify_data.data.string, temp, len);
3310 /*******************************************************************
3311 * fill a notify_info_data with job time
3312 ********************************************************************/
3314 static void spoolss_notify_job_time(int snum,
3315 SPOOL_NOTIFY_INFO_DATA *data,
3316 print_queue_struct *queue,
3317 NT_PRINTER_INFO_LEVEL *printer,
3318 TALLOC_CTX *mem_ctx)
3320 data->notify_data.value[0]=0x0;
3321 data->notify_data.value[1]=0;
3324 /*******************************************************************
3325 * fill a notify_info_data with job size
3326 ********************************************************************/
3328 static void spoolss_notify_job_size(int snum,
3329 SPOOL_NOTIFY_INFO_DATA *data,
3330 print_queue_struct *queue,
3331 NT_PRINTER_INFO_LEVEL *printer,
3332 TALLOC_CTX *mem_ctx)
3334 data->notify_data.value[0]=queue->size;
3335 data->notify_data.value[1]=0;
3338 /*******************************************************************
3339 * fill a notify_info_data with page info
3340 ********************************************************************/
3341 static void spoolss_notify_total_pages(int snum,
3342 SPOOL_NOTIFY_INFO_DATA *data,
3343 print_queue_struct *queue,
3344 NT_PRINTER_INFO_LEVEL *printer,
3345 TALLOC_CTX *mem_ctx)
3347 data->notify_data.value[0]=queue->page_count;
3348 data->notify_data.value[1]=0;
3351 /*******************************************************************
3352 * fill a notify_info_data with pages printed info.
3353 ********************************************************************/
3354 static void spoolss_notify_pages_printed(int snum,
3355 SPOOL_NOTIFY_INFO_DATA *data,
3356 print_queue_struct *queue,
3357 NT_PRINTER_INFO_LEVEL *printer,
3358 TALLOC_CTX *mem_ctx)
3360 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3361 data->notify_data.value[1]=0;
3364 /*******************************************************************
3365 Fill a notify_info_data with job position.
3366 ********************************************************************/
3368 static void spoolss_notify_job_position(int snum,
3369 SPOOL_NOTIFY_INFO_DATA *data,
3370 print_queue_struct *queue,
3371 NT_PRINTER_INFO_LEVEL *printer,
3372 TALLOC_CTX *mem_ctx)
3374 data->notify_data.value[0]=queue->job;
3375 data->notify_data.value[1]=0;
3378 /*******************************************************************
3379 Fill a notify_info_data with submitted time.
3380 ********************************************************************/
3382 static void spoolss_notify_submitted_time(int snum,
3383 SPOOL_NOTIFY_INFO_DATA *data,
3384 print_queue_struct *queue,
3385 NT_PRINTER_INFO_LEVEL *printer,
3386 TALLOC_CTX *mem_ctx)
3393 t=gmtime(&queue->time);
3395 len = sizeof(SYSTEMTIME);
3397 data->notify_data.data.length = len;
3398 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3400 if (!data->notify_data.data.string) {
3401 data->notify_data.data.length = 0;
3405 make_systemtime(&st, t);
3408 * Systemtime must be linearized as a set of UINT16's.
3409 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3412 p = (char *)data->notify_data.data.string;
3413 SSVAL(p, 0, st.year);
3414 SSVAL(p, 2, st.month);
3415 SSVAL(p, 4, st.dayofweek);
3416 SSVAL(p, 6, st.day);
3417 SSVAL(p, 8, st.hour);
3418 SSVAL(p, 10, st.minute);
3419 SSVAL(p, 12, st.second);
3420 SSVAL(p, 14, st.milliseconds);
3423 struct s_notify_info_data_table
3429 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3430 print_queue_struct *queue,
3431 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3434 /* A table describing the various print notification constants and
3435 whether the notification data is a pointer to a variable sized
3436 buffer, a one value uint32 or a two value uint32. */
3438 static const struct s_notify_info_data_table notify_info_data_table[] =
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3491 /*******************************************************************
3492 Return the size of info_data structure.
3493 ********************************************************************/
3495 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3499 for (i = 0; i < sizeof(notify_info_data_table); i++)
3501 if ( (notify_info_data_table[i].type == type)
3502 && (notify_info_data_table[i].field == field) )
3504 switch(notify_info_data_table[i].size)
3506 case NOTIFY_ONE_VALUE:
3507 case NOTIFY_TWO_VALUE:
3512 /* The only pointer notify data I have seen on
3513 the wire is the submitted time and this has
3514 the notify size set to 4. -tpot */
3516 case NOTIFY_POINTER:
3519 case NOTIFY_SECDESC:
3525 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3530 /*******************************************************************
3531 Return the type of notify_info_data.
3532 ********************************************************************/
3534 static int type_of_notify_info_data(uint16 type, uint16 field)
3538 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3539 if (notify_info_data_table[i].type == type &&
3540 notify_info_data_table[i].field == field)
3541 return notify_info_data_table[i].size;
3547 /****************************************************************************
3548 ****************************************************************************/
3550 static int search_notify(uint16 type, uint16 field, int *value)
3554 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3555 if (notify_info_data_table[i].type == type &&
3556 notify_info_data_table[i].field == field &&
3557 notify_info_data_table[i].fn != NULL) {
3566 /****************************************************************************
3567 ****************************************************************************/
3569 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3571 info_data->type = type;
3572 info_data->field = field;
3573 info_data->reserved = 0;
3575 info_data->size = size_of_notify_info_data(type, field);
3576 info_data->enc_type = type_of_notify_info_data(type, field);
3583 /*******************************************************************
3585 * fill a notify_info struct with info asked
3587 ********************************************************************/
3589 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3590 snum, SPOOL_NOTIFY_OPTION_TYPE
3591 *option_type, uint32 id,
3592 TALLOC_CTX *mem_ctx)
3598 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3599 NT_PRINTER_INFO_LEVEL *printer = NULL;
3600 print_queue_struct *queue=NULL;
3602 type=option_type->type;
3604 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3605 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3606 option_type->count, lp_servicename(snum)));
3608 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3611 for(field_num=0; field_num<option_type->count; field_num++) {
3612 field = option_type->fields[field_num];
3614 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3616 if (!search_notify(type, field, &j) )
3619 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3620 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3625 current_data = &info->data[info->count];
3627 construct_info_data(current_data, type, field, id);
3629 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3630 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3632 notify_info_data_table[j].fn(snum, current_data, queue,
3638 free_a_printer(&printer, 2);
3642 /*******************************************************************
3644 * fill a notify_info struct with info asked
3646 ********************************************************************/
3648 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3649 SPOOL_NOTIFY_INFO *info,
3650 NT_PRINTER_INFO_LEVEL *printer,
3651 int snum, SPOOL_NOTIFY_OPTION_TYPE
3652 *option_type, uint32 id,
3653 TALLOC_CTX *mem_ctx)
3659 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3661 DEBUG(4,("construct_notify_jobs_info\n"));
3663 type = option_type->type;
3665 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3666 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3667 option_type->count));
3669 for(field_num=0; field_num<option_type->count; field_num++) {
3670 field = option_type->fields[field_num];
3672 if (!search_notify(type, field, &j) )
3675 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3676 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3679 else info->data = tid;
3681 current_data=&(info->data[info->count]);
3683 construct_info_data(current_data, type, field, id);
3684 notify_info_data_table[j].fn(snum, current_data, queue,
3693 * JFM: The enumeration is not that simple, it's even non obvious.
3695 * let's take an example: I want to monitor the PRINTER SERVER for
3696 * the printer's name and the number of jobs currently queued.
3697 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3698 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3700 * I have 3 printers on the back of my server.
3702 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3705 * 1 printer 1 name 1
3706 * 2 printer 1 cjob 1
3707 * 3 printer 2 name 2
3708 * 4 printer 2 cjob 2
3709 * 5 printer 3 name 3
3710 * 6 printer 3 name 3
3712 * that's the print server case, the printer case is even worse.
3715 /*******************************************************************
3717 * enumerate all printers on the printserver
3718 * fill a notify_info struct with info asked
3720 ********************************************************************/
3722 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3723 SPOOL_NOTIFY_INFO *info,
3724 TALLOC_CTX *mem_ctx)
3727 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3728 int n_services=lp_numservices();
3730 SPOOL_NOTIFY_OPTION *option;
3731 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3733 DEBUG(4,("printserver_notify_info\n"));
3738 option=Printer->notify.option;
3743 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3744 sending a ffpcn() request first */
3749 for (i=0; i<option->count; i++) {
3750 option_type=&(option->ctr.type[i]);
3752 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3755 for (snum=0; snum<n_services; snum++)
3757 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3758 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3764 * Debugging information, don't delete.
3767 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3768 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3769 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3771 for (i=0; i<info->count; i++) {
3772 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3773 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3774 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3781 /*******************************************************************
3783 * fill a notify_info struct with info asked
3785 ********************************************************************/
3787 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3788 TALLOC_CTX *mem_ctx)
3791 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3794 SPOOL_NOTIFY_OPTION *option;
3795 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3797 print_queue_struct *queue=NULL;
3798 print_status_struct status;
3800 DEBUG(4,("printer_notify_info\n"));
3805 option=Printer->notify.option;
3811 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3812 sending a ffpcn() request first */
3817 get_printer_snum(p, hnd, &snum);
3819 for (i=0; i<option->count; i++) {
3820 option_type=&option->ctr.type[i];
3822 switch ( option_type->type ) {
3823 case PRINTER_NOTIFY_TYPE:
3824 if(construct_notify_printer_info(Printer, info, snum,
3830 case JOB_NOTIFY_TYPE: {
3831 NT_PRINTER_INFO_LEVEL *printer = NULL;
3833 count = print_queue_status(snum, &queue, &status);
3835 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3838 for (j=0; j<count; j++) {
3839 construct_notify_jobs_info(&queue[j], info,
3846 free_a_printer(&printer, 2);
3856 * Debugging information, don't delete.
3859 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3860 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3861 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3863 for (i=0; i<info->count; i++) {
3864 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3865 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3866 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3872 /********************************************************************
3874 ********************************************************************/
3876 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3878 POLICY_HND *handle = &q_u->handle;
3879 SPOOL_NOTIFY_INFO *info = &r_u->info;
3881 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3882 WERROR result = WERR_BADFID;
3884 /* we always have a NOTIFY_INFO struct */
3888 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3889 OUR_HANDLE(handle)));
3893 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3896 * We are now using the change value, and
3897 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3898 * I don't have a global notification system, I'm sending back all the
3899 * informations even when _NOTHING_ has changed.
3902 /* We need to keep track of the change value to send back in
3903 RRPCN replies otherwise our updates are ignored. */
3905 Printer->notify.fnpcn = True;
3907 if (Printer->notify.client_connected) {
3908 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3909 Printer->notify.change = q_u->change;
3912 /* just ignore the SPOOL_NOTIFY_OPTION */
3914 switch (Printer->printer_type) {
3915 case PRINTER_HANDLE_IS_PRINTSERVER:
3916 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3919 case PRINTER_HANDLE_IS_PRINTER:
3920 result = printer_notify_info(p, handle, info, p->mem_ctx);
3924 Printer->notify.fnpcn = False;
3930 /********************************************************************
3931 * construct_printer_info_0
3932 * fill a printer_info_0 struct
3933 ********************************************************************/
3935 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3939 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3940 counter_printer_0 *session_counter;
3941 uint32 global_counter;
3944 print_status_struct status;
3946 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3949 count = print_queue_length(snum, &status);
3951 /* check if we already have a counter for this printer */
3952 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3953 if (session_counter->snum == snum)
3957 /* it's the first time, add it to the list */
3958 if (session_counter==NULL) {
3959 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3960 free_a_printer(&ntprinter, 2);
3963 ZERO_STRUCTP(session_counter);
3964 session_counter->snum=snum;
3965 session_counter->counter=0;
3966 DLIST_ADD(counter_list, session_counter);
3970 session_counter->counter++;
3973 * the global_counter should be stored in a TDB as it's common to all the clients
3974 * and should be zeroed on samba startup
3976 global_counter=session_counter->counter;
3978 pstrcpy(chaine,ntprinter->info_2->printername);
3980 init_unistr(&printer->printername, chaine);
3982 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3983 init_unistr(&printer->servername, chaine);
3985 printer->cjobs = count;
3986 printer->total_jobs = 0;
3987 printer->total_bytes = 0;
3989 setuptime = (time_t)ntprinter->info_2->setuptime;
3990 t=gmtime(&setuptime);
3992 printer->year = t->tm_year+1900;
3993 printer->month = t->tm_mon+1;
3994 printer->dayofweek = t->tm_wday;
3995 printer->day = t->tm_mday;
3996 printer->hour = t->tm_hour;
3997 printer->minute = t->tm_min;
3998 printer->second = t->tm_sec;
3999 printer->milliseconds = 0;
4001 printer->global_counter = global_counter;
4002 printer->total_pages = 0;
4004 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4005 printer->major_version = 0x0005; /* NT 5 */
4006 printer->build_version = 0x0893; /* build 2195 */
4008 printer->unknown7 = 0x1;
4009 printer->unknown8 = 0x0;
4010 printer->unknown9 = 0x0;
4011 printer->session_counter = session_counter->counter;
4012 printer->unknown11 = 0x0;
4013 printer->printer_errors = 0x0; /* number of print failure */
4014 printer->unknown13 = 0x0;
4015 printer->unknown14 = 0x1;
4016 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4017 printer->unknown16 = 0x0;
4018 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4019 printer->unknown18 = 0x0;
4020 printer->status = nt_printq_status(status.status);
4021 printer->unknown20 = 0x0;
4022 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4023 printer->unknown22 = 0x0;
4024 printer->unknown23 = 0x6; /* 6 ???*/
4025 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4026 printer->unknown25 = 0;
4027 printer->unknown26 = 0;
4028 printer->unknown27 = 0;
4029 printer->unknown28 = 0;
4030 printer->unknown29 = 0;
4032 free_a_printer(&ntprinter,2);
4036 /********************************************************************
4037 * construct_printer_info_1
4038 * fill a printer_info_1 struct
4039 ********************************************************************/
4040 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4044 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4046 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4049 printer->flags=flags;
4051 if (*ntprinter->info_2->comment == '\0') {
4052 init_unistr(&printer->comment, lp_comment(snum));
4053 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4054 ntprinter->info_2->drivername, lp_comment(snum));
4057 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4058 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4059 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4062 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4064 init_unistr(&printer->description, chaine);
4065 init_unistr(&printer->name, chaine2);
4067 free_a_printer(&ntprinter,2);
4072 /****************************************************************************
4073 Free a DEVMODE struct.
4074 ****************************************************************************/
4076 static void free_dev_mode(DEVICEMODE *dev)
4081 SAFE_FREE(dev->private);
4086 /****************************************************************************
4087 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4088 should be valid upon entry
4089 ****************************************************************************/
4091 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4093 if ( !devmode || !ntdevmode )
4096 init_unistr(&devmode->devicename, ntdevmode->devicename);
4098 init_unistr(&devmode->formname, ntdevmode->formname);
4100 devmode->specversion = ntdevmode->specversion;
4101 devmode->driverversion = ntdevmode->driverversion;
4102 devmode->size = ntdevmode->size;
4103 devmode->driverextra = ntdevmode->driverextra;
4104 devmode->fields = ntdevmode->fields;
4106 devmode->orientation = ntdevmode->orientation;
4107 devmode->papersize = ntdevmode->papersize;
4108 devmode->paperlength = ntdevmode->paperlength;
4109 devmode->paperwidth = ntdevmode->paperwidth;
4110 devmode->scale = ntdevmode->scale;
4111 devmode->copies = ntdevmode->copies;
4112 devmode->defaultsource = ntdevmode->defaultsource;
4113 devmode->printquality = ntdevmode->printquality;
4114 devmode->color = ntdevmode->color;
4115 devmode->duplex = ntdevmode->duplex;
4116 devmode->yresolution = ntdevmode->yresolution;
4117 devmode->ttoption = ntdevmode->ttoption;
4118 devmode->collate = ntdevmode->collate;
4119 devmode->icmmethod = ntdevmode->icmmethod;
4120 devmode->icmintent = ntdevmode->icmintent;
4121 devmode->mediatype = ntdevmode->mediatype;
4122 devmode->dithertype = ntdevmode->dithertype;
4124 if (ntdevmode->private != NULL) {
4125 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4132 /****************************************************************************
4133 Create a DEVMODE struct. Returns malloced memory.
4134 ****************************************************************************/
4136 DEVICEMODE *construct_dev_mode(int snum)
4138 NT_PRINTER_INFO_LEVEL *printer = NULL;
4139 DEVICEMODE *devmode = NULL;
4141 DEBUG(7,("construct_dev_mode\n"));
4143 DEBUGADD(8,("getting printer characteristics\n"));
4145 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4148 if ( !printer->info_2->devmode ) {
4149 DEBUG(5, ("BONG! There was no device mode!\n"));
4153 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4154 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4158 ZERO_STRUCTP(devmode);
4160 DEBUGADD(8,("loading DEVICEMODE\n"));
4162 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4163 free_dev_mode( devmode );
4168 free_a_printer(&printer,2);
4173 /********************************************************************
4174 * construct_printer_info_2
4175 * fill a printer_info_2 struct
4176 ********************************************************************/
4178 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4181 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4183 print_status_struct status;
4185 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4188 count = print_queue_length(snum, &status);
4190 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4191 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4192 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4193 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4194 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4196 if (*ntprinter->info_2->comment == '\0')
4197 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4199 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4201 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4202 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4203 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4204 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4205 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4207 printer->attributes = ntprinter->info_2->attributes;
4209 printer->priority = ntprinter->info_2->priority; /* priority */
4210 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4211 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4212 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4213 printer->status = nt_printq_status(status.status); /* status */
4214 printer->cjobs = count; /* jobs */
4215 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4217 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4218 DEBUG(8, ("Returning NULL Devicemode!\n"));
4221 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4222 /* steal the printer info sec_desc structure. [badly done]. */
4223 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4224 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4225 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4226 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4229 printer->secdesc = NULL;
4232 free_a_printer(&ntprinter, 2);
4236 /********************************************************************
4237 * construct_printer_info_3
4238 * fill a printer_info_3 struct
4239 ********************************************************************/
4241 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4243 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4244 PRINTER_INFO_3 *printer = NULL;
4246 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4250 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4251 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4255 ZERO_STRUCTP(printer);
4257 printer->flags = 4; /* These are the components of the SD we are returning. */
4258 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4259 /* steal the printer info sec_desc structure. [badly done]. */
4260 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4264 * Set the flags for the components we are returning.
4267 if (printer->secdesc->owner_sid)
4268 printer->flags |= OWNER_SECURITY_INFORMATION;
4270 if (printer->secdesc->grp_sid)
4271 printer->flags |= GROUP_SECURITY_INFORMATION;
4273 if (printer->secdesc->dacl)
4274 printer->flags |= DACL_SECURITY_INFORMATION;
4276 if (printer->secdesc->sacl)
4277 printer->flags |= SACL_SECURITY_INFORMATION;
4280 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4281 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4282 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4285 free_a_printer(&ntprinter, 2);
4287 *pp_printer = printer;
4291 /********************************************************************
4292 * construct_printer_info_4
4293 * fill a printer_info_4 struct
4294 ********************************************************************/
4296 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4298 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4300 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4303 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4304 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4305 printer->attributes = ntprinter->info_2->attributes;
4307 free_a_printer(&ntprinter, 2);
4311 /********************************************************************
4312 * construct_printer_info_5
4313 * fill a printer_info_5 struct
4314 ********************************************************************/
4316 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4318 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4320 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4323 init_unistr(&printer->printername, ntprinter->info_2->printername);
4324 init_unistr(&printer->portname, ntprinter->info_2->portname);
4325 printer->attributes = ntprinter->info_2->attributes;
4327 /* these two are not used by NT+ according to MSDN */
4329 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4330 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4332 free_a_printer(&ntprinter, 2);
4337 /********************************************************************
4338 * construct_printer_info_7
4339 * fill a printer_info_7 struct
4340 ********************************************************************/
4342 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4344 char *guid_str = NULL;
4347 if (is_printer_published(print_hnd, snum, &guid)) {
4348 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4349 strupper_m(guid_str);
4350 init_unistr(&printer->guid, guid_str);
4351 printer->action = SPOOL_DS_PUBLISH;
4353 init_unistr(&printer->guid, "");
4354 printer->action = SPOOL_DS_UNPUBLISH;
4360 /********************************************************************
4361 Spoolss_enumprinters.
4362 ********************************************************************/
4364 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4368 int n_services=lp_numservices();
4369 PRINTER_INFO_1 *tp, *printers=NULL;
4370 PRINTER_INFO_1 current_prt;
4372 DEBUG(4,("enum_all_printers_info_1\n"));
4374 for (snum=0; snum<n_services; snum++) {
4375 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4376 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4378 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4379 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4380 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4381 SAFE_FREE(printers);
4386 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4388 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4394 /* check the required size. */
4395 for (i=0; i<*returned; i++)
4396 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4398 if (!alloc_buffer_size(buffer, *needed))
4399 return WERR_INSUFFICIENT_BUFFER;
4401 /* fill the buffer with the structures */
4402 for (i=0; i<*returned; i++)
4403 smb_io_printer_info_1("", buffer, &printers[i], 0);
4406 SAFE_FREE(printers);
4408 if (*needed > offered) {
4410 return WERR_INSUFFICIENT_BUFFER;
4416 /********************************************************************
4417 enum_all_printers_info_1_local.
4418 *********************************************************************/
4420 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4422 DEBUG(4,("enum_all_printers_info_1_local\n"));
4424 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4427 /********************************************************************
4428 enum_all_printers_info_1_name.
4429 *********************************************************************/
4431 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4435 DEBUG(4,("enum_all_printers_info_1_name\n"));
4437 if ((name[0] == '\\') && (name[1] == '\\'))
4440 if (is_myname_or_ipaddr(s)) {
4441 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4444 return WERR_INVALID_NAME;
4447 /********************************************************************
4448 enum_all_printers_info_1_remote.
4449 *********************************************************************/
4451 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4453 PRINTER_INFO_1 *printer;
4454 fstring printername;
4457 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4459 /* JFM: currently it's more a place holder than anything else.
4460 * In the spooler world there is a notion of server registration.
4461 * the print servers are registring (sp ?) on the PDC (in the same domain)
4463 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4466 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4471 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4472 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4473 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4475 init_unistr(&printer->description, desc);
4476 init_unistr(&printer->name, printername);
4477 init_unistr(&printer->comment, comment);
4478 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4480 /* check the required size. */
4481 *needed += spoolss_size_printer_info_1(printer);
4483 if (!alloc_buffer_size(buffer, *needed)) {
4485 return WERR_INSUFFICIENT_BUFFER;
4488 /* fill the buffer with the structures */
4489 smb_io_printer_info_1("", buffer, printer, 0);
4494 if (*needed > offered) {
4496 return WERR_INSUFFICIENT_BUFFER;
4502 /********************************************************************
4503 enum_all_printers_info_1_network.
4504 *********************************************************************/
4506 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4510 DEBUG(4,("enum_all_printers_info_1_network\n"));
4512 /* If we respond to a enum_printers level 1 on our name with flags
4513 set to PRINTER_ENUM_REMOTE with a list of printers then these
4514 printers incorrectly appear in the APW browse list.
4515 Specifically the printers for the server appear at the workgroup
4516 level where all the other servers in the domain are
4517 listed. Windows responds to this call with a
4518 WERR_CAN_NOT_COMPLETE so we should do the same. */
4520 if (name[0] == '\\' && name[1] == '\\')
4523 if (is_myname_or_ipaddr(s))
4524 return WERR_CAN_NOT_COMPLETE;
4526 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4529 /********************************************************************
4530 * api_spoolss_enumprinters
4532 * called from api_spoolss_enumprinters (see this to understand)
4533 ********************************************************************/
4535 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4539 int n_services=lp_numservices();
4540 PRINTER_INFO_2 *tp, *printers=NULL;
4541 PRINTER_INFO_2 current_prt;
4543 for (snum=0; snum<n_services; snum++) {
4544 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4545 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4547 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4548 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4549 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4550 SAFE_FREE(printers);
4555 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4556 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4562 /* check the required size. */
4563 for (i=0; i<*returned; i++)
4564 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4566 if (!alloc_buffer_size(buffer, *needed)) {
4567 for (i=0; i<*returned; i++) {
4568 free_devmode(printers[i].devmode);
4570 SAFE_FREE(printers);
4571 return WERR_INSUFFICIENT_BUFFER;
4574 /* fill the buffer with the structures */
4575 for (i=0; i<*returned; i++)
4576 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4579 for (i=0; i<*returned; i++) {
4580 free_devmode(printers[i].devmode);
4582 SAFE_FREE(printers);
4584 if (*needed > offered) {
4586 return WERR_INSUFFICIENT_BUFFER;
4592 /********************************************************************
4593 * handle enumeration of printers at level 1
4594 ********************************************************************/
4596 static WERROR enumprinters_level1( uint32 flags, fstring name,
4597 NEW_BUFFER *buffer, uint32 offered,
4598 uint32 *needed, uint32 *returned)
4600 /* Not all the flags are equals */
4602 if (flags & PRINTER_ENUM_LOCAL)
4603 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4605 if (flags & PRINTER_ENUM_NAME)
4606 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4608 if (flags & PRINTER_ENUM_REMOTE)
4609 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4611 if (flags & PRINTER_ENUM_NETWORK)
4612 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4614 return WERR_OK; /* NT4sp5 does that */
4617 /********************************************************************
4618 * handle enumeration of printers at level 2
4619 ********************************************************************/
4621 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4622 NEW_BUFFER *buffer, uint32 offered,
4623 uint32 *needed, uint32 *returned)
4625 char *s = servername;
4627 if (flags & PRINTER_ENUM_LOCAL) {
4628 return enum_all_printers_info_2(buffer, offered, needed, returned);
4631 if (flags & PRINTER_ENUM_NAME) {
4632 if ((servername[0] == '\\') && (servername[1] == '\\'))
4634 if (is_myname_or_ipaddr(s))
4635 return enum_all_printers_info_2(buffer, offered, needed, returned);
4637 return WERR_INVALID_NAME;
4640 if (flags & PRINTER_ENUM_REMOTE)
4641 return WERR_UNKNOWN_LEVEL;
4646 /********************************************************************
4647 * handle enumeration of printers at level 5
4648 ********************************************************************/
4650 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4651 NEW_BUFFER *buffer, uint32 offered,
4652 uint32 *needed, uint32 *returned)
4654 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4658 /********************************************************************
4659 * api_spoolss_enumprinters
4661 * called from api_spoolss_enumprinters (see this to understand)
4662 ********************************************************************/
4664 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4666 uint32 flags = q_u->flags;
4667 UNISTR2 *servername = &q_u->servername;
4668 uint32 level = q_u->level;
4669 NEW_BUFFER *buffer = NULL;
4670 uint32 offered = q_u->offered;
4671 uint32 *needed = &r_u->needed;
4672 uint32 *returned = &r_u->returned;
4676 /* that's an [in out] buffer */
4677 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4678 buffer = r_u->buffer;
4680 DEBUG(4,("_spoolss_enumprinters\n"));
4687 * flags==PRINTER_ENUM_NAME
4688 * if name=="" then enumerates all printers
4689 * if name!="" then enumerate the printer
4690 * flags==PRINTER_ENUM_REMOTE
4691 * name is NULL, enumerate printers
4692 * Level 2: name!="" enumerates printers, name can't be NULL
4693 * Level 3: doesn't exist
4694 * Level 4: does a local registry lookup
4695 * Level 5: same as Level 2
4698 unistr2_to_ascii(name, servername, sizeof(name)-1);
4703 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4705 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4707 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4712 return WERR_UNKNOWN_LEVEL;
4715 /****************************************************************************
4716 ****************************************************************************/
4718 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4720 PRINTER_INFO_0 *printer=NULL;
4722 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4725 construct_printer_info_0(print_hnd, printer, snum);
4727 /* check the required size. */
4728 *needed += spoolss_size_printer_info_0(printer);
4730 if (!alloc_buffer_size(buffer, *needed)) {
4732 return WERR_INSUFFICIENT_BUFFER;
4735 /* fill the buffer with the structures */
4736 smb_io_printer_info_0("", buffer, printer, 0);
4741 if (*needed > offered) {
4742 return WERR_INSUFFICIENT_BUFFER;
4748 /****************************************************************************
4749 ****************************************************************************/
4751 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4753 PRINTER_INFO_1 *printer=NULL;
4755 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4758 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4760 /* check the required size. */
4761 *needed += spoolss_size_printer_info_1(printer);
4763 if (!alloc_buffer_size(buffer, *needed)) {
4765 return WERR_INSUFFICIENT_BUFFER;
4768 /* fill the buffer with the structures */
4769 smb_io_printer_info_1("", buffer, printer, 0);
4774 if (*needed > offered) {
4775 return WERR_INSUFFICIENT_BUFFER;
4781 /****************************************************************************
4782 ****************************************************************************/
4784 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4786 PRINTER_INFO_2 *printer=NULL;
4788 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4791 construct_printer_info_2(print_hnd, printer, snum);
4793 /* check the required size. */
4794 *needed += spoolss_size_printer_info_2(printer);
4796 if (!alloc_buffer_size(buffer, *needed)) {
4797 free_printer_info_2(printer);
4798 return WERR_INSUFFICIENT_BUFFER;
4801 /* fill the buffer with the structures */
4802 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4803 free_printer_info_2(printer);
4808 free_printer_info_2(printer);
4810 if (*needed > offered) {
4811 return WERR_INSUFFICIENT_BUFFER;
4817 /****************************************************************************
4818 ****************************************************************************/
4820 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4822 PRINTER_INFO_3 *printer=NULL;
4824 if (!construct_printer_info_3(print_hnd, &printer, snum))
4827 /* check the required size. */
4828 *needed += spoolss_size_printer_info_3(printer);
4830 if (!alloc_buffer_size(buffer, *needed)) {
4831 free_printer_info_3(printer);
4832 return WERR_INSUFFICIENT_BUFFER;
4835 /* fill the buffer with the structures */
4836 smb_io_printer_info_3("", buffer, printer, 0);
4839 free_printer_info_3(printer);
4841 if (*needed > offered) {
4842 return WERR_INSUFFICIENT_BUFFER;
4848 /****************************************************************************
4849 ****************************************************************************/
4851 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4853 PRINTER_INFO_4 *printer=NULL;
4855 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4858 if (!construct_printer_info_4(print_hnd, printer, snum))
4861 /* check the required size. */
4862 *needed += spoolss_size_printer_info_4(printer);
4864 if (!alloc_buffer_size(buffer, *needed)) {
4865 free_printer_info_4(printer);
4866 return WERR_INSUFFICIENT_BUFFER;
4869 /* fill the buffer with the structures */
4870 smb_io_printer_info_4("", buffer, printer, 0);
4873 free_printer_info_4(printer);
4875 if (*needed > offered) {
4876 return WERR_INSUFFICIENT_BUFFER;
4882 /****************************************************************************
4883 ****************************************************************************/
4885 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4887 PRINTER_INFO_5 *printer=NULL;
4889 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4892 if (!construct_printer_info_5(print_hnd, printer, snum))
4895 /* check the required size. */
4896 *needed += spoolss_size_printer_info_5(printer);
4898 if (!alloc_buffer_size(buffer, *needed)) {
4899 free_printer_info_5(printer);
4900 return WERR_INSUFFICIENT_BUFFER;
4903 /* fill the buffer with the structures */
4904 smb_io_printer_info_5("", buffer, printer, 0);
4907 free_printer_info_5(printer);
4909 if (*needed > offered) {
4910 return WERR_INSUFFICIENT_BUFFER;
4916 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4918 PRINTER_INFO_7 *printer=NULL;
4920 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4923 if (!construct_printer_info_7(print_hnd, printer, snum))
4926 /* check the required size. */
4927 *needed += spoolss_size_printer_info_7(printer);
4929 if (!alloc_buffer_size(buffer, *needed)) {
4930 free_printer_info_7(printer);
4931 return WERR_INSUFFICIENT_BUFFER;
4934 /* fill the buffer with the structures */
4935 smb_io_printer_info_7("", buffer, printer, 0);
4938 free_printer_info_7(printer);
4940 if (*needed > offered) {
4941 return WERR_INSUFFICIENT_BUFFER;
4947 /****************************************************************************
4948 ****************************************************************************/
4950 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4952 POLICY_HND *handle = &q_u->handle;
4953 uint32 level = q_u->level;
4954 NEW_BUFFER *buffer = NULL;
4955 uint32 offered = q_u->offered;
4956 uint32 *needed = &r_u->needed;
4957 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4961 /* that's an [in out] buffer */
4962 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4963 buffer = r_u->buffer;
4967 if (!get_printer_snum(p, handle, &snum))
4972 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4974 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4976 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4978 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4980 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4982 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4984 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4986 return WERR_UNKNOWN_LEVEL;
4989 /********************************************************************
4990 * fill a DRIVER_INFO_1 struct
4991 ********************************************************************/
4993 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4995 init_unistr( &info->name, driver.info_3->name);
4998 /********************************************************************
4999 * construct_printer_driver_info_1
5000 ********************************************************************/
5002 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5004 NT_PRINTER_INFO_LEVEL *printer = NULL;
5005 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5007 ZERO_STRUCT(driver);
5009 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5010 return WERR_INVALID_PRINTER_NAME;
5012 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5013 return WERR_UNKNOWN_PRINTER_DRIVER;
5015 fill_printer_driver_info_1(info, driver, servername, architecture);
5017 free_a_printer(&printer,2);
5022 /********************************************************************
5023 * construct_printer_driver_info_2
5024 * fill a printer_info_2 struct
5025 ********************************************************************/
5027 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5031 info->version=driver.info_3->cversion;
5033 init_unistr( &info->name, driver.info_3->name );
5034 init_unistr( &info->architecture, driver.info_3->environment );
5037 if (strlen(driver.info_3->driverpath)) {
5038 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5039 init_unistr( &info->driverpath, temp );
5041 init_unistr( &info->driverpath, "" );
5043 if (strlen(driver.info_3->datafile)) {
5044 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5045 init_unistr( &info->datafile, temp );
5047 init_unistr( &info->datafile, "" );
5049 if (strlen(driver.info_3->configfile)) {
5050 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5051 init_unistr( &info->configfile, temp );
5053 init_unistr( &info->configfile, "" );
5056 /********************************************************************
5057 * construct_printer_driver_info_2
5058 * fill a printer_info_2 struct
5059 ********************************************************************/
5061 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5063 NT_PRINTER_INFO_LEVEL *printer = NULL;
5064 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5066 ZERO_STRUCT(printer);
5067 ZERO_STRUCT(driver);
5069 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5070 return WERR_INVALID_PRINTER_NAME;
5072 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5073 return WERR_UNKNOWN_PRINTER_DRIVER;
5075 fill_printer_driver_info_2(info, driver, servername);
5077 free_a_printer(&printer,2);
5082 /********************************************************************
5083 * copy a strings array and convert to UNICODE
5085 * convert an array of ascii string to a UNICODE string
5086 ********************************************************************/
5088 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5096 DEBUG(6,("init_unistr_array\n"));
5107 v = ""; /* hack to handle null lists */
5110 /* hack to allow this to be used in places other than when generating
5111 the list of dependent files */
5114 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5118 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5120 /* add one extra unit16 for the second terminating NULL */
5122 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5123 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5131 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5136 /* special case for ""; we need to add both NULL's here */
5138 (*uni_array)[j++]=0x0000;
5139 (*uni_array)[j]=0x0000;
5142 DEBUGADD(6,("last one:done\n"));
5144 /* return size of array in uint16's */
5149 /********************************************************************
5150 * construct_printer_info_3
5151 * fill a printer_info_3 struct
5152 ********************************************************************/
5154 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5160 info->version=driver.info_3->cversion;
5162 init_unistr( &info->name, driver.info_3->name );
5163 init_unistr( &info->architecture, driver.info_3->environment );
5165 if (strlen(driver.info_3->driverpath)) {
5166 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5167 init_unistr( &info->driverpath, temp );
5169 init_unistr( &info->driverpath, "" );
5171 if (strlen(driver.info_3->datafile)) {
5172 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5173 init_unistr( &info->datafile, temp );
5175 init_unistr( &info->datafile, "" );
5177 if (strlen(driver.info_3->configfile)) {
5178 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5179 init_unistr( &info->configfile, temp );
5181 init_unistr( &info->configfile, "" );
5183 if (strlen(driver.info_3->helpfile)) {
5184 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5185 init_unistr( &info->helpfile, temp );
5187 init_unistr( &info->helpfile, "" );
5189 init_unistr( &info->monitorname, driver.info_3->monitorname );
5190 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5192 info->dependentfiles=NULL;
5193 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5196 /********************************************************************
5197 * construct_printer_info_3
5198 * fill a printer_info_3 struct
5199 ********************************************************************/
5201 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5203 NT_PRINTER_INFO_LEVEL *printer = NULL;
5204 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5206 ZERO_STRUCT(driver);
5208 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5209 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5210 if (!W_ERROR_IS_OK(status))
5211 return WERR_INVALID_PRINTER_NAME;
5213 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5214 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5219 * I put this code in during testing. Helpful when commenting out the
5220 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5221 * as win2k always queries the driver using an infor level of 6.
5222 * I've left it in (but ifdef'd out) because I'll probably
5223 * use it in experimentation again in the future. --jerry 22/01/2002
5226 if (!W_ERROR_IS_OK(status)) {
5228 * Is this a W2k client ?
5231 /* Yes - try again with a WinNT driver. */
5233 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5234 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5238 if (!W_ERROR_IS_OK(status)) {
5239 free_a_printer(&printer,2);
5240 return WERR_UNKNOWN_PRINTER_DRIVER;
5248 fill_printer_driver_info_3(info, driver, servername);
5250 free_a_printer(&printer,2);
5255 /********************************************************************
5256 * construct_printer_info_6
5257 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5258 ********************************************************************/
5260 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5266 memset(&nullstr, '\0', sizeof(fstring));
5268 info->version=driver.info_3->cversion;
5270 init_unistr( &info->name, driver.info_3->name );
5271 init_unistr( &info->architecture, driver.info_3->environment );
5273 if (strlen(driver.info_3->driverpath)) {
5274 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5275 init_unistr( &info->driverpath, temp );
5277 init_unistr( &info->driverpath, "" );
5279 if (strlen(driver.info_3->datafile)) {
5280 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5281 init_unistr( &info->datafile, temp );
5283 init_unistr( &info->datafile, "" );
5285 if (strlen(driver.info_3->configfile)) {
5286 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5287 init_unistr( &info->configfile, temp );
5289 init_unistr( &info->configfile, "" );
5291 if (strlen(driver.info_3->helpfile)) {
5292 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5293 init_unistr( &info->helpfile, temp );
5295 init_unistr( &info->helpfile, "" );
5297 init_unistr( &info->monitorname, driver.info_3->monitorname );
5298 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5300 info->dependentfiles = NULL;
5301 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5303 info->previousdrivernames=NULL;
5304 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5306 info->driver_date.low=0;
5307 info->driver_date.high=0;
5310 info->driver_version_low=0;
5311 info->driver_version_high=0;
5313 init_unistr( &info->mfgname, "");
5314 init_unistr( &info->oem_url, "");
5315 init_unistr( &info->hardware_id, "");
5316 init_unistr( &info->provider, "");
5319 /********************************************************************
5320 * construct_printer_info_6
5321 * fill a printer_info_6 struct
5322 ********************************************************************/
5324 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5325 fstring servername, fstring architecture, uint32 version)
5327 NT_PRINTER_INFO_LEVEL *printer = NULL;
5328 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5331 ZERO_STRUCT(driver);
5333 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5335 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5337 if (!W_ERROR_IS_OK(status))
5338 return WERR_INVALID_PRINTER_NAME;
5340 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5342 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5344 if (!W_ERROR_IS_OK(status))
5347 * Is this a W2k client ?
5351 free_a_printer(&printer,2);
5352 return WERR_UNKNOWN_PRINTER_DRIVER;
5355 /* Yes - try again with a WinNT driver. */
5357 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5358 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5359 if (!W_ERROR_IS_OK(status)) {
5360 free_a_printer(&printer,2);
5361 return WERR_UNKNOWN_PRINTER_DRIVER;
5365 fill_printer_driver_info_6(info, driver, servername);
5367 free_a_printer(&printer,2);
5368 free_a_printer_driver(driver, 3);
5373 /****************************************************************************
5374 ****************************************************************************/
5376 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5378 SAFE_FREE(info->dependentfiles);
5381 /****************************************************************************
5382 ****************************************************************************/
5384 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5386 SAFE_FREE(info->dependentfiles);
5390 /****************************************************************************
5391 ****************************************************************************/
5393 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5395 DRIVER_INFO_1 *info=NULL;
5398 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5401 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5402 if (!W_ERROR_IS_OK(status)) {
5407 /* check the required size. */
5408 *needed += spoolss_size_printer_driver_info_1(info);
5410 if (!alloc_buffer_size(buffer, *needed)) {
5412 return WERR_INSUFFICIENT_BUFFER;
5415 /* fill the buffer with the structures */
5416 smb_io_printer_driver_info_1("", buffer, info, 0);
5421 if (*needed > offered)
5422 return WERR_INSUFFICIENT_BUFFER;
5427 /****************************************************************************
5428 ****************************************************************************/
5430 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5432 DRIVER_INFO_2 *info=NULL;
5435 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5438 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5439 if (!W_ERROR_IS_OK(status)) {
5444 /* check the required size. */
5445 *needed += spoolss_size_printer_driver_info_2(info);
5447 if (!alloc_buffer_size(buffer, *needed)) {
5449 return WERR_INSUFFICIENT_BUFFER;
5452 /* fill the buffer with the structures */
5453 smb_io_printer_driver_info_2("", buffer, info, 0);
5458 if (*needed > offered)
5459 return WERR_INSUFFICIENT_BUFFER;
5464 /****************************************************************************
5465 ****************************************************************************/
5467 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5474 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5475 if (!W_ERROR_IS_OK(status)) {
5479 /* check the required size. */
5480 *needed += spoolss_size_printer_driver_info_3(&info);
5482 if (!alloc_buffer_size(buffer, *needed)) {
5483 free_printer_driver_info_3(&info);
5484 return WERR_INSUFFICIENT_BUFFER;
5487 /* fill the buffer with the structures */
5488 smb_io_printer_driver_info_3("", buffer, &info, 0);
5490 free_printer_driver_info_3(&info);
5492 if (*needed > offered)
5493 return WERR_INSUFFICIENT_BUFFER;
5498 /****************************************************************************
5499 ****************************************************************************/
5501 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5508 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5509 if (!W_ERROR_IS_OK(status)) {
5513 /* check the required size. */
5514 *needed += spoolss_size_printer_driver_info_6(&info);
5516 if (!alloc_buffer_size(buffer, *needed)) {
5517 free_printer_driver_info_6(&info);
5518 return WERR_INSUFFICIENT_BUFFER;
5521 /* fill the buffer with the structures */
5522 smb_io_printer_driver_info_6("", buffer, &info, 0);
5524 free_printer_driver_info_6(&info);
5526 if (*needed > offered)
5527 return WERR_INSUFFICIENT_BUFFER;
5532 /****************************************************************************
5533 ****************************************************************************/
5535 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5537 POLICY_HND *handle = &q_u->handle;
5538 UNISTR2 *uni_arch = &q_u->architecture;
5539 uint32 level = q_u->level;
5540 uint32 clientmajorversion = q_u->clientmajorversion;
5541 NEW_BUFFER *buffer = NULL;
5542 uint32 offered = q_u->offered;
5543 uint32 *needed = &r_u->needed;
5544 uint32 *servermajorversion = &r_u->servermajorversion;
5545 uint32 *serverminorversion = &r_u->serverminorversion;
5548 fstring architecture;
5551 /* that's an [in out] buffer */
5552 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5553 buffer = r_u->buffer;
5555 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5558 *servermajorversion = 0;
5559 *serverminorversion = 0;
5561 fstrcpy(servername, get_called_name());
5562 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5564 if (!get_printer_snum(p, handle, &snum))
5569 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5571 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5573 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5575 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5578 /* apparently this call is the equivalent of
5579 EnumPrinterDataEx() for the DsDriver key */
5584 return WERR_UNKNOWN_LEVEL;
5587 /****************************************************************************
5588 ****************************************************************************/
5590 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5592 POLICY_HND *handle = &q_u->handle;
5594 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5597 DEBUG(3,("Error in startpageprinter printer handle\n"));
5601 Printer->page_started=True;
5605 /****************************************************************************
5606 ****************************************************************************/
5608 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5610 POLICY_HND *handle = &q_u->handle;
5613 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5616 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5620 if (!get_printer_snum(p, handle, &snum))
5623 Printer->page_started=False;
5624 print_job_endpage(snum, Printer->jobid);
5629 /********************************************************************
5630 * api_spoolss_getprinter
5631 * called from the spoolss dispatcher
5633 ********************************************************************/
5635 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5637 POLICY_HND *handle = &q_u->handle;
5638 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5639 uint32 *jobid = &r_u->jobid;
5641 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5645 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5646 struct current_user user;
5649 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5653 get_current_user(&user, p);
5656 * a nice thing with NT is it doesn't listen to what you tell it.
5657 * when asked to send _only_ RAW datas, it tries to send datas
5660 * So I add checks like in NT Server ...
5663 if (info_1->p_datatype != 0) {
5664 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5665 if (strcmp(datatype, "RAW") != 0) {
5667 return WERR_INVALID_DATATYPE;
5671 /* get the share number of the printer */
5672 if (!get_printer_snum(p, handle, &snum)) {
5676 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5678 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5680 /* An error occured in print_job_start() so return an appropriate
5683 if (Printer->jobid == -1) {
5684 return map_werror_from_unix(errno);
5687 Printer->document_started=True;
5688 (*jobid) = Printer->jobid;
5693 /********************************************************************
5694 * api_spoolss_getprinter
5695 * called from the spoolss dispatcher
5697 ********************************************************************/
5699 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5701 POLICY_HND *handle = &q_u->handle;
5703 return _spoolss_enddocprinter_internal(p, handle);
5706 /****************************************************************************
5707 ****************************************************************************/
5709 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5711 POLICY_HND *handle = &q_u->handle;
5712 uint32 buffer_size = q_u->buffer_size;
5713 uint8 *buffer = q_u->buffer;
5714 uint32 *buffer_written = &q_u->buffer_size2;
5716 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5719 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5720 r_u->buffer_written = q_u->buffer_size2;
5724 if (!get_printer_snum(p, handle, &snum))
5727 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5728 if (*buffer_written == -1) {
5729 r_u->buffer_written = 0;
5730 if (errno == ENOSPC)
5731 return WERR_NO_SPOOL_SPACE;
5733 return WERR_ACCESS_DENIED;
5736 r_u->buffer_written = q_u->buffer_size2;
5741 /********************************************************************
5742 * api_spoolss_getprinter
5743 * called from the spoolss dispatcher
5745 ********************************************************************/
5747 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5750 struct current_user user;
5752 WERROR errcode = WERR_BADFUNC;
5753 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5755 get_current_user(&user, p);
5758 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5762 if (!get_printer_snum(p, handle, &snum))
5766 case PRINTER_CONTROL_PAUSE:
5767 if (print_queue_pause(&user, snum, &errcode)) {
5771 case PRINTER_CONTROL_RESUME:
5772 case PRINTER_CONTROL_UNPAUSE:
5773 if (print_queue_resume(&user, snum, &errcode)) {
5777 case PRINTER_CONTROL_PURGE:
5778 if (print_queue_purge(&user, snum, &errcode)) {
5783 return WERR_UNKNOWN_LEVEL;
5789 /********************************************************************
5790 * api_spoolss_abortprinter
5791 * From MSDN: "Deletes printer's spool file if printer is configured
5793 ********************************************************************/
5795 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5797 POLICY_HND *handle = &q_u->handle;
5798 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5800 struct current_user user;
5801 WERROR errcode = WERR_OK;
5804 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5808 if (!get_printer_snum(p, handle, &snum))
5811 get_current_user( &user, p );
5813 print_job_delete( &user, snum, Printer->jobid, &errcode );
5818 /********************************************************************
5819 * called by spoolss_api_setprinter
5820 * when updating a printer description
5821 ********************************************************************/
5823 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5824 const SPOOL_PRINTER_INFO_LEVEL *info,
5825 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5827 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5828 struct current_user user;
5832 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5834 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5835 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5836 OUR_HANDLE(handle)));
5838 result = WERR_BADFID;
5842 /* NT seems to like setting the security descriptor even though
5843 nothing may have actually changed. This causes annoying
5844 dialog boxes when the user doesn't have permission to change
5845 the security descriptor. */
5847 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5849 if (DEBUGLEVEL >= 10) {
5853 the_acl = old_secdesc_ctr->sec->dacl;
5854 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5855 PRINTERNAME(snum), the_acl->num_aces));
5857 for (i = 0; i < the_acl->num_aces; i++) {
5860 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5862 DEBUG(10, ("%s 0x%08x\n", sid_str,
5863 the_acl->ace[i].info.mask));
5866 the_acl = secdesc_ctr->sec->dacl;
5869 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5870 PRINTERNAME(snum), the_acl->num_aces));
5872 for (i = 0; i < the_acl->num_aces; i++) {
5875 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5877 DEBUG(10, ("%s 0x%08x\n", sid_str,
5878 the_acl->ace[i].info.mask));
5881 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5885 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5887 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5892 /* Work out which user is performing the operation */
5894 get_current_user(&user, p);
5896 /* Check the user has permissions to change the security
5897 descriptor. By experimentation with two NT machines, the user
5898 requires Full Access to the printer to change security
5901 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5902 result = WERR_ACCESS_DENIED;
5906 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5913 /********************************************************************
5914 Do Samba sanity checks on a printer info struct.
5915 this has changed purpose: it now "canonicalises" printer
5916 info from a client rather than just checking it is correct
5917 ********************************************************************/
5919 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5921 fstring printername;
5924 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5925 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5927 /* we force some elements to "correct" values */
5928 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5929 fstrcpy(info->sharename, lp_servicename(snum));
5931 /* make sure printername is in \\server\printername format */
5933 fstrcpy( printername, info->printername );
5935 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5936 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5940 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5941 get_called_name(), p );
5943 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5944 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5951 /****************************************************************************
5952 ****************************************************************************/
5954 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5956 extern userdom_struct current_user_info;
5957 char *cmd = lp_addprinter_cmd();
5963 fstring remote_machine = "%m";
5965 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5967 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5968 cmd, printer->info_2->printername, printer->info_2->sharename,
5969 printer->info_2->portname, printer->info_2->drivername,
5970 printer->info_2->location, printer->info_2->comment, remote_machine);
5972 DEBUG(10,("Running [%s]\n", command));
5973 ret = smbrun(command, &fd);
5974 DEBUGADD(10,("returned [%d]\n", ret));
5983 /* Get lines and convert them back to dos-codepage */
5984 qlines = fd_lines_load(fd, &numlines);
5985 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5989 /* Set the portname to what the script says the portname should be. */
5990 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5991 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5993 /* Send SIGHUP to process group... is there a better way? */
5996 /* reload our services immediately */
5997 reload_services( False );
6000 file_lines_free(qlines);
6004 /********************************************************************
6005 * Called by spoolss_api_setprinter
6006 * when updating a printer description.
6007 ********************************************************************/
6009 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6010 const SPOOL_PRINTER_INFO_LEVEL *info,
6011 DEVICEMODE *devmode)
6014 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6015 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6020 DEBUG(8,("update_printer\n"));
6025 result = WERR_BADFID;
6029 if (!get_printer_snum(p, handle, &snum)) {
6030 result = WERR_BADFID;
6034 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6035 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6036 result = WERR_BADFID;
6040 DEBUGADD(8,("Converting info_2 struct\n"));
6043 * convert_printer_info converts the incoming
6044 * info from the client and overwrites the info
6045 * just read from the tdb in the pointer 'printer'.
6048 if (!convert_printer_info(info, printer, level)) {
6049 result = WERR_NOMEM;
6054 /* we have a valid devmode
6055 convert it and link it*/
6057 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6058 if (!convert_devicemode(printer->info_2->printername, devmode,
6059 &printer->info_2->devmode)) {
6060 result = WERR_NOMEM;
6065 /* Do sanity check on the requested changes for Samba */
6067 if (!check_printer_ok(printer->info_2, snum)) {
6068 result = WERR_INVALID_PARAM;
6072 /* FIXME!!! If the driver has changed we really should verify that
6073 it is installed before doing much else --jerry */
6075 /* Check calling user has permission to update printer description */
6077 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6078 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6079 result = WERR_ACCESS_DENIED;
6083 /* Call addprinter hook */
6084 /* Check changes to see if this is really needed */
6086 if ( *lp_addprinter_cmd()
6087 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6088 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6089 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6090 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6092 if ( !add_printer_hook(printer) ) {
6093 result = WERR_ACCESS_DENIED;
6098 * make sure we actually reload the services after
6099 * this as smb.conf could have a new section in it
6100 * .... shouldn't .... but could
6102 reload_services(False);
6106 * When a *new* driver is bound to a printer, the drivername is used to
6107 * lookup previously saved driver initialization info, which is then
6108 * bound to the printer, simulating what happens in the Windows arch.
6110 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6112 if (!set_driver_init(printer, 2))
6114 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6115 printer->info_2->drivername));
6118 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6119 printer->info_2->drivername));
6121 notify_printer_driver(snum, printer->info_2->drivername);
6125 * flag which changes actually occured. This is a small subset of
6126 * all the possible changes. We also have to update things in the
6130 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6131 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6132 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6133 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6135 notify_printer_comment(snum, printer->info_2->comment);
6138 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6139 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6140 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6141 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6143 notify_printer_sharename(snum, printer->info_2->sharename);
6146 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6149 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6152 pname = printer->info_2->printername;
6155 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6156 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6157 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6159 notify_printer_printername( snum, pname );
6162 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6163 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6164 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6165 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6167 notify_printer_port(snum, printer->info_2->portname);
6170 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6171 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6172 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6173 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6175 notify_printer_location(snum, printer->info_2->location);
6178 /* here we need to update some more DsSpooler keys */
6179 /* uNCName, serverName, shortServerName */
6181 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6182 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6183 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6184 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6185 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6187 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6188 global_myname(), printer->info_2->sharename );
6189 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6190 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6191 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6193 /* Update printer info */
6194 result = mod_a_printer(printer, 2);
6197 free_a_printer(&printer, 2);
6198 free_a_printer(&old_printer, 2);
6204 /****************************************************************************
6205 ****************************************************************************/
6206 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6207 const SPOOL_PRINTER_INFO_LEVEL *info)
6210 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6212 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6214 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6219 if (!get_printer_snum(p, handle, &snum))
6222 nt_printer_publish(Printer, snum, info7->action);
6226 return WERR_UNKNOWN_LEVEL;
6229 /****************************************************************************
6230 ****************************************************************************/
6232 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6234 POLICY_HND *handle = &q_u->handle;
6235 uint32 level = q_u->level;
6236 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6237 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6238 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6239 uint32 command = q_u->command;
6242 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6245 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6249 /* check the level */
6252 return control_printer(handle, command, p);
6254 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6255 if (!W_ERROR_IS_OK(result))
6258 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6261 return update_printer_sec(handle, level, info, p,
6264 return publish_or_unpublish_printer(p, handle, info);
6266 return WERR_UNKNOWN_LEVEL;
6270 /****************************************************************************
6271 ****************************************************************************/
6273 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6275 POLICY_HND *handle = &q_u->handle;
6276 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6279 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6283 if (Printer->notify.client_connected==True) {
6286 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6288 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6289 !get_printer_snum(p, handle, &snum) )
6292 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6295 Printer->notify.flags=0;
6296 Printer->notify.options=0;
6297 Printer->notify.localmachine[0]='\0';
6298 Printer->notify.printerlocal=0;
6299 if (Printer->notify.option)
6300 free_spool_notify_option(&Printer->notify.option);
6301 Printer->notify.client_connected=False;
6306 /****************************************************************************
6307 ****************************************************************************/
6309 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6311 /* that's an [in out] buffer (despite appearences to the contrary) */
6312 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6315 return WERR_INVALID_PARAM; /* this is what a NT server
6316 returns for AddJob. AddJob
6317 must fail on non-local
6321 /****************************************************************************
6322 ****************************************************************************/
6324 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6325 int position, int snum)
6331 t=gmtime(&queue->time);
6332 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6334 job_info->jobid=queue->job;
6335 init_unistr(&job_info->printername, lp_servicename(snum));
6336 init_unistr(&job_info->machinename, temp_name);
6337 init_unistr(&job_info->username, queue->fs_user);
6338 init_unistr(&job_info->document, queue->fs_file);
6339 init_unistr(&job_info->datatype, "RAW");
6340 init_unistr(&job_info->text_status, "");
6341 job_info->status=nt_printj_status(queue->status);
6342 job_info->priority=queue->priority;
6343 job_info->position=position;
6344 job_info->totalpages=queue->page_count;
6345 job_info->pagesprinted=0;
6347 make_systemtime(&job_info->submitted, t);
6350 /****************************************************************************
6351 ****************************************************************************/
6353 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6354 int position, int snum,
6355 NT_PRINTER_INFO_LEVEL *ntprinter,
6356 DEVICEMODE *devmode)
6361 t=gmtime(&queue->time);
6362 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6364 job_info->jobid=queue->job;
6366 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6368 init_unistr(&job_info->machinename, temp_name);
6369 init_unistr(&job_info->username, queue->fs_user);
6370 init_unistr(&job_info->document, queue->fs_file);
6371 init_unistr(&job_info->notifyname, queue->fs_user);
6372 init_unistr(&job_info->datatype, "RAW");
6373 init_unistr(&job_info->printprocessor, "winprint");
6374 init_unistr(&job_info->parameters, "");
6375 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6376 init_unistr(&job_info->text_status, "");
6378 /* and here the security descriptor */
6380 job_info->status=nt_printj_status(queue->status);
6381 job_info->priority=queue->priority;
6382 job_info->position=position;
6383 job_info->starttime=0;
6384 job_info->untiltime=0;
6385 job_info->totalpages=queue->page_count;
6386 job_info->size=queue->size;
6387 make_systemtime(&(job_info->submitted), t);
6388 job_info->timeelapsed=0;
6389 job_info->pagesprinted=0;
6391 job_info->devmode = devmode;
6396 /****************************************************************************
6397 Enumjobs at level 1.
6398 ****************************************************************************/
6400 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6401 NEW_BUFFER *buffer, uint32 offered,
6402 uint32 *needed, uint32 *returned)
6407 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6414 for (i=0; i<*returned; i++)
6415 fill_job_info_1(&info[i], &queue[i], i, snum);
6419 /* check the required size. */
6420 for (i=0; i<*returned; i++)
6421 (*needed) += spoolss_size_job_info_1(&info[i]);
6423 if (!alloc_buffer_size(buffer, *needed)) {
6425 return WERR_INSUFFICIENT_BUFFER;
6428 /* fill the buffer with the structures */
6429 for (i=0; i<*returned; i++)
6430 smb_io_job_info_1("", buffer, &info[i], 0);
6435 if (*needed > offered) {
6437 return WERR_INSUFFICIENT_BUFFER;
6443 /****************************************************************************
6444 Enumjobs at level 2.
6445 ****************************************************************************/
6447 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6448 NEW_BUFFER *buffer, uint32 offered,
6449 uint32 *needed, uint32 *returned)
6451 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6452 JOB_INFO_2 *info = NULL;
6455 DEVICEMODE *devmode = NULL;
6457 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6460 result = WERR_NOMEM;
6464 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6465 if (!W_ERROR_IS_OK(result)) {
6470 /* this should not be a failure condition if the devmode is NULL */
6472 devmode = construct_dev_mode(snum);
6474 for (i=0; i<*returned; i++)
6475 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6478 free_a_printer(&ntprinter, 2);
6481 /* check the required size. */
6482 for (i=0; i<*returned; i++)
6483 (*needed) += spoolss_size_job_info_2(&info[i]);
6485 if (*needed > offered) {
6487 result = WERR_INSUFFICIENT_BUFFER;
6491 if (!alloc_buffer_size(buffer, *needed)) {
6493 result = WERR_INSUFFICIENT_BUFFER;
6497 /* fill the buffer with the structures */
6498 for (i=0; i<*returned; i++)
6499 smb_io_job_info_2("", buffer, &info[i], 0);
6504 free_a_printer(&ntprinter, 2);
6505 free_devmode(devmode);
6513 /****************************************************************************
6515 ****************************************************************************/
6517 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6519 POLICY_HND *handle = &q_u->handle;
6520 uint32 level = q_u->level;
6521 NEW_BUFFER *buffer = NULL;
6522 uint32 offered = q_u->offered;
6523 uint32 *needed = &r_u->needed;
6524 uint32 *returned = &r_u->returned;
6528 print_status_struct prt_status;
6529 print_queue_struct *queue=NULL;
6531 /* that's an [in out] buffer */
6532 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6533 buffer = r_u->buffer;
6535 DEBUG(4,("_spoolss_enumjobs\n"));
6540 if (!get_printer_snum(p, handle, &snum))
6543 *returned = print_queue_status(snum, &queue, &prt_status);
6544 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6546 if (*returned == 0) {
6553 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6556 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6561 return WERR_UNKNOWN_LEVEL;
6565 /****************************************************************************
6566 ****************************************************************************/
6568 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6573 /****************************************************************************
6574 ****************************************************************************/
6576 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6578 POLICY_HND *handle = &q_u->handle;
6579 uint32 jobid = q_u->jobid;
6580 uint32 command = q_u->command;
6582 struct current_user user;
6584 WERROR errcode = WERR_BADFUNC;
6586 if (!get_printer_snum(p, handle, &snum)) {
6590 if (!print_job_exists(snum, jobid)) {
6591 return WERR_INVALID_PRINTER_NAME;
6594 get_current_user(&user, p);
6597 case JOB_CONTROL_CANCEL:
6598 case JOB_CONTROL_DELETE:
6599 if (print_job_delete(&user, snum, jobid, &errcode)) {
6603 case JOB_CONTROL_PAUSE:
6604 if (print_job_pause(&user, snum, jobid, &errcode)) {
6608 case JOB_CONTROL_RESTART:
6609 case JOB_CONTROL_RESUME:
6610 if (print_job_resume(&user, snum, jobid, &errcode)) {
6615 return WERR_UNKNOWN_LEVEL;
6621 /****************************************************************************
6622 Enumerates all printer drivers at level 1.
6623 ****************************************************************************/
6625 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6630 fstring *list = NULL;
6632 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6633 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6637 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6639 ndrivers=get_ntdrivers(&list, architecture, version);
6640 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6646 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6647 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6648 SAFE_FREE(driver_info_1);
6652 else driver_info_1 = tdi1;
6655 for (i=0; i<ndrivers; i++) {
6657 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6658 ZERO_STRUCT(driver);
6659 status = get_a_printer_driver(&driver, 3, list[i],
6660 architecture, version);
6661 if (!W_ERROR_IS_OK(status)) {
6665 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6666 free_a_printer_driver(driver, 3);
6669 *returned+=ndrivers;
6673 /* check the required size. */
6674 for (i=0; i<*returned; i++) {
6675 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6676 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6679 if (!alloc_buffer_size(buffer, *needed)) {
6680 SAFE_FREE(driver_info_1);
6681 return WERR_INSUFFICIENT_BUFFER;
6684 /* fill the buffer with the driver structures */
6685 for (i=0; i<*returned; i++) {
6686 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6687 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6690 SAFE_FREE(driver_info_1);
6692 if (*needed > offered) {
6694 return WERR_INSUFFICIENT_BUFFER;
6700 /****************************************************************************
6701 Enumerates all printer drivers at level 2.
6702 ****************************************************************************/
6704 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6709 fstring *list = NULL;
6711 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6712 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6716 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6718 ndrivers=get_ntdrivers(&list, architecture, version);
6719 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6725 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6726 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6727 SAFE_FREE(driver_info_2);
6731 else driver_info_2 = tdi2;
6734 for (i=0; i<ndrivers; i++) {
6737 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6738 ZERO_STRUCT(driver);
6739 status = get_a_printer_driver(&driver, 3, list[i],
6740 architecture, version);
6741 if (!W_ERROR_IS_OK(status)) {
6745 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6746 free_a_printer_driver(driver, 3);
6749 *returned+=ndrivers;
6753 /* check the required size. */
6754 for (i=0; i<*returned; i++) {
6755 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6756 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6759 if (!alloc_buffer_size(buffer, *needed)) {
6760 SAFE_FREE(driver_info_2);
6761 return WERR_INSUFFICIENT_BUFFER;
6764 /* fill the buffer with the form structures */
6765 for (i=0; i<*returned; i++) {
6766 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6767 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6770 SAFE_FREE(driver_info_2);
6772 if (*needed > offered) {
6774 return WERR_INSUFFICIENT_BUFFER;
6780 /****************************************************************************
6781 Enumerates all printer drivers at level 3.
6782 ****************************************************************************/
6784 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6789 fstring *list = NULL;
6791 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6792 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6796 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6798 ndrivers=get_ntdrivers(&list, architecture, version);
6799 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6805 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6806 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6807 SAFE_FREE(driver_info_3);
6811 else driver_info_3 = tdi3;
6814 for (i=0; i<ndrivers; i++) {
6817 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6818 ZERO_STRUCT(driver);
6819 status = get_a_printer_driver(&driver, 3, list[i],
6820 architecture, version);
6821 if (!W_ERROR_IS_OK(status)) {
6825 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6826 free_a_printer_driver(driver, 3);
6829 *returned+=ndrivers;
6833 /* check the required size. */
6834 for (i=0; i<*returned; i++) {
6835 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6836 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6839 if (!alloc_buffer_size(buffer, *needed)) {
6840 SAFE_FREE(driver_info_3);
6841 return WERR_INSUFFICIENT_BUFFER;
6844 /* fill the buffer with the driver structures */
6845 for (i=0; i<*returned; i++) {
6846 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6847 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6850 for (i=0; i<*returned; i++)
6851 SAFE_FREE(driver_info_3[i].dependentfiles);
6853 SAFE_FREE(driver_info_3);
6855 if (*needed > offered) {
6857 return WERR_INSUFFICIENT_BUFFER;
6863 /****************************************************************************
6864 Enumerates all printer drivers.
6865 ****************************************************************************/
6867 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6869 UNISTR2 *environment = &q_u->environment;
6870 uint32 level = q_u->level;
6871 NEW_BUFFER *buffer = NULL;
6872 uint32 offered = q_u->offered;
6873 uint32 *needed = &r_u->needed;
6874 uint32 *returned = &r_u->returned;
6876 fstring *list = NULL;
6878 fstring architecture;
6880 /* that's an [in out] buffer */
6881 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6882 buffer = r_u->buffer;
6884 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6885 fstrcpy(servername, get_called_name());
6889 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6893 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6895 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6897 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6901 return WERR_UNKNOWN_LEVEL;
6905 /****************************************************************************
6906 ****************************************************************************/
6908 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6910 form->flag=list->flag;
6911 init_unistr(&form->name, list->name);
6912 form->width=list->width;
6913 form->length=list->length;
6914 form->left=list->left;
6915 form->top=list->top;
6916 form->right=list->right;
6917 form->bottom=list->bottom;
6920 /****************************************************************************
6921 ****************************************************************************/
6923 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6925 uint32 level = q_u->level;
6926 NEW_BUFFER *buffer = NULL;
6927 uint32 offered = q_u->offered;
6928 uint32 *needed = &r_u->needed;
6929 uint32 *numofforms = &r_u->numofforms;
6930 uint32 numbuiltinforms;
6932 nt_forms_struct *list=NULL;
6933 nt_forms_struct *builtinlist=NULL;
6938 /* that's an [in out] buffer */
6939 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6940 buffer = r_u->buffer;
6942 DEBUG(4,("_spoolss_enumforms\n"));
6943 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6944 DEBUGADD(5,("Info level [%d]\n", level));
6946 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6947 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6948 *numofforms = get_ntforms(&list);
6949 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6950 *numofforms += numbuiltinforms;
6952 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6956 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6961 /* construct the list of form structures */
6962 for (i=0; i<numbuiltinforms; i++) {
6963 DEBUGADD(6,("Filling form number [%d]\n",i));
6964 fill_form_1(&forms_1[i], &builtinlist[i]);
6967 SAFE_FREE(builtinlist);
6969 for (; i<*numofforms; i++) {
6970 DEBUGADD(6,("Filling form number [%d]\n",i));
6971 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6976 /* check the required size. */
6977 for (i=0; i<numbuiltinforms; i++) {
6978 DEBUGADD(6,("adding form [%d]'s size\n",i));
6979 buffer_size += spoolss_size_form_1(&forms_1[i]);
6981 for (; i<*numofforms; i++) {
6982 DEBUGADD(6,("adding form [%d]'s size\n",i));
6983 buffer_size += spoolss_size_form_1(&forms_1[i]);
6986 *needed=buffer_size;
6988 if (!alloc_buffer_size(buffer, buffer_size)){
6990 return WERR_INSUFFICIENT_BUFFER;
6993 /* fill the buffer with the form structures */
6994 for (i=0; i<numbuiltinforms; i++) {
6995 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6996 smb_io_form_1("", buffer, &forms_1[i], 0);
6998 for (; i<*numofforms; i++) {
6999 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7000 smb_io_form_1("", buffer, &forms_1[i], 0);
7005 if (*needed > offered) {
7007 return WERR_INSUFFICIENT_BUFFER;
7014 SAFE_FREE(builtinlist);
7015 return WERR_UNKNOWN_LEVEL;
7020 /****************************************************************************
7021 ****************************************************************************/
7023 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7025 uint32 level = q_u->level;
7026 UNISTR2 *uni_formname = &q_u->formname;
7027 NEW_BUFFER *buffer = NULL;
7028 uint32 offered = q_u->offered;
7029 uint32 *needed = &r_u->needed;
7031 nt_forms_struct *list=NULL;
7032 nt_forms_struct builtin_form;
7037 int numofforms=0, i=0;
7039 /* that's an [in out] buffer */
7040 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7041 buffer = r_u->buffer;
7043 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7045 DEBUG(4,("_spoolss_getform\n"));
7046 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7047 DEBUGADD(5,("Info level [%d]\n", level));
7049 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7050 if (!foundBuiltin) {
7051 numofforms = get_ntforms(&list);
7052 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7054 if (numofforms == 0)
7061 fill_form_1(&form_1, &builtin_form);
7064 /* Check if the requested name is in the list of form structures */
7065 for (i=0; i<numofforms; i++) {
7067 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7069 if (strequal(form_name, list[i].name)) {
7070 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7071 fill_form_1(&form_1, &list[i]);
7077 if (i == numofforms) {
7081 /* check the required size. */
7083 *needed=spoolss_size_form_1(&form_1);
7085 if (!alloc_buffer_size(buffer, buffer_size)){
7086 return WERR_INSUFFICIENT_BUFFER;
7089 if (*needed > offered) {
7090 return WERR_INSUFFICIENT_BUFFER;
7093 /* fill the buffer with the form structures */
7094 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7095 smb_io_form_1("", buffer, &form_1, 0);
7101 return WERR_UNKNOWN_LEVEL;
7105 /****************************************************************************
7106 ****************************************************************************/
7108 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7110 init_unistr(&port->port_name, name);
7113 /****************************************************************************
7114 ****************************************************************************/
7116 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7118 init_unistr(&port->port_name, name);
7119 init_unistr(&port->monitor_name, "Local Monitor");
7120 init_unistr(&port->description, "Local Port");
7121 port->port_type=PORT_TYPE_WRITE;
7125 /****************************************************************************
7127 ****************************************************************************/
7129 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7131 PORT_INFO_1 *ports=NULL;
7134 if (*lp_enumports_cmd()) {
7135 char *cmd = lp_enumports_cmd();
7142 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7144 DEBUG(10,("Running [%s]\n", command));
7145 ret = smbrun(command, &fd);
7146 DEBUG(10,("Returned [%d]\n", ret));
7150 /* Is this the best error to return here? */
7151 return WERR_ACCESS_DENIED;
7155 qlines = fd_lines_load(fd, &numlines);
7156 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7160 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7161 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7162 dos_errstr(WERR_NOMEM)));
7163 file_lines_free(qlines);
7167 for (i=0; i<numlines; i++) {
7168 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7169 fill_port_1(&ports[i], qlines[i]);
7172 file_lines_free(qlines);
7175 *returned = numlines;
7178 *returned = 1; /* Sole Samba port returned. */
7180 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7183 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7185 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7188 /* check the required size. */
7189 for (i=0; i<*returned; i++) {
7190 DEBUGADD(6,("adding port [%d]'s size\n", i));
7191 *needed += spoolss_size_port_info_1(&ports[i]);
7194 if (!alloc_buffer_size(buffer, *needed)) {
7196 return WERR_INSUFFICIENT_BUFFER;
7199 /* fill the buffer with the ports structures */
7200 for (i=0; i<*returned; i++) {
7201 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7202 smb_io_port_1("", buffer, &ports[i], 0);
7207 if (*needed > offered) {
7209 return WERR_INSUFFICIENT_BUFFER;
7215 /****************************************************************************
7217 ****************************************************************************/
7219 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7221 PORT_INFO_2 *ports=NULL;
7224 if (*lp_enumports_cmd()) {
7225 char *cmd = lp_enumports_cmd();
7234 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7235 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7237 path = lp_lockdir();
7239 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7240 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7243 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7244 ret = smbrun(command, &fd);
7245 DEBUGADD(10,("returned [%d]\n", ret));
7249 /* Is this the best error to return here? */
7250 return WERR_ACCESS_DENIED;
7254 qlines = fd_lines_load(fd, &numlines);
7255 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7259 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7260 file_lines_free(qlines);
7264 for (i=0; i<numlines; i++) {
7265 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7266 fill_port_2(&(ports[i]), qlines[i]);
7269 file_lines_free(qlines);
7272 *returned = numlines;
7278 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7281 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7283 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7286 /* check the required size. */
7287 for (i=0; i<*returned; i++) {
7288 DEBUGADD(6,("adding port [%d]'s size\n", i));
7289 *needed += spoolss_size_port_info_2(&ports[i]);
7292 if (!alloc_buffer_size(buffer, *needed)) {
7294 return WERR_INSUFFICIENT_BUFFER;
7297 /* fill the buffer with the ports structures */
7298 for (i=0; i<*returned; i++) {
7299 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7300 smb_io_port_2("", buffer, &ports[i], 0);
7305 if (*needed > offered) {
7307 return WERR_INSUFFICIENT_BUFFER;
7313 /****************************************************************************
7315 ****************************************************************************/
7317 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7319 uint32 level = q_u->level;
7320 NEW_BUFFER *buffer = NULL;
7321 uint32 offered = q_u->offered;
7322 uint32 *needed = &r_u->needed;
7323 uint32 *returned = &r_u->returned;
7325 /* that's an [in out] buffer */
7326 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7327 buffer = r_u->buffer;
7329 DEBUG(4,("_spoolss_enumports\n"));
7336 return enumports_level_1(buffer, offered, needed, returned);
7338 return enumports_level_2(buffer, offered, needed, returned);
7340 return WERR_UNKNOWN_LEVEL;
7344 /****************************************************************************
7345 ****************************************************************************/
7347 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7348 const SPOOL_PRINTER_INFO_LEVEL *info,
7349 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7350 uint32 user_switch, const SPOOL_USER_CTR *user,
7353 NT_PRINTER_INFO_LEVEL *printer = NULL;
7356 WERROR err = WERR_OK;
7358 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7359 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7363 ZERO_STRUCTP(printer);
7365 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7366 if (!convert_printer_info(info, printer, 2)) {
7367 free_a_printer(&printer, 2);
7371 /* check to see if the printer already exists */
7373 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7374 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7375 printer->info_2->sharename));
7376 free_a_printer(&printer, 2);
7377 return WERR_PRINTER_ALREADY_EXISTS;
7380 /* FIXME!!! smbd should check to see if the driver is installed before
7381 trying to add a printer like this --jerry */
7383 if (*lp_addprinter_cmd() ) {
7384 if ( !add_printer_hook(printer) ) {
7385 free_a_printer(&printer,2);
7386 return WERR_ACCESS_DENIED;
7390 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7391 printer->info_2->sharename);
7394 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7395 free_a_printer(&printer,2);
7396 return WERR_ACCESS_DENIED;
7399 /* you must be a printer admin to add a new printer */
7400 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7401 free_a_printer(&printer,2);
7402 return WERR_ACCESS_DENIED;
7406 * Do sanity check on the requested changes for Samba.
7409 if (!check_printer_ok(printer->info_2, snum)) {
7410 free_a_printer(&printer,2);
7411 return WERR_INVALID_PARAM;
7415 * When a printer is created, the drivername bound to the printer is used
7416 * to lookup previously saved driver initialization info, which is then
7417 * bound to the new printer, simulating what happens in the Windows arch.
7422 set_driver_init(printer, 2);
7426 /* A valid devmode was included, convert and link it
7428 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7430 if (!convert_devicemode(printer->info_2->printername, devmode,
7431 &printer->info_2->devmode))
7435 /* write the ASCII on disk */
7436 err = mod_a_printer(printer, 2);
7437 if (!W_ERROR_IS_OK(err)) {
7438 free_a_printer(&printer,2);
7442 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7443 /* Handle open failed - remove addition. */
7444 del_a_printer(printer->info_2->sharename);
7445 free_a_printer(&printer,2);
7446 return WERR_ACCESS_DENIED;
7449 update_c_setprinter(False);
7450 free_a_printer(&printer,2);
7455 /****************************************************************************
7456 ****************************************************************************/
7458 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7460 UNISTR2 *uni_srv_name = &q_u->server_name;
7461 uint32 level = q_u->level;
7462 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7463 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7464 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7465 uint32 user_switch = q_u->user_switch;
7466 SPOOL_USER_CTR *user = &q_u->user_ctr;
7467 POLICY_HND *handle = &r_u->handle;
7471 /* we don't handle yet */
7472 /* but I know what to do ... */
7473 return WERR_UNKNOWN_LEVEL;
7475 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7477 user_switch, user, handle);
7479 return WERR_UNKNOWN_LEVEL;
7483 /****************************************************************************
7484 ****************************************************************************/
7486 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7488 uint32 level = q_u->level;
7489 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7490 WERROR err = WERR_OK;
7491 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7492 struct current_user user;
7493 fstring driver_name;
7496 ZERO_STRUCT(driver);
7498 get_current_user(&user, p);
7500 if (!convert_printer_driver_info(info, &driver, level)) {
7505 DEBUG(5,("Cleaning driver's information\n"));
7506 err = clean_up_driver_struct(driver, level, &user);
7507 if (!W_ERROR_IS_OK(err))
7510 DEBUG(5,("Moving driver to final destination\n"));
7511 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7512 if (W_ERROR_IS_OK(err))
7513 err = WERR_ACCESS_DENIED;
7517 if (add_a_printer_driver(driver, level)!=0) {
7518 err = WERR_ACCESS_DENIED;
7522 /* BEGIN_ADMIN_LOG */
7525 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7526 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7527 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7530 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7531 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7532 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7538 * I think this is where he DrvUpgradePrinter() hook would be
7539 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7540 * server. Right now, we just need to send ourselves a message
7541 * to update each printer bound to this driver. --jerry
7544 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7545 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7550 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7551 * decide if the driver init data should be deleted. The rules are:
7552 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7553 * 2) delete init data only if there is no 2k/Xp driver
7554 * 3) always delete init data
7555 * The generalized rule is always use init data from the highest order driver.
7556 * It is necessary to follow the driver install by an initialization step to
7557 * finish off this process.
7560 version = driver.info_3->cversion;
7561 else if (level == 6)
7562 version = driver.info_6->version;
7567 * 9x printer driver - never delete init data
7570 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7575 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7576 * there is no 2k/Xp driver init data for this driver name.
7580 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7582 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7584 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7586 if (!del_driver_init(driver_name))
7587 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7590 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7592 free_a_printer_driver(driver1,3);
7593 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7600 * 2k or Xp printer driver - always delete init data
7603 if (!del_driver_init(driver_name))
7604 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7608 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7614 free_a_printer_driver(driver, level);
7618 /********************************************************************
7619 * spoolss_addprinterdriverex
7620 ********************************************************************/
7622 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7624 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7625 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7628 * we only support the semantics of AddPrinterDriver()
7629 * i.e. only copy files that are newer than existing ones
7632 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7633 return WERR_ACCESS_DENIED;
7635 ZERO_STRUCT(q_u_local);
7636 ZERO_STRUCT(r_u_local);
7638 /* just pass the information off to _spoolss_addprinterdriver() */
7639 q_u_local.server_name_ptr = q_u->server_name_ptr;
7640 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7641 q_u_local.level = q_u->level;
7642 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7644 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7647 /****************************************************************************
7648 ****************************************************************************/
7650 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7652 init_unistr(&info->name, name);
7655 /****************************************************************************
7656 ****************************************************************************/
7658 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7662 const char *short_archi;
7663 DRIVER_DIRECTORY_1 *info=NULL;
7665 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7667 if (!(short_archi = get_short_archi(long_archi)))
7668 return WERR_INVALID_ENVIRONMENT;
7670 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7673 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7675 DEBUG(4,("printer driver directory: [%s]\n", path));
7677 fill_driverdir_1(info, path);
7679 *needed += spoolss_size_driverdir_info_1(info);
7681 if (!alloc_buffer_size(buffer, *needed)) {
7683 return WERR_INSUFFICIENT_BUFFER;
7686 smb_io_driverdir_1("", buffer, info, 0);
7690 if (*needed > offered)
7691 return WERR_INSUFFICIENT_BUFFER;
7696 /****************************************************************************
7697 ****************************************************************************/
7699 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7701 UNISTR2 *name = &q_u->name;
7702 UNISTR2 *uni_environment = &q_u->environment;
7703 uint32 level = q_u->level;
7704 NEW_BUFFER *buffer = NULL;
7705 uint32 offered = q_u->offered;
7706 uint32 *needed = &r_u->needed;
7708 /* that's an [in out] buffer */
7709 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7710 buffer = r_u->buffer;
7712 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7718 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7720 return WERR_UNKNOWN_LEVEL;
7724 /****************************************************************************
7725 ****************************************************************************/
7727 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7729 POLICY_HND *handle = &q_u->handle;
7730 uint32 idx = q_u->index;
7731 uint32 in_value_len = q_u->valuesize;
7732 uint32 in_data_len = q_u->datasize;
7733 uint32 *out_max_value_len = &r_u->valuesize;
7734 uint16 **out_value = &r_u->value;
7735 uint32 *out_value_len = &r_u->realvaluesize;
7736 uint32 *out_type = &r_u->type;
7737 uint32 *out_max_data_len = &r_u->datasize;
7738 uint8 **data_out = &r_u->data;
7739 uint32 *out_data_len = &r_u->realdatasize;
7741 NT_PRINTER_INFO_LEVEL *printer = NULL;
7743 uint32 biggest_valuesize;
7744 uint32 biggest_datasize;
7746 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7749 REGISTRY_VALUE *val = NULL;
7750 NT_PRINTER_DATA *p_data;
7751 int i, key_index, num_values;
7754 ZERO_STRUCT( printer );
7758 *out_max_data_len = 0;
7762 DEBUG(5,("spoolss_enumprinterdata\n"));
7765 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7769 if (!get_printer_snum(p,handle, &snum))
7772 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7773 if (!W_ERROR_IS_OK(result))
7776 p_data = &printer->info_2->data;
7777 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7782 * The NT machine wants to know the biggest size of value and data
7784 * cf: MSDN EnumPrinterData remark section
7787 if ( !in_value_len && !in_data_len && (key_index != -1) )
7789 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7791 biggest_valuesize = 0;
7792 biggest_datasize = 0;
7794 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7796 for ( i=0; i<num_values; i++ )
7798 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7800 name_length = strlen(val->valuename);
7801 if ( strlen(val->valuename) > biggest_valuesize )
7802 biggest_valuesize = name_length;
7804 if ( val->size > biggest_datasize )
7805 biggest_datasize = val->size;
7807 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7811 /* the value is an UNICODE string but real_value_size is the length
7812 in bytes including the trailing 0 */
7814 *out_value_len = 2 * (1+biggest_valuesize);
7815 *out_data_len = biggest_datasize;
7817 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7823 * the value len is wrong in NT sp3
7824 * that's the number of bytes not the number of unicode chars
7827 if ( key_index != -1 )
7828 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7833 /* out_value should default to "" or else NT4 has
7834 problems unmarshalling the response */
7836 *out_max_value_len=(in_value_len/sizeof(uint16));
7838 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7840 result = WERR_NOMEM;
7844 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7846 /* the data is counted in bytes */
7848 *out_max_data_len = in_data_len;
7849 *out_data_len = in_data_len;
7851 /* only allocate when given a non-zero data_len */
7853 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7855 result = WERR_NOMEM;
7859 result = WERR_NO_MORE_ITEMS;
7865 * - counted in bytes in the request
7866 * - counted in UNICODE chars in the max reply
7867 * - counted in bytes in the real size
7869 * take a pause *before* coding not *during* coding
7873 *out_max_value_len=(in_value_len/sizeof(uint16));
7874 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7876 result = WERR_NOMEM;
7880 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7884 *out_type = regval_type( val );
7886 /* data - counted in bytes */
7888 *out_max_data_len = in_data_len;
7889 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7891 result = WERR_NOMEM;
7894 data_len = (size_t)regval_size(val);
7895 memcpy( *data_out, regval_data_p(val), data_len );
7896 *out_data_len = data_len;
7900 free_a_printer(&printer, 2);
7904 /****************************************************************************
7905 ****************************************************************************/
7907 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7909 POLICY_HND *handle = &q_u->handle;
7910 UNISTR2 *value = &q_u->value;
7911 uint32 type = q_u->type;
7912 uint8 *data = q_u->data;
7913 uint32 real_len = q_u->real_len;
7915 NT_PRINTER_INFO_LEVEL *printer = NULL;
7917 WERROR status = WERR_OK;
7918 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7921 DEBUG(5,("spoolss_setprinterdata\n"));
7924 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7928 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7929 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7930 return WERR_INVALID_PARAM;
7933 if (!get_printer_snum(p,handle, &snum))
7937 * Access check : NT returns "access denied" if you make a
7938 * SetPrinterData call without the necessary privildge.
7939 * we were originally returning OK if nothing changed
7940 * which made Win2k issue **a lot** of SetPrinterData
7941 * when connecting to a printer --jerry
7944 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7946 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7947 status = WERR_ACCESS_DENIED;
7951 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7952 if (!W_ERROR_IS_OK(status))
7955 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7958 * When client side code sets a magic printer data key, detect it and save
7959 * the current printer data and the magic key's data (its the DEVMODE) for
7960 * future printer/driver initializations.
7962 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7964 /* Set devmode and printer initialization info */
7965 status = save_driver_init( printer, 2, data, real_len );
7967 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7971 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7972 type, data, real_len );
7973 if ( W_ERROR_IS_OK(status) )
7974 status = mod_a_printer(printer, 2);
7978 free_a_printer(&printer, 2);
7983 /****************************************************************************
7984 ****************************************************************************/
7986 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7988 POLICY_HND *handle = &q_u->handle;
7989 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7992 DEBUG(5,("_spoolss_resetprinter\n"));
7995 * All we do is to check to see if the handle and queue is valid.
7996 * This call really doesn't mean anything to us because we only
7997 * support RAW printing. --jerry
8001 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8005 if (!get_printer_snum(p,handle, &snum))
8009 /* blindly return success */
8014 /****************************************************************************
8015 ****************************************************************************/
8017 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8019 POLICY_HND *handle = &q_u->handle;
8020 UNISTR2 *value = &q_u->valuename;
8022 NT_PRINTER_INFO_LEVEL *printer = NULL;
8024 WERROR status = WERR_OK;
8025 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8028 DEBUG(5,("spoolss_deleteprinterdata\n"));
8031 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8035 if (!get_printer_snum(p, handle, &snum))
8038 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8039 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8040 return WERR_ACCESS_DENIED;
8043 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8044 if (!W_ERROR_IS_OK(status))
8047 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8049 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8051 if ( W_ERROR_IS_OK(status) )
8052 mod_a_printer( printer, 2 );
8054 free_a_printer(&printer, 2);
8059 /****************************************************************************
8060 ****************************************************************************/
8062 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8064 POLICY_HND *handle = &q_u->handle;
8065 FORM *form = &q_u->form;
8066 nt_forms_struct tmpForm;
8068 WERROR status = WERR_OK;
8069 NT_PRINTER_INFO_LEVEL *printer = NULL;
8072 nt_forms_struct *list=NULL;
8073 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8075 DEBUG(5,("spoolss_addform\n"));
8078 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8083 /* forms can be added on printer of on the print server handle */
8085 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8087 if (!get_printer_snum(p,handle, &snum))
8090 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8091 if (!W_ERROR_IS_OK(status))
8095 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8096 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8097 status = WERR_ACCESS_DENIED;
8101 /* can't add if builtin */
8103 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8104 status = WERR_ALREADY_EXISTS;
8108 count = get_ntforms(&list);
8110 if(!add_a_form(&list, form, &count)) {
8111 status = WERR_NOMEM;
8115 write_ntforms(&list, count);
8118 * ChangeID must always be set if this is a printer
8121 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8122 status = mod_a_printer(printer, 2);
8126 free_a_printer(&printer, 2);
8132 /****************************************************************************
8133 ****************************************************************************/
8135 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8137 POLICY_HND *handle = &q_u->handle;
8138 UNISTR2 *form_name = &q_u->name;
8139 nt_forms_struct tmpForm;
8141 nt_forms_struct *list=NULL;
8142 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8144 WERROR status = WERR_OK;
8145 NT_PRINTER_INFO_LEVEL *printer = NULL;
8147 DEBUG(5,("spoolss_deleteform\n"));
8150 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8154 /* forms can be deleted on printer of on the print server handle */
8156 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8158 if (!get_printer_snum(p,handle, &snum))
8161 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8162 if (!W_ERROR_IS_OK(status))
8166 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8167 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8168 status = WERR_ACCESS_DENIED;
8172 /* can't delete if builtin */
8174 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8175 status = WERR_INVALID_PARAM;
8179 count = get_ntforms(&list);
8181 if ( !delete_a_form(&list, form_name, &count, &status ))
8185 * ChangeID must always be set if this is a printer
8188 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8189 status = mod_a_printer(printer, 2);
8193 free_a_printer(&printer, 2);
8199 /****************************************************************************
8200 ****************************************************************************/
8202 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8204 POLICY_HND *handle = &q_u->handle;
8205 FORM *form = &q_u->form;
8206 nt_forms_struct tmpForm;
8208 WERROR status = WERR_OK;
8209 NT_PRINTER_INFO_LEVEL *printer = NULL;
8212 nt_forms_struct *list=NULL;
8213 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8215 DEBUG(5,("spoolss_setform\n"));
8218 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8222 /* forms can be modified on printer of on the print server handle */
8224 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8226 if (!get_printer_snum(p,handle, &snum))
8229 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8230 if (!W_ERROR_IS_OK(status))
8234 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8235 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8236 status = WERR_ACCESS_DENIED;
8240 /* can't set if builtin */
8241 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8242 status = WERR_INVALID_PARAM;
8246 count = get_ntforms(&list);
8247 update_a_form(&list, form, count);
8248 write_ntforms(&list, count);
8251 * ChangeID must always be set if this is a printer
8254 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8255 status = mod_a_printer(printer, 2);
8260 free_a_printer(&printer, 2);
8266 /****************************************************************************
8267 enumprintprocessors level 1.
8268 ****************************************************************************/
8270 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8272 PRINTPROCESSOR_1 *info_1=NULL;
8274 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8279 init_unistr(&info_1->name, "winprint");
8281 *needed += spoolss_size_printprocessor_info_1(info_1);
8283 if (!alloc_buffer_size(buffer, *needed))
8284 return WERR_INSUFFICIENT_BUFFER;
8286 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8290 if (*needed > offered) {
8292 return WERR_INSUFFICIENT_BUFFER;
8298 /****************************************************************************
8299 ****************************************************************************/
8301 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8303 uint32 level = q_u->level;
8304 NEW_BUFFER *buffer = NULL;
8305 uint32 offered = q_u->offered;
8306 uint32 *needed = &r_u->needed;
8307 uint32 *returned = &r_u->returned;
8309 /* that's an [in out] buffer */
8310 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8311 buffer = r_u->buffer;
8313 DEBUG(5,("spoolss_enumprintprocessors\n"));
8316 * Enumerate the print processors ...
8318 * Just reply with "winprint", to keep NT happy
8319 * and I can use my nice printer checker.
8327 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8329 return WERR_UNKNOWN_LEVEL;
8333 /****************************************************************************
8334 enumprintprocdatatypes level 1.
8335 ****************************************************************************/
8337 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8339 PRINTPROCDATATYPE_1 *info_1=NULL;
8341 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8346 init_unistr(&info_1->name, "RAW");
8348 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8350 if (!alloc_buffer_size(buffer, *needed))
8351 return WERR_INSUFFICIENT_BUFFER;
8353 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8357 if (*needed > offered) {
8359 return WERR_INSUFFICIENT_BUFFER;
8365 /****************************************************************************
8366 ****************************************************************************/
8368 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8370 uint32 level = q_u->level;
8371 NEW_BUFFER *buffer = NULL;
8372 uint32 offered = q_u->offered;
8373 uint32 *needed = &r_u->needed;
8374 uint32 *returned = &r_u->returned;
8376 /* that's an [in out] buffer */
8377 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8378 buffer = r_u->buffer;
8380 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8387 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8389 return WERR_UNKNOWN_LEVEL;
8393 /****************************************************************************
8394 enumprintmonitors level 1.
8395 ****************************************************************************/
8397 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8399 PRINTMONITOR_1 *info_1=NULL;
8401 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8406 init_unistr(&info_1->name, "Local Port");
8408 *needed += spoolss_size_printmonitor_info_1(info_1);
8410 if (!alloc_buffer_size(buffer, *needed))
8411 return WERR_INSUFFICIENT_BUFFER;
8413 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8417 if (*needed > offered) {
8419 return WERR_INSUFFICIENT_BUFFER;
8425 /****************************************************************************
8426 enumprintmonitors level 2.
8427 ****************************************************************************/
8429 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8431 PRINTMONITOR_2 *info_2=NULL;
8433 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8438 init_unistr(&info_2->name, "Local Port");
8439 init_unistr(&info_2->environment, "Windows NT X86");
8440 init_unistr(&info_2->dll_name, "localmon.dll");
8442 *needed += spoolss_size_printmonitor_info_2(info_2);
8444 if (!alloc_buffer_size(buffer, *needed))
8445 return WERR_INSUFFICIENT_BUFFER;
8447 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8451 if (*needed > offered) {
8453 return WERR_INSUFFICIENT_BUFFER;
8459 /****************************************************************************
8460 ****************************************************************************/
8462 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8464 uint32 level = q_u->level;
8465 NEW_BUFFER *buffer = NULL;
8466 uint32 offered = q_u->offered;
8467 uint32 *needed = &r_u->needed;
8468 uint32 *returned = &r_u->returned;
8470 /* that's an [in out] buffer */
8471 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8472 buffer = r_u->buffer;
8474 DEBUG(5,("spoolss_enumprintmonitors\n"));
8477 * Enumerate the print monitors ...
8479 * Just reply with "Local Port", to keep NT happy
8480 * and I can use my nice printer checker.
8488 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8490 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8492 return WERR_UNKNOWN_LEVEL;
8496 /****************************************************************************
8497 ****************************************************************************/
8499 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8503 JOB_INFO_1 *info_1=NULL;
8505 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8507 if (info_1 == NULL) {
8511 for (i=0; i<count && found==False; i++) {
8512 if ((*queue)[i].job==(int)jobid)
8518 /* NT treats not found as bad param... yet another bad choice */
8519 return WERR_INVALID_PARAM;
8522 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8524 *needed += spoolss_size_job_info_1(info_1);
8526 if (!alloc_buffer_size(buffer, *needed)) {
8528 return WERR_INSUFFICIENT_BUFFER;
8531 smb_io_job_info_1("", buffer, info_1, 0);
8535 if (*needed > offered)
8536 return WERR_INSUFFICIENT_BUFFER;
8541 /****************************************************************************
8542 ****************************************************************************/
8544 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8549 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8551 DEVICEMODE *devmode = NULL;
8552 NT_DEVICEMODE *nt_devmode = NULL;
8554 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8556 ZERO_STRUCTP(info_2);
8558 if (info_2 == NULL) {
8563 for ( i=0; i<count && found==False; i++ )
8565 if ((*queue)[i].job == (int)jobid)
8571 /* NT treats not found as bad param... yet another bad
8573 ret = WERR_INVALID_PARAM;
8577 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8578 if (!W_ERROR_IS_OK(ret))
8582 * if the print job does not have a DEVMODE associated with it,
8583 * just use the one for the printer. A NULL devicemode is not
8584 * a failure condition
8587 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8588 devmode = construct_dev_mode(snum);
8590 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8591 ZERO_STRUCTP( devmode );
8592 convert_nt_devicemode( devmode, nt_devmode );
8596 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8598 *needed += spoolss_size_job_info_2(info_2);
8600 if (!alloc_buffer_size(buffer, *needed)) {
8601 ret = WERR_INSUFFICIENT_BUFFER;
8605 smb_io_job_info_2("", buffer, info_2, 0);
8607 if (*needed > offered) {
8608 ret = WERR_INSUFFICIENT_BUFFER;
8615 /* Cleanup allocated memory */
8617 free_job_info_2(info_2); /* Also frees devmode */
8619 free_a_printer(&ntprinter, 2);
8624 /****************************************************************************
8625 ****************************************************************************/
8627 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8629 POLICY_HND *handle = &q_u->handle;
8630 uint32 jobid = q_u->jobid;
8631 uint32 level = q_u->level;
8632 NEW_BUFFER *buffer = NULL;
8633 uint32 offered = q_u->offered;
8634 uint32 *needed = &r_u->needed;
8635 WERROR wstatus = WERR_OK;
8639 print_queue_struct *queue = NULL;
8640 print_status_struct prt_status;
8642 /* that's an [in out] buffer */
8643 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8644 buffer = r_u->buffer;
8646 DEBUG(5,("spoolss_getjob\n"));
8650 if (!get_printer_snum(p, handle, &snum))
8653 count = print_queue_status(snum, &queue, &prt_status);
8655 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8656 count, prt_status.status, prt_status.message));
8660 wstatus = getjob_level_1(&queue, count, snum, jobid,
8661 buffer, offered, needed);
8664 wstatus = getjob_level_2(&queue, count, snum, jobid,
8665 buffer, offered, needed);
8668 wstatus = WERR_UNKNOWN_LEVEL;
8676 /********************************************************************
8677 spoolss_getprinterdataex
8679 From MSDN documentation of GetPrinterDataEx: pass request
8680 to GetPrinterData if key is "PrinterDriverData".
8681 ********************************************************************/
8683 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8685 POLICY_HND *handle = &q_u->handle;
8686 uint32 in_size = q_u->size;
8687 uint32 *type = &r_u->type;
8688 uint32 *out_size = &r_u->size;
8689 uint8 **data = &r_u->data;
8690 uint32 *needed = &r_u->needed;
8691 fstring keyname, valuename;
8693 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8695 NT_PRINTER_INFO_LEVEL *printer = NULL;
8697 WERROR status = WERR_OK;
8699 DEBUG(4,("_spoolss_getprinterdataex\n"));
8701 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8702 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8704 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8705 keyname, valuename));
8707 /* in case of problem, return some default values */
8711 *out_size = in_size;
8714 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8715 status = WERR_BADFID;
8719 /* Is the handle to a printer or to the server? */
8721 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8722 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8723 status = WERR_INVALID_PARAM;
8727 if ( !get_printer_snum(p,handle, &snum) )
8730 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8731 if ( !W_ERROR_IS_OK(status) )
8734 /* check to see if the keyname is valid */
8735 if ( !strlen(keyname) ) {
8736 status = WERR_INVALID_PARAM;
8740 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8741 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8742 free_a_printer( &printer, 2 );
8743 status = WERR_BADFILE;
8747 /* When given a new keyname, we should just create it */
8749 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8751 if (*needed > *out_size)
8752 status = WERR_MORE_DATA;
8755 if ( !W_ERROR_IS_OK(status) )
8757 DEBUG(5, ("error: allocating %d\n", *out_size));
8759 /* reply this param doesn't exist */
8763 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8764 status = WERR_NOMEM;
8774 free_a_printer( &printer, 2 );
8779 /********************************************************************
8780 * spoolss_setprinterdataex
8781 ********************************************************************/
8783 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8785 POLICY_HND *handle = &q_u->handle;
8786 uint32 type = q_u->type;
8787 uint8 *data = q_u->data;
8788 uint32 real_len = q_u->real_len;
8790 NT_PRINTER_INFO_LEVEL *printer = NULL;
8792 WERROR status = WERR_OK;
8793 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8798 DEBUG(4,("_spoolss_setprinterdataex\n"));
8800 /* From MSDN documentation of SetPrinterDataEx: pass request to
8801 SetPrinterData if key is "PrinterDriverData" */
8804 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8808 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8809 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8810 return WERR_INVALID_PARAM;
8813 if ( !get_printer_snum(p,handle, &snum) )
8817 * Access check : NT returns "access denied" if you make a
8818 * SetPrinterData call without the necessary privildge.
8819 * we were originally returning OK if nothing changed
8820 * which made Win2k issue **a lot** of SetPrinterData
8821 * when connecting to a printer --jerry
8824 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8826 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8827 return WERR_ACCESS_DENIED;
8830 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8831 if (!W_ERROR_IS_OK(status))
8834 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8835 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8837 /* check for OID in valuename */
8839 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8845 /* save the registry data */
8847 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8849 if ( W_ERROR_IS_OK(status) )
8851 /* save the OID if one was specified */
8853 fstrcat( keyname, "\\" );
8854 fstrcat( keyname, SPOOL_OID_KEY );
8857 * I'm not checking the status here on purpose. Don't know
8858 * if this is right, but I'm returning the status from the
8859 * previous set_printer_dataex() call. I have no idea if
8860 * this is right. --jerry
8863 set_printer_dataex( printer, keyname, valuename,
8864 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8867 status = mod_a_printer(printer, 2);
8870 free_a_printer(&printer, 2);
8876 /********************************************************************
8877 * spoolss_deleteprinterdataex
8878 ********************************************************************/
8880 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8882 POLICY_HND *handle = &q_u->handle;
8883 UNISTR2 *value = &q_u->valuename;
8884 UNISTR2 *key = &q_u->keyname;
8886 NT_PRINTER_INFO_LEVEL *printer = NULL;
8888 WERROR status = WERR_OK;
8889 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8890 pstring valuename, keyname;
8892 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8895 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8899 if (!get_printer_snum(p, handle, &snum))
8902 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8903 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8904 return WERR_ACCESS_DENIED;
8907 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8908 if (!W_ERROR_IS_OK(status))
8911 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8912 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8914 status = delete_printer_dataex( printer, keyname, valuename );
8916 if ( W_ERROR_IS_OK(status) )
8917 mod_a_printer( printer, 2 );
8919 free_a_printer(&printer, 2);
8924 /********************************************************************
8925 * spoolss_enumprinterkey
8926 ********************************************************************/
8929 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8932 fstring *keynames = NULL;
8933 uint16 *enumkeys = NULL;
8936 POLICY_HND *handle = &q_u->handle;
8937 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8938 NT_PRINTER_DATA *data;
8939 NT_PRINTER_INFO_LEVEL *printer = NULL;
8941 WERROR status = WERR_BADFILE;
8944 DEBUG(4,("_spoolss_enumprinterkey\n"));
8947 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8951 if ( !get_printer_snum(p,handle, &snum) )
8954 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8955 if (!W_ERROR_IS_OK(status))
8958 /* get the list of subkey names */
8960 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8961 data = &printer->info_2->data;
8963 num_keys = get_printer_subkeys( data, key, &keynames );
8965 if ( num_keys == -1 ) {
8966 status = WERR_BADFILE;
8970 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8972 r_u->needed = printerkey_len*2;
8974 if ( q_u->size < r_u->needed ) {
8975 status = WERR_MORE_DATA;
8979 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8980 status = WERR_NOMEM;
8986 if ( q_u->size < r_u->needed )
8987 status = WERR_MORE_DATA;
8990 free_a_printer( &printer, 2 );
8991 SAFE_FREE( keynames );
8996 /********************************************************************
8997 * spoolss_deleteprinterkey
8998 ********************************************************************/
9000 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9002 POLICY_HND *handle = &q_u->handle;
9003 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9005 NT_PRINTER_INFO_LEVEL *printer = NULL;
9009 DEBUG(5,("spoolss_deleteprinterkey\n"));
9012 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9016 /* if keyname == NULL, return error */
9018 if ( !q_u->keyname.buffer )
9019 return WERR_INVALID_PARAM;
9021 if (!get_printer_snum(p, handle, &snum))
9024 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9025 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9026 return WERR_ACCESS_DENIED;
9029 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9030 if (!W_ERROR_IS_OK(status))
9033 /* delete the key and all subneys */
9035 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9037 status = delete_all_printer_data( printer->info_2, key );
9039 if ( W_ERROR_IS_OK(status) )
9040 status = mod_a_printer(printer, 2);
9042 free_a_printer( &printer, 2 );
9048 /********************************************************************
9049 * spoolss_enumprinterdataex
9050 ********************************************************************/
9052 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9054 POLICY_HND *handle = &q_u->handle;
9055 uint32 in_size = q_u->size;
9058 NT_PRINTER_INFO_LEVEL *printer = NULL;
9059 PRINTER_ENUM_VALUES *enum_values = NULL;
9060 NT_PRINTER_DATA *p_data;
9062 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9067 REGISTRY_VALUE *val;
9072 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9075 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9080 * first check for a keyname of NULL or "". Win2k seems to send
9081 * this a lot and we should send back WERR_INVALID_PARAM
9082 * no need to spend time looking up the printer in this case.
9086 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9087 if ( !strlen(key) ) {
9088 result = WERR_INVALID_PARAM;
9092 /* get the printer off of disk */
9094 if (!get_printer_snum(p,handle, &snum))
9097 ZERO_STRUCT(printer);
9098 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9099 if (!W_ERROR_IS_OK(result))
9102 /* now look for a match on the key name */
9104 p_data = &printer->info_2->data;
9106 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9107 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9109 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9110 result = WERR_INVALID_PARAM;
9117 /* allocate the memory for the array of pointers -- if necessary */
9119 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9122 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9124 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9125 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9126 result = WERR_NOMEM;
9130 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9134 * loop through all params and build the array to pass
9135 * back to the client
9138 for ( i=0; i<num_entries; i++ )
9140 /* lookup the registry value */
9142 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9143 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9147 value_name = regval_name( val );
9148 init_unistr( &enum_values[i].valuename, value_name );
9149 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9150 enum_values[i].type = regval_type( val );
9152 data_len = regval_size( val );
9154 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9156 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9158 result = WERR_NOMEM;
9162 enum_values[i].data_len = data_len;
9164 /* keep track of the size of the array in bytes */
9166 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9169 /* housekeeping information in the reply */
9171 r_u->needed = needed;
9172 r_u->returned = num_entries;
9174 if (needed > in_size) {
9175 result = WERR_MORE_DATA;
9179 /* copy data into the reply */
9181 r_u->ctr.size = r_u->needed;
9182 r_u->ctr.size_of_array = r_u->returned;
9183 r_u->ctr.values = enum_values;
9189 free_a_printer(&printer, 2);
9194 /****************************************************************************
9195 ****************************************************************************/
9197 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9199 init_unistr(&info->name, name);
9202 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9203 UNISTR2 *environment,
9210 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9212 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9214 if (!get_short_archi(long_archi))
9215 return WERR_INVALID_ENVIRONMENT;
9217 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9220 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9222 fill_printprocessordirectory_1(info, path);
9224 *needed += spoolss_size_printprocessordirectory_info_1(info);
9226 if (!alloc_buffer_size(buffer, *needed)) {
9228 return WERR_INSUFFICIENT_BUFFER;
9231 smb_io_printprocessordirectory_1("", buffer, info, 0);
9235 if (*needed > offered)
9236 return WERR_INSUFFICIENT_BUFFER;
9241 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9243 uint32 level = q_u->level;
9244 NEW_BUFFER *buffer = NULL;
9245 uint32 offered = q_u->offered;
9246 uint32 *needed = &r_u->needed;
9249 /* that's an [in out] buffer */
9250 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9251 buffer = r_u->buffer;
9253 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9259 result = getprintprocessordirectory_level_1
9260 (&q_u->name, &q_u->environment, buffer, offered, needed);
9263 result = WERR_UNKNOWN_LEVEL;
9271 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9272 SPOOL_R_REPLYOPENPRINTER *r_u)
9274 DEBUG(5,("_spoolss_replyopenprinter\n"));
9276 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9281 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9282 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9284 DEBUG(5,("_spoolss_replycloseprinter\n"));