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-2003,
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 {
74 static ubi_dlList 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_PRINTING );
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
315 && StrCaseCmp(p->dev.handlename, printername)==0)
317 DEBUG(10,("invalidating printer_info cache for handl:\n"));
318 free_a_printer( &p->printer_info, 2 );
319 p->printer_info = NULL;
325 /****************************************************************************
326 Close printer index by handle.
327 ****************************************************************************/
329 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
331 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
334 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
338 close_policy_hnd(p, hnd);
343 /****************************************************************************
344 Delete a printer given a handle.
345 ****************************************************************************/
347 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
349 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
352 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
357 * It turns out that Windows allows delete printer on a handle
358 * opened by an admin user, then used on a pipe handle created
359 * by an anonymous user..... but they're working on security.... riiight !
363 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
364 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
365 return WERR_ACCESS_DENIED;
369 /* Check calling user has permission to delete printer. Note that
370 since we set the snum parameter to -1 only administrators can
371 delete the printer. This stops people with the Full Control
372 permission from deleting the printer. */
374 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
375 DEBUG(3, ("printer delete denied by security descriptor\n"));
376 return WERR_ACCESS_DENIED;
380 if (del_a_printer(Printer->dev.handlename) != 0) {
381 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
385 if (*lp_deleteprinter_cmd()) {
387 char *cmd = lp_deleteprinter_cmd();
391 /* Printer->dev.handlename equals portname equals sharename */
392 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
393 Printer->dev.handlename);
395 DEBUG(10,("Running [%s]\n", command));
396 ret = smbrun(command, NULL);
398 return WERR_BADFID; /* What to return here? */
400 DEBUGADD(10,("returned [%d]\n", ret));
402 /* Send SIGHUP to process group... is there a better way? */
405 /* go ahead and re-read the services immediately */
406 reload_services( False );
408 if ( lp_servicenumber( Printer->dev.handlename ) < 0 )
409 return WERR_ACCESS_DENIED;
415 /****************************************************************************
416 Return the snum of a printer corresponding to an handle.
417 ****************************************************************************/
419 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
421 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
424 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
428 switch (Printer->printer_type) {
429 case PRINTER_HANDLE_IS_PRINTER:
430 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
431 *number = print_queue_snum(Printer->dev.handlename);
432 return (*number != -1);
433 case PRINTER_HANDLE_IS_PRINTSERVER:
440 /****************************************************************************
441 Set printer handle type.
442 Check if it's \\server or \\server\printer
443 ****************************************************************************/
445 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
447 DEBUG(3,("Setting printer type=%s\n", handlename));
449 if ( strlen(handlename) < 3 ) {
450 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
454 /* it's a print server */
455 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
456 DEBUGADD(4,("Printer is a print server\n"));
457 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
461 DEBUGADD(4,("Printer is a printer\n"));
462 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
468 /****************************************************************************
469 Set printer handle name.
470 ****************************************************************************/
472 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
475 int n_services=lp_numservices();
480 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
482 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
483 ZERO_STRUCT(Printer->dev.printerservername);
484 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
488 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
491 if (*handlename=='\\') {
492 aprinter=strchr_m(handlename+2, '\\');
499 DEBUGADD(5,("searching for [%s] (len=%lu)\n", aprinter, (unsigned long)strlen(aprinter)));
502 * The original code allowed smbd to store a printer name that
503 * was different from the share name. This is not possible
504 * anymore, so I've simplified this loop greatly. Here
505 * we are just verifying that the printer name is a valid
506 * printer service defined in smb.conf
507 * --jerry [Fri Feb 15 11:17:46 CST 2002]
510 for (snum=0; snum<n_services; snum++) {
512 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
515 fstrcpy(sname, lp_servicename(snum));
517 DEBUGADD(5,("share:%s\n",sname));
519 if (! StrCaseCmp(sname, aprinter)) {
528 DEBUGADD(4,("Printer not found\n"));
532 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
534 ZERO_STRUCT(Printer->dev.handlename);
535 fstrcpy(Printer->dev.handlename, sname);
540 /****************************************************************************
541 Find first available printer slot. creates a printer handle for you.
542 ****************************************************************************/
544 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
546 Printer_entry *new_printer;
548 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
550 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
553 ZERO_STRUCTP(new_printer);
555 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
556 SAFE_FREE(new_printer);
560 /* Add to the internal list. */
561 DLIST_ADD(printers_list, new_printer);
563 new_printer->notify.option=NULL;
565 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
566 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
567 close_printer_handle(p, hnd);
571 if (!set_printer_hnd_printertype(new_printer, name)) {
572 close_printer_handle(p, hnd);
576 if (!set_printer_hnd_name(new_printer, name)) {
577 close_printer_handle(p, hnd);
581 new_printer->access_granted = access_granted;
583 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
588 /****************************************************************************
589 Allocate more memory for a BUFFER.
590 ****************************************************************************/
592 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
600 /* damn, I'm doing the reverse operation of prs_grow() :) */
601 if (buffer_size < prs_data_size(ps))
604 extra_space = buffer_size - prs_data_size(ps);
607 * save the offset and move to the end of the buffer
608 * prs_grow() checks the extra_space against the offset
610 old_offset=prs_offset(ps);
611 prs_set_offset(ps, prs_data_size(ps));
613 if (!prs_grow(ps, extra_space))
616 prs_set_offset(ps, old_offset);
618 buffer->string_at_end=prs_data_size(ps);
623 /***************************************************************************
624 check to see if the client motify handle is monitoring the notification
625 given by (notify_type, notify_field).
626 **************************************************************************/
628 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
634 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
637 SPOOL_NOTIFY_OPTION *option = p->notify.option;
641 * Flags should always be zero when the change notify
642 * is registered by the client's spooler. A user Win32 app
643 * might use the flags though instead of the NOTIFY_OPTION_INFO
648 return is_monitoring_event_flags(
649 p->notify.flags, notify_type, notify_field);
651 for (i = 0; i < option->count; i++) {
653 /* Check match for notify_type */
655 if (option->ctr.type[i].type != notify_type)
658 /* Check match for field */
660 for (j = 0; j < option->ctr.type[i].count; j++) {
661 if (option->ctr.type[i].fields[j] == notify_field) {
667 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
668 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
669 p->dev.handlename : p->dev.printerservername,
670 notify_type, notify_field));
675 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
677 static void notify_one_value(struct spoolss_notify_msg *msg,
678 SPOOL_NOTIFY_INFO_DATA *data,
681 data->notify_data.value[0] = msg->notify.value[0];
682 data->notify_data.value[1] = 0;
685 static void notify_string(struct spoolss_notify_msg *msg,
686 SPOOL_NOTIFY_INFO_DATA *data,
691 /* The length of the message includes the trailing \0 */
693 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
695 data->notify_data.data.length = msg->len * 2;
696 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
698 if (!data->notify_data.data.string) {
699 data->notify_data.data.length = 0;
703 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
706 static void notify_system_time(struct spoolss_notify_msg *msg,
707 SPOOL_NOTIFY_INFO_DATA *data,
713 if (msg->len != sizeof(time_t)) {
714 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
719 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
720 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
724 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
725 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
729 if (!spoolss_io_system_time("", &ps, 0, &systime))
732 data->notify_data.data.length = prs_offset(&ps);
733 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
735 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
740 struct notify2_message_table {
742 void (*fn)(struct spoolss_notify_msg *msg,
743 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
746 static struct notify2_message_table printer_notify_table[] = {
747 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
748 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
749 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
750 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
751 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
752 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
753 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
754 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
755 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
756 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
757 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
758 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
759 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
760 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
761 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
762 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
763 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
764 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
765 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
768 static struct notify2_message_table job_notify_table[] = {
769 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
770 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
771 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
772 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
773 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
774 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
775 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
776 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
777 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
778 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
779 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
780 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
781 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
782 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
783 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
784 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
785 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
786 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
787 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
788 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
789 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
790 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
791 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
792 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
796 /***********************************************************************
797 Allocate talloc context for container object
798 **********************************************************************/
800 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
805 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
810 /***********************************************************************
811 release all allocated memory and zero out structure
812 **********************************************************************/
814 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
820 talloc_destroy(ctr->ctx);
827 /***********************************************************************
828 **********************************************************************/
830 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
838 /***********************************************************************
839 **********************************************************************/
841 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
843 if ( !ctr || !ctr->msg_groups )
846 if ( idx >= ctr->num_groups )
849 return &ctr->msg_groups[idx];
853 /***********************************************************************
854 How many groups of change messages do we have ?
855 **********************************************************************/
857 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
862 return ctr->num_groups;
865 /***********************************************************************
866 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
867 **********************************************************************/
869 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
871 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
872 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
873 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
879 /* loop over all groups looking for a matching printer name */
881 for ( i=0; i<ctr->num_groups; i++ ) {
882 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
886 /* add a new group? */
888 if ( i == ctr->num_groups ) {
891 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
892 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
895 ctr->msg_groups = groups;
897 /* clear the new entry and set the printer name */
899 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
900 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
903 /* add the change messages; 'i' is the correct index now regardless */
905 msg_grp = &ctr->msg_groups[i];
909 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
910 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
913 msg_grp->msgs = msg_list;
915 new_slot = msg_grp->num_msgs-1;
916 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
918 /* need to allocate own copy of data */
921 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
923 return ctr->num_groups;
926 /***********************************************************************
927 Send a change notication message on all handles which have a call
929 **********************************************************************/
931 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
934 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
935 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
936 SPOOLSS_NOTIFY_MSG *messages;
937 int sending_msg_count;
940 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
944 messages = msg_group->msgs;
947 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
951 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
953 /* loop over all printers */
955 for (p = printers_list; p; p = p->next) {
956 SPOOL_NOTIFY_INFO_DATA *data;
961 /* Is there notification on this handle? */
963 if ( !p->notify.client_connected )
966 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
968 /* For this printer? Print servers always receive
971 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
972 ( !strequal(msg_group->printername, p->dev.handlename) ) )
975 DEBUG(10,("Our printer\n"));
977 /* allocate the max entries possible */
979 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
982 /* build the array of change notifications */
984 sending_msg_count = 0;
986 for ( i=0; i<msg_group->num_msgs; i++ ) {
987 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
989 /* Are we monitoring this event? */
991 if (!is_monitoring_event(p, msg->type, msg->field))
997 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
998 msg->type, msg->field, p->dev.handlename));
1001 * if the is a printer notification handle and not a job notification
1002 * type, then set the id to 0. Other wise just use what was specified
1005 * When registering change notification on a print server handle
1006 * we always need to send back the id (snum) matching the printer
1007 * for which the change took place. For change notify registered
1008 * on a printer handle, this does not matter and the id should be 0.
1013 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1019 /* Convert unix jobid to smb jobid */
1021 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1022 id = sysjob_to_jobid(msg->id);
1025 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1030 construct_info_data( &data[data_len], msg->type, msg->field, id );
1033 case PRINTER_NOTIFY_TYPE:
1034 if ( printer_notify_table[msg->field].fn )
1035 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1038 case JOB_NOTIFY_TYPE:
1039 if ( job_notify_table[msg->field].fn )
1040 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1044 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1051 if ( sending_msg_count ) {
1052 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1053 data_len, data, p->notify.change, 0 );
1058 DEBUG(8,("send_notify2_changes: Exit...\n"));
1062 /***********************************************************************
1063 **********************************************************************/
1065 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1068 uint32 tv_sec, tv_usec;
1071 /* Unpack message */
1073 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1076 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1078 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1081 tdb_unpack((char *)buf + offset, len - offset, "dd",
1082 &msg->notify.value[0], &msg->notify.value[1]);
1084 tdb_unpack((char *)buf + offset, len - offset, "B",
1085 &msg->len, &msg->notify.data);
1087 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1088 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1090 tv->tv_sec = tv_sec;
1091 tv->tv_usec = tv_usec;
1094 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1095 msg->notify.value[1]));
1097 dump_data(3, msg->notify.data, msg->len);
1102 /* ENUMJOB last timestamp list. */
1104 struct ejts_list *next, *prev;
1109 static struct ejts_list *ejts_head;
1111 static struct ejts_list *find_enumjobs_timestamp(const char *printer_name)
1113 struct ejts_list *ejtsl;
1115 for( ejtsl = ejts_head; ejtsl; ejtsl = ejtsl->next)
1116 if (strequal(ejtsl->printer_name, printer_name))
1121 static void set_enumjobs_timestamp(int snum)
1123 const char *printer_name = lp_const_servicename(snum);
1124 struct ejts_list *ejtsl = find_enumjobs_timestamp(printer_name);
1127 ejtsl = (struct ejts_list *)malloc(sizeof(struct ejts_list));
1130 ejtsl->printer_name = strdup(printer_name);
1131 if (!ejtsl->printer_name) {
1135 DLIST_ADD(ejts_head, ejtsl);
1138 gettimeofday(&ejtsl->tv, NULL);
1141 static int timeval_diff(struct timeval *tv1, struct timeval *tv2)
1143 if (tv1->tv_sec > tv2->tv_sec)
1145 if (tv1->tv_sec < tv2->tv_sec)
1147 if (tv1->tv_usec > tv2->tv_usec)
1149 if (tv1->tv_usec < tv2->tv_usec)
1154 /********************************************************************
1155 Receive a notify2 message list
1156 ********************************************************************/
1158 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1160 size_t msg_count, i;
1161 char *buf = (char *)msg;
1164 SPOOLSS_NOTIFY_MSG notify;
1165 SPOOLSS_NOTIFY_MSG_CTR messages;
1169 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1173 msg_count = IVAL(buf, 0);
1176 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1178 if (msg_count == 0) {
1179 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1183 /* initialize the container */
1185 ZERO_STRUCT( messages );
1186 notify_msg_ctr_init( &messages );
1189 * build message groups for each printer identified
1190 * in a change_notify msg. Remember that a PCN message
1191 * includes the handle returned for the srv_spoolss_replyopenprinter()
1192 * call. Therefore messages are grouped according to printer handle.
1195 for ( i=0; i<msg_count; i++ ) {
1196 struct timeval msg_tv;
1198 if (msg_ptr + 4 - buf > len) {
1199 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1203 msg_len = IVAL(msg_ptr,0);
1206 if (msg_ptr + msg_len - buf > len) {
1207 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1211 /* unpack messages */
1213 ZERO_STRUCT( notify );
1214 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1217 /* See if it is still relevent. */
1218 if (notify.type == JOB_NOTIFY_TYPE) {
1219 BOOL status_is_deleting = False;
1221 if (notify.field == JOB_NOTIFY_STATUS && (notify.notify.value[0] & (JOB_STATUS_DELETING|JOB_STATUS_DELETED)))
1222 status_is_deleting = True;
1224 if (!status_is_deleting) {
1225 struct ejts_list *ejtsl = find_enumjobs_timestamp(notify.printer);
1227 if (ejtsl && (timeval_diff(&ejtsl->tv, &msg_tv) > 0)) {
1229 DEBUG(10, ("receive_notify2_message_list: enumjobs ts = %u, %u, msg ts = %u, %u discarding\n",
1230 (unsigned int)ejtsl->tv.tv_sec, (unsigned int)ejtsl->tv.tv_usec,
1231 (unsigned int)msg_tv.tv_sec, (unsigned int)msg_tv.tv_usec ));
1233 /* Message no longer relevent. Ignore it. */
1234 if ( notify.len != 0 )
1235 SAFE_FREE( notify.notify.data );
1240 /* add to correct list in container */
1242 notify_msg_ctr_addmsg( &messages, ¬ify );
1244 /* free memory that might have been allocated by notify2_unpack_msg() */
1246 if ( notify.len != 0 )
1247 SAFE_FREE( notify.notify.data );
1250 /* process each group of messages */
1252 num_groups = notify_msg_ctr_numgroups( &messages );
1253 for ( i=0; i<num_groups; i++ )
1254 send_notify2_changes( &messages, i );
1259 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1261 notify_msg_ctr_destroy( &messages );
1266 /********************************************************************
1267 Send a message to ourself about new driver being installed
1268 so we can upgrade the information for each printer bound to this
1270 ********************************************************************/
1272 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1274 int len = strlen(drivername);
1279 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1282 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1287 /**********************************************************************
1288 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1289 over all printers, upgrading ones as necessary
1290 **********************************************************************/
1292 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1296 int n_services = lp_numservices();
1298 len = MIN(len,sizeof(drivername)-1);
1299 strncpy(drivername, buf, len);
1301 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1303 /* Iterate the printer list */
1305 for (snum=0; snum<n_services; snum++)
1307 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1310 NT_PRINTER_INFO_LEVEL *printer = NULL;
1312 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1313 if (!W_ERROR_IS_OK(result))
1316 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1318 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1320 /* all we care about currently is the change_id */
1322 result = mod_a_printer(*printer, 2);
1323 if (!W_ERROR_IS_OK(result)) {
1324 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1325 dos_errstr(result)));
1329 free_a_printer(&printer, 2);
1336 /********************************************************************
1337 Update the cache for all printq's with a registered client
1339 ********************************************************************/
1341 void update_monitored_printq_cache( void )
1343 Printer_entry *printer = printers_list;
1346 /* loop through all printers and update the cache where
1347 client_connected == True */
1350 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1351 && printer->notify.client_connected )
1353 snum = print_queue_snum(printer->dev.handlename);
1354 print_queue_status( snum, NULL, NULL );
1357 printer = printer->next;
1362 /********************************************************************
1363 Send a message to ourself about new driver being installed
1364 so we can upgrade the information for each printer bound to this
1366 ********************************************************************/
1368 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1370 int len = strlen(drivername);
1375 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1378 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1383 /**********************************************************************
1384 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1385 over all printers, resetting printer data as neessary
1386 **********************************************************************/
1388 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1392 int n_services = lp_numservices();
1394 len = MIN( len, sizeof(drivername)-1 );
1395 strncpy( drivername, buf, len );
1397 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1399 /* Iterate the printer list */
1401 for ( snum=0; snum<n_services; snum++ )
1403 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1406 NT_PRINTER_INFO_LEVEL *printer = NULL;
1408 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1409 if ( !W_ERROR_IS_OK(result) )
1413 * if the printer is bound to the driver,
1414 * then reset to the new driver initdata
1417 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1419 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1421 if ( !set_driver_init(printer, 2) ) {
1422 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1423 printer->info_2->printername, printer->info_2->drivername));
1426 result = mod_a_printer( *printer, 2 );
1427 if ( !W_ERROR_IS_OK(result) ) {
1428 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1429 get_dos_error_msg(result)));
1433 free_a_printer( &printer, 2 );
1442 /********************************************************************
1443 Copy routines used by convert_to_openprinterex()
1444 *******************************************************************/
1446 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1454 DEBUG (8,("dup_devmode\n"));
1456 /* bulk copy first */
1458 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1462 /* dup the pointer members separately */
1464 len = unistrlen(devmode->devicename.buffer);
1466 d->devicename.buffer = talloc(ctx, len*2);
1467 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1472 len = unistrlen(devmode->formname.buffer);
1474 d->devicename.buffer = talloc(ctx, len*2);
1475 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1479 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1484 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1486 if (!new_ctr || !ctr)
1489 DEBUG(8,("copy_devmode_ctr\n"));
1491 new_ctr->size = ctr->size;
1492 new_ctr->devmode_ptr = ctr->devmode_ptr;
1494 if(ctr->devmode_ptr)
1495 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1498 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1500 if (!new_def || !def)
1503 DEBUG(8,("copy_printer_defaults\n"));
1505 new_def->datatype_ptr = def->datatype_ptr;
1507 if (def->datatype_ptr)
1508 copy_unistr2(&new_def->datatype, &def->datatype);
1510 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1512 new_def->access_required = def->access_required;
1515 /********************************************************************
1516 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1517 * SPOOL_Q_OPEN_PRINTER_EX structure
1518 ********************************************************************/
1520 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1522 if (!q_u_ex || !q_u)
1525 DEBUG(8,("convert_to_openprinterex\n"));
1527 q_u_ex->printername_ptr = q_u->printername_ptr;
1529 if (q_u->printername_ptr)
1530 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1532 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1535 /********************************************************************
1536 * spoolss_open_printer
1538 * called from the spoolss dispatcher
1539 ********************************************************************/
1541 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1543 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1544 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1549 ZERO_STRUCT(q_u_ex);
1550 ZERO_STRUCT(r_u_ex);
1552 /* convert the OpenPrinter() call to OpenPrinterEx() */
1554 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1556 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1558 /* convert back to OpenPrinter() */
1560 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1565 /********************************************************************
1566 * spoolss_open_printer
1568 * If the openprinterex rpc call contains a devmode,
1569 * it's a per-user one. This per-user devmode is derivated
1570 * from the global devmode. Openprinterex() contains a per-user
1571 * devmode for when you do EMF printing and spooling.
1572 * In the EMF case, the NT workstation is only doing half the job
1573 * of rendering the page. The other half is done by running the printer
1574 * driver on the server.
1575 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1576 * The EMF file only contains what is to be printed on the page.
1577 * So in order for the server to know how to print, the NT client sends
1578 * a devicemode attached to the openprinterex call.
1579 * But this devicemode is short lived, it's only valid for the current print job.
1581 * If Samba would have supported EMF spooling, this devicemode would
1582 * have been attached to the handle, to sent it to the driver to correctly
1583 * rasterize the EMF file.
1585 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1586 * we just act as a pass-thru between windows and the printer.
1588 * In order to know that Samba supports only RAW spooling, NT has to call
1589 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1590 * and until NT sends a RAW job, we refuse it.
1592 * But to call getprinter() or startdoc(), you first need a valid handle,
1593 * and to get an handle you have to call openprintex(). Hence why you have
1594 * a devicemode in the openprinterex() call.
1597 * Differences between NT4 and NT 2000.
1600 * On NT4, you only have a global devicemode. This global devicemode can be changed
1601 * by the administrator (or by a user with enough privs). Everytime a user
1602 * wants to print, the devicemode is resetted to the default. In Word, everytime
1603 * you print, the printer's characteristics are always reset to the global devicemode.
1607 * In W2K, there is the notion of per-user devicemode. The first time you use
1608 * a printer, a per-user devicemode is build from the global devicemode.
1609 * If you change your per-user devicemode, it is saved in the registry, under the
1610 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1611 * printer preferences available.
1613 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1614 * on the General Tab of the printer properties windows.
1616 * To change the global devicemode: it's the "Printing Defaults..." button
1617 * on the Advanced Tab of the printer properties window.
1620 ********************************************************************/
1622 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1624 UNISTR2 *printername = NULL;
1625 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1626 POLICY_HND *handle = &r_u->handle;
1630 struct current_user user;
1631 Printer_entry *Printer=NULL;
1633 if (q_u->printername_ptr != 0)
1634 printername = &q_u->printername;
1636 if (printername == NULL)
1637 return WERR_INVALID_PRINTER_NAME;
1639 /* some sanity check because you can open a printer or a print server */
1640 /* aka: \\server\printer or \\server */
1641 unistr2_to_ascii(name, printername, sizeof(name)-1);
1643 DEBUGADD(3,("checking name: %s\n",name));
1645 if (!open_printer_hnd(p, handle, name, 0))
1646 return WERR_INVALID_PRINTER_NAME;
1648 Printer=find_printer_index_by_hnd(p, handle);
1650 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1651 Can't find printer handle we created for printer %s\n", name ));
1652 close_printer_handle(p,handle);
1653 return WERR_INVALID_PRINTER_NAME;
1656 get_current_user(&user, p);
1659 * First case: the user is opening the print server:
1661 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1662 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1664 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1665 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1666 * or if the user is listed in the smb.conf printer admin parameter.
1668 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1669 * client view printer folder, but does not show the MSAPW.
1671 * Note: this test needs code to check access rights here too. Jeremy
1672 * could you look at this?
1674 * Second case: the user is opening a printer:
1675 * NT doesn't let us connect to a printer if the connecting user
1676 * doesn't have print permission.
1679 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1681 /* Printserver handles use global struct... */
1685 /* Map standard access rights to object specific access rights */
1687 se_map_standard(&printer_default->access_required,
1688 &printserver_std_mapping);
1690 /* Deny any object specific bits that don't apply to print
1691 servers (i.e printer and job specific bits) */
1693 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1695 if (printer_default->access_required &
1696 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1697 DEBUG(3, ("access DENIED for non-printserver bits"));
1698 close_printer_handle(p, handle);
1699 return WERR_ACCESS_DENIED;
1702 /* Allow admin access */
1704 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1706 if (!lp_ms_add_printer_wizard()) {
1707 close_printer_handle(p, handle);
1708 return WERR_ACCESS_DENIED;
1711 /* if the user is not root and not a printer admin, then fail */
1714 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1716 close_printer_handle(p, handle);
1717 return WERR_ACCESS_DENIED;
1720 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1724 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1727 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1728 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1730 /* We fall through to return WERR_OK */
1735 /* NT doesn't let us connect to a printer if the connecting user
1736 doesn't have print permission. */
1738 if (!get_printer_snum(p, handle, &snum)) {
1739 close_printer_handle(p, handle);
1743 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1745 /* map an empty access mask to the minimum access mask */
1746 if (printer_default->access_required == 0x0)
1747 printer_default->access_required = PRINTER_ACCESS_USE;
1750 * If we are not serving the printer driver for this printer,
1751 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1752 * will keep NT clients happy --jerry
1755 if (lp_use_client_driver(snum)
1756 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1758 printer_default->access_required = PRINTER_ACCESS_USE;
1761 /* check smb.conf parameters and the the sec_desc */
1763 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1764 DEBUG(3, ("access DENIED for printer open\n"));
1765 close_printer_handle(p, handle);
1766 return WERR_ACCESS_DENIED;
1769 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1770 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1771 close_printer_handle(p, handle);
1772 return WERR_ACCESS_DENIED;
1775 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1776 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1778 printer_default->access_required = PRINTER_ACCESS_USE;
1780 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1781 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1785 Printer->access_granted = printer_default->access_required;
1788 * If the client sent a devmode in the OpenPrinter() call, then
1789 * save it here in case we get a job submission on this handle
1792 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1793 && q_u->printer_default.devmode_cont.devmode_ptr )
1795 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1796 &Printer->nt_devmode );
1799 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1800 optimization in Windows 2000 clients --jerry */
1802 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1803 && (RA_WIN2K == get_remote_arch()) )
1805 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1812 /****************************************************************************
1813 ****************************************************************************/
1815 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1816 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1822 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1831 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1832 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1838 printer->info_3=NULL;
1839 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1843 printer->info_6=NULL;
1844 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1854 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1855 NT_DEVICEMODE **pp_nt_devmode)
1857 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1860 * Ensure nt_devmode is a valid pointer
1861 * as we will be overwriting it.
1864 if (nt_devmode == NULL) {
1865 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1866 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1870 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1871 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1873 nt_devmode->specversion=devmode->specversion;
1874 nt_devmode->driverversion=devmode->driverversion;
1875 nt_devmode->size=devmode->size;
1876 nt_devmode->fields=devmode->fields;
1877 nt_devmode->orientation=devmode->orientation;
1878 nt_devmode->papersize=devmode->papersize;
1879 nt_devmode->paperlength=devmode->paperlength;
1880 nt_devmode->paperwidth=devmode->paperwidth;
1881 nt_devmode->scale=devmode->scale;
1882 nt_devmode->copies=devmode->copies;
1883 nt_devmode->defaultsource=devmode->defaultsource;
1884 nt_devmode->printquality=devmode->printquality;
1885 nt_devmode->color=devmode->color;
1886 nt_devmode->duplex=devmode->duplex;
1887 nt_devmode->yresolution=devmode->yresolution;
1888 nt_devmode->ttoption=devmode->ttoption;
1889 nt_devmode->collate=devmode->collate;
1891 nt_devmode->logpixels=devmode->logpixels;
1892 nt_devmode->bitsperpel=devmode->bitsperpel;
1893 nt_devmode->pelswidth=devmode->pelswidth;
1894 nt_devmode->pelsheight=devmode->pelsheight;
1895 nt_devmode->displayflags=devmode->displayflags;
1896 nt_devmode->displayfrequency=devmode->displayfrequency;
1897 nt_devmode->icmmethod=devmode->icmmethod;
1898 nt_devmode->icmintent=devmode->icmintent;
1899 nt_devmode->mediatype=devmode->mediatype;
1900 nt_devmode->dithertype=devmode->dithertype;
1901 nt_devmode->reserved1=devmode->reserved1;
1902 nt_devmode->reserved2=devmode->reserved2;
1903 nt_devmode->panningwidth=devmode->panningwidth;
1904 nt_devmode->panningheight=devmode->panningheight;
1907 * Only change private and driverextra if the incoming devmode
1908 * has a new one. JRA.
1911 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1912 SAFE_FREE(nt_devmode->private);
1913 nt_devmode->driverextra=devmode->driverextra;
1914 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1916 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1919 *pp_nt_devmode = nt_devmode;
1924 /********************************************************************
1925 * _spoolss_enddocprinter_internal.
1926 ********************************************************************/
1928 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1930 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1934 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1938 if (!get_printer_snum(p, handle, &snum))
1941 Printer->document_started=False;
1942 print_job_end(snum, Printer->jobid,True);
1943 /* error codes unhandled so far ... */
1948 /********************************************************************
1949 * api_spoolss_closeprinter
1950 ********************************************************************/
1952 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1954 POLICY_HND *handle = &q_u->handle;
1956 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 if (!close_printer_handle(p, handle))
1964 /* clear the returned printer handle. Observed behavior
1965 from Win2k server. Don't think this really matters.
1966 Previous code just copied the value of the closed
1969 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1974 /********************************************************************
1975 * api_spoolss_deleteprinter
1977 ********************************************************************/
1979 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1981 POLICY_HND *handle = &q_u->handle;
1982 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1985 if (Printer && Printer->document_started)
1986 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1988 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1990 result = delete_printer_handle(p, handle);
1992 update_c_setprinter(False);
1997 /*******************************************************************
1998 * static function to lookup the version id corresponding to an
1999 * long architecture string
2000 ******************************************************************/
2002 static int get_version_id (char * arch)
2005 struct table_node archi_table[]= {
2007 {"Windows 4.0", "WIN40", 0 },
2008 {"Windows NT x86", "W32X86", 2 },
2009 {"Windows NT R4000", "W32MIPS", 2 },
2010 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2011 {"Windows NT PowerPC", "W32PPC", 2 },
2015 for (i=0; archi_table[i].long_archi != NULL; i++)
2017 if (strcmp(arch, archi_table[i].long_archi) == 0)
2018 return (archi_table[i].version);
2024 /********************************************************************
2025 * _spoolss_deleteprinterdriver
2026 ********************************************************************/
2028 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2032 NT_PRINTER_DRIVER_INFO_LEVEL info;
2033 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2035 struct current_user user;
2037 WERROR status_win2k = WERR_ACCESS_DENIED;
2039 get_current_user(&user, p);
2041 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2042 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2044 /* check that we have a valid driver name first */
2046 if ((version=get_version_id(arch)) == -1)
2047 return WERR_INVALID_ENVIRONMENT;
2050 ZERO_STRUCT(info_win2k);
2052 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2054 /* try for Win2k driver if "Windows NT x86" */
2056 if ( version == 2 ) {
2058 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2059 status = WERR_UNKNOWN_PRINTER_DRIVER;
2063 /* otherwise it was a failure */
2065 status = WERR_UNKNOWN_PRINTER_DRIVER;
2071 if (printer_driver_in_use(info.info_3)) {
2072 status = WERR_PRINTER_DRIVER_IN_USE;
2078 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2080 /* if we get to here, we now have 2 driver info structures to remove */
2081 /* remove the Win2k driver first*/
2083 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2084 free_a_printer_driver( info_win2k, 3 );
2086 /* this should not have failed---if it did, report to client */
2087 if ( !W_ERROR_IS_OK(status_win2k) )
2092 status = delete_printer_driver(info.info_3, &user, version, False);
2094 /* if at least one of the deletes succeeded return OK */
2096 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2100 free_a_printer_driver( info, 3 );
2105 /********************************************************************
2106 * spoolss_deleteprinterdriverex
2107 ********************************************************************/
2109 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2113 NT_PRINTER_DRIVER_INFO_LEVEL info;
2114 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2116 uint32 flags = q_u->delete_flags;
2118 struct current_user user;
2120 WERROR status_win2k = WERR_ACCESS_DENIED;
2122 get_current_user(&user, p);
2124 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2125 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2127 /* check that we have a valid driver name first */
2128 if ((version=get_version_id(arch)) == -1) {
2129 /* this is what NT returns */
2130 return WERR_INVALID_ENVIRONMENT;
2133 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2134 version = q_u->version;
2137 ZERO_STRUCT(info_win2k);
2139 status = get_a_printer_driver(&info, 3, driver, arch, version);
2141 if ( !W_ERROR_IS_OK(status) )
2144 * if the client asked for a specific version,
2145 * or this is something other than Windows NT x86,
2149 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2152 /* try for Win2k driver if "Windows NT x86" */
2155 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2156 status = WERR_UNKNOWN_PRINTER_DRIVER;
2161 if ( printer_driver_in_use(info.info_3) ) {
2162 status = WERR_PRINTER_DRIVER_IN_USE;
2167 * we have a couple of cases to consider.
2168 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2169 * then the delete should fail if **any** files overlap with
2171 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2172 * non-overlapping files
2173 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2174 * is set, the do not delete any files
2175 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2178 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2180 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2182 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2183 /* no idea of the correct error here */
2184 status = WERR_ACCESS_DENIED;
2189 /* also check for W32X86/3 if necessary; maybe we already have? */
2191 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2192 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2195 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2196 /* no idea of the correct error here */
2197 free_a_printer_driver( info_win2k, 3 );
2198 status = WERR_ACCESS_DENIED;
2202 /* if we get to here, we now have 2 driver info structures to remove */
2203 /* remove the Win2k driver first*/
2205 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2206 free_a_printer_driver( info_win2k, 3 );
2208 /* this should not have failed---if it did, report to client */
2210 if ( !W_ERROR_IS_OK(status_win2k) )
2215 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2217 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2220 free_a_printer_driver( info, 3 );
2226 /****************************************************************************
2227 Internal routine for retreiving printerdata
2228 ***************************************************************************/
2230 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2231 const char *key, const char *value, uint32 *type, uint8 **data,
2232 uint32 *needed, uint32 in_size )
2234 REGISTRY_VALUE *val;
2237 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2238 return WERR_BADFILE;
2240 *type = regval_type( val );
2242 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2244 size = regval_size( val );
2246 /* copy the min(in_size, len) */
2249 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2251 /* special case for 0 length values */
2253 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2257 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2266 DEBUG(5,("get_printer_dataex: copy done\n"));
2271 /****************************************************************************
2272 Internal routine for removing printerdata
2273 ***************************************************************************/
2275 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2277 return delete_printer_data( printer->info_2, key, value );
2280 /****************************************************************************
2281 Internal routine for storing printerdata
2282 ***************************************************************************/
2284 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2285 uint32 type, uint8 *data, int real_len )
2287 delete_printer_data( printer->info_2, key, value );
2289 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2292 /********************************************************************
2293 GetPrinterData on a printer server Handle.
2294 ********************************************************************/
2296 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2300 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2302 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2304 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2310 if (!StrCaseCmp(value, "BeepEnabled")) {
2312 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2314 SIVAL(*data, 0, 0x00);
2319 if (!StrCaseCmp(value, "EventLog")) {
2321 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2323 /* formally was 0x1b */
2324 SIVAL(*data, 0, 0x0);
2329 if (!StrCaseCmp(value, "NetPopup")) {
2331 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2333 SIVAL(*data, 0, 0x00);
2338 if (!StrCaseCmp(value, "MajorVersion")) {
2340 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2343 /* Windows NT 4.0 seems to not allow uploading of drivers
2344 to a server that reports 0x3 as the MajorVersion.
2345 need to investigate more how Win2k gets around this .
2348 if ( RA_WINNT == get_remote_arch() )
2357 if (!StrCaseCmp(value, "MinorVersion")) {
2359 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2367 * uint32 size = 0x114
2369 * uint32 minor = [0|1]
2370 * uint32 build = [2195|2600]
2371 * extra unicode string = e.g. "Service Pack 3"
2373 if (!StrCaseCmp(value, "OSVersion")) {
2377 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2379 ZERO_STRUCTP( *data );
2381 SIVAL(*data, 0, *needed); /* size */
2382 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2384 SIVAL(*data, 12, 2195); /* build */
2386 /* leave extra string empty */
2392 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2393 const char *string="C:\\PRINTERS";
2395 *needed = 2*(strlen(string)+1);
2396 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2398 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2400 /* it's done by hand ready to go on the wire */
2401 for (i=0; i<strlen(string); i++) {
2402 (*data)[2*i]=string[i];
2403 (*data)[2*i+1]='\0';
2408 if (!StrCaseCmp(value, "Architecture")) {
2409 const char *string="Windows NT x86";
2411 *needed = 2*(strlen(string)+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(string); i++) {
2416 (*data)[2*i]=string[i];
2417 (*data)[2*i+1]='\0';
2422 if (!StrCaseCmp(value, "DsPresent")) {
2424 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2426 SIVAL(*data, 0, 0x01);
2431 if (!StrCaseCmp(value, "DNSMachineName")) {
2434 if (!get_myfullname(hostname))
2435 return WERR_BADFILE;
2437 *needed = 2*(strlen(hostname)+1);
2438 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2440 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2441 for (i=0; i<strlen(hostname); i++) {
2442 (*data)[2*i]=hostname[i];
2443 (*data)[2*i+1]='\0';
2449 return WERR_BADFILE;
2452 /********************************************************************
2453 * spoolss_getprinterdata
2454 ********************************************************************/
2456 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2458 POLICY_HND *handle = &q_u->handle;
2459 UNISTR2 *valuename = &q_u->valuename;
2460 uint32 in_size = q_u->size;
2461 uint32 *type = &r_u->type;
2462 uint32 *out_size = &r_u->size;
2463 uint8 **data = &r_u->data;
2464 uint32 *needed = &r_u->needed;
2467 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2468 NT_PRINTER_INFO_LEVEL *printer = NULL;
2472 * Reminder: when it's a string, the length is in BYTES
2473 * even if UNICODE is negociated.
2478 *out_size = in_size;
2480 /* in case of problem, return some default values */
2485 DEBUG(4,("_spoolss_getprinterdata\n"));
2488 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2489 status = WERR_BADFID;
2493 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2495 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2496 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2499 if ( !get_printer_snum(p,handle, &snum) ) {
2500 status = WERR_BADFID;
2504 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2505 if ( !W_ERROR_IS_OK(status) )
2508 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2510 if ( strequal(value, "ChangeId") ) {
2512 *needed = sizeof(uint32);
2513 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2514 status = WERR_NOMEM;
2517 SIVAL( *data, 0, printer->info_2->changeid );
2521 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2524 if (*needed > *out_size)
2525 status = WERR_MORE_DATA;
2528 if ( !W_ERROR_IS_OK(status) )
2530 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2532 /* reply this param doesn't exist */
2535 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2537 free_a_printer( &printer, 2 );
2546 /* cleanup & exit */
2549 free_a_printer( &printer, 2 );
2554 /*********************************************************
2555 Connect to the client machine.
2556 **********************************************************/
2558 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2559 struct in_addr *client_ip, const char *remote_machine)
2561 ZERO_STRUCTP(the_cli);
2563 if(cli_initialise(the_cli) == NULL) {
2564 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2568 if ( is_zero_ip(*client_ip) ) {
2569 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2570 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2571 cli_shutdown(the_cli);
2575 if (ismyip(the_cli->dest_ip)) {
2576 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2577 cli_shutdown(the_cli);
2582 the_cli->dest_ip.s_addr = client_ip->s_addr;
2583 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2584 inet_ntoa(*client_ip) ));
2587 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2588 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) ));
2589 cli_shutdown(the_cli);
2593 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2594 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2596 cli_shutdown(the_cli);
2600 the_cli->protocol = PROTOCOL_NT1;
2602 if (!cli_negprot(the_cli)) {
2603 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2604 cli_shutdown(the_cli);
2608 if (the_cli->protocol != PROTOCOL_NT1) {
2609 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2610 cli_shutdown(the_cli);
2615 * Do an anonymous session setup.
2618 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2619 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2620 cli_shutdown(the_cli);
2624 if (!(the_cli->sec_mode & 1)) {
2625 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2626 cli_shutdown(the_cli);
2630 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2631 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) ));
2632 cli_shutdown(the_cli);
2637 * Ok - we have an anonymous connection to the IPC$ share.
2638 * Now start the NT Domain stuff :-).
2641 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2642 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)));
2643 cli_nt_session_close(the_cli);
2644 cli_ulogoff(the_cli);
2645 cli_shutdown(the_cli);
2652 /***************************************************************************
2653 Connect to the client.
2654 ****************************************************************************/
2656 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2657 uint32 localprinter, uint32 type,
2658 POLICY_HND *handle, struct in_addr *client_ip)
2663 * If it's the first connection, contact the client
2664 * and connect to the IPC$ share anonymously
2666 if (smb_connections==0) {
2667 fstring unix_printer;
2669 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2671 ZERO_STRUCT(notify_cli);
2673 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2676 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2677 /* Tell the connections db we're now interested in printer
2678 * notify messages. */
2679 register_message_flags( True, FLAG_MSG_PRINTING );
2683 * Tell the specific printing tdb we want messages for this printer
2684 * by registering our PID.
2687 if (!print_notify_register_pid(snum))
2688 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2692 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2695 if (!W_ERROR_IS_OK(result))
2696 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2697 dos_errstr(result)));
2699 return (W_ERROR_IS_OK(result));
2702 /********************************************************************
2704 * ReplyFindFirstPrinterChangeNotifyEx
2706 * before replying OK: status=0 a rpc call is made to the workstation
2707 * asking ReplyOpenPrinter
2709 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2710 * called from api_spoolss_rffpcnex
2711 ********************************************************************/
2713 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2715 POLICY_HND *handle = &q_u->handle;
2716 uint32 flags = q_u->flags;
2717 uint32 options = q_u->options;
2718 UNISTR2 *localmachine = &q_u->localmachine;
2719 uint32 printerlocal = q_u->printerlocal;
2721 SPOOL_NOTIFY_OPTION *option = q_u->option;
2722 struct in_addr client_ip;
2724 /* store the notify value in the printer struct */
2726 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2729 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2733 Printer->notify.flags=flags;
2734 Printer->notify.options=options;
2735 Printer->notify.printerlocal=printerlocal;
2737 if (Printer->notify.option)
2738 free_spool_notify_option(&Printer->notify.option);
2740 Printer->notify.option=dup_spool_notify_option(option);
2742 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2743 sizeof(Printer->notify.localmachine)-1);
2745 /* Connect to the client machine and send a ReplyOpenPrinter */
2747 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2749 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2750 !get_printer_snum(p, handle, &snum) )
2753 client_ip.s_addr = inet_addr(p->conn->client_address);
2755 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2756 Printer->notify.printerlocal, 1,
2757 &Printer->notify.client_hnd, &client_ip))
2758 return WERR_SERVER_UNAVAILABLE;
2760 Printer->notify.client_connected=True;
2765 /*******************************************************************
2766 * fill a notify_info_data with the servername
2767 ********************************************************************/
2769 void spoolss_notify_server_name(int snum,
2770 SPOOL_NOTIFY_INFO_DATA *data,
2771 print_queue_struct *queue,
2772 NT_PRINTER_INFO_LEVEL *printer,
2773 TALLOC_CTX *mem_ctx)
2775 pstring temp_name, temp;
2778 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2780 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2782 data->notify_data.data.length = len;
2783 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2785 if (!data->notify_data.data.string) {
2786 data->notify_data.data.length = 0;
2790 memcpy(data->notify_data.data.string, temp, len);
2793 /*******************************************************************
2794 * fill a notify_info_data with the printername (not including the servername).
2795 ********************************************************************/
2797 void spoolss_notify_printer_name(int snum,
2798 SPOOL_NOTIFY_INFO_DATA *data,
2799 print_queue_struct *queue,
2800 NT_PRINTER_INFO_LEVEL *printer,
2801 TALLOC_CTX *mem_ctx)
2806 /* the notify name should not contain the \\server\ part */
2807 char *p = strrchr(printer->info_2->printername, '\\');
2810 p = printer->info_2->printername;
2815 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2817 data->notify_data.data.length = len;
2818 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2820 if (!data->notify_data.data.string) {
2821 data->notify_data.data.length = 0;
2825 memcpy(data->notify_data.data.string, temp, len);
2828 /*******************************************************************
2829 * fill a notify_info_data with the servicename
2830 ********************************************************************/
2832 void spoolss_notify_share_name(int snum,
2833 SPOOL_NOTIFY_INFO_DATA *data,
2834 print_queue_struct *queue,
2835 NT_PRINTER_INFO_LEVEL *printer,
2836 TALLOC_CTX *mem_ctx)
2841 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2843 data->notify_data.data.length = len;
2844 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2846 if (!data->notify_data.data.string) {
2847 data->notify_data.data.length = 0;
2851 memcpy(data->notify_data.data.string, temp, len);
2854 /*******************************************************************
2855 * fill a notify_info_data with the port name
2856 ********************************************************************/
2858 void spoolss_notify_port_name(int snum,
2859 SPOOL_NOTIFY_INFO_DATA *data,
2860 print_queue_struct *queue,
2861 NT_PRINTER_INFO_LEVEL *printer,
2862 TALLOC_CTX *mem_ctx)
2867 /* even if it's strange, that's consistant in all the code */
2869 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2871 data->notify_data.data.length = len;
2872 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2874 if (!data->notify_data.data.string) {
2875 data->notify_data.data.length = 0;
2879 memcpy(data->notify_data.data.string, temp, len);
2882 /*******************************************************************
2883 * fill a notify_info_data with the printername
2884 * but it doesn't exist, have to see what to do
2885 ********************************************************************/
2887 void spoolss_notify_driver_name(int snum,
2888 SPOOL_NOTIFY_INFO_DATA *data,
2889 print_queue_struct *queue,
2890 NT_PRINTER_INFO_LEVEL *printer,
2891 TALLOC_CTX *mem_ctx)
2896 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2898 data->notify_data.data.length = len;
2899 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2901 if (!data->notify_data.data.string) {
2902 data->notify_data.data.length = 0;
2906 memcpy(data->notify_data.data.string, temp, len);
2909 /*******************************************************************
2910 * fill a notify_info_data with the comment
2911 ********************************************************************/
2913 void spoolss_notify_comment(int snum,
2914 SPOOL_NOTIFY_INFO_DATA *data,
2915 print_queue_struct *queue,
2916 NT_PRINTER_INFO_LEVEL *printer,
2917 TALLOC_CTX *mem_ctx)
2922 if (*printer->info_2->comment == '\0')
2923 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2925 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2927 data->notify_data.data.length = len;
2928 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2930 if (!data->notify_data.data.string) {
2931 data->notify_data.data.length = 0;
2935 memcpy(data->notify_data.data.string, temp, len);
2938 /*******************************************************************
2939 * fill a notify_info_data with the comment
2940 * location = "Room 1, floor 2, building 3"
2941 ********************************************************************/
2943 void spoolss_notify_location(int snum,
2944 SPOOL_NOTIFY_INFO_DATA *data,
2945 print_queue_struct *queue,
2946 NT_PRINTER_INFO_LEVEL *printer,
2947 TALLOC_CTX *mem_ctx)
2952 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2954 data->notify_data.data.length = len;
2955 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2957 if (!data->notify_data.data.string) {
2958 data->notify_data.data.length = 0;
2962 memcpy(data->notify_data.data.string, temp, len);
2965 /*******************************************************************
2966 * fill a notify_info_data with the device mode
2967 * jfm:xxxx don't to it for know but that's a real problem !!!
2968 ********************************************************************/
2970 static void spoolss_notify_devmode(int snum,
2971 SPOOL_NOTIFY_INFO_DATA *data,
2972 print_queue_struct *queue,
2973 NT_PRINTER_INFO_LEVEL *printer,
2974 TALLOC_CTX *mem_ctx)
2978 /*******************************************************************
2979 * fill a notify_info_data with the separator file name
2980 ********************************************************************/
2982 void spoolss_notify_sepfile(int snum,
2983 SPOOL_NOTIFY_INFO_DATA *data,
2984 print_queue_struct *queue,
2985 NT_PRINTER_INFO_LEVEL *printer,
2986 TALLOC_CTX *mem_ctx)
2991 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2993 data->notify_data.data.length = len;
2994 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2996 if (!data->notify_data.data.string) {
2997 data->notify_data.data.length = 0;
3001 memcpy(data->notify_data.data.string, temp, len);
3004 /*******************************************************************
3005 * fill a notify_info_data with the print processor
3006 * jfm:xxxx return always winprint to indicate we don't do anything to it
3007 ********************************************************************/
3009 void spoolss_notify_print_processor(int snum,
3010 SPOOL_NOTIFY_INFO_DATA *data,
3011 print_queue_struct *queue,
3012 NT_PRINTER_INFO_LEVEL *printer,
3013 TALLOC_CTX *mem_ctx)
3018 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3020 data->notify_data.data.length = len;
3021 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3023 if (!data->notify_data.data.string) {
3024 data->notify_data.data.length = 0;
3028 memcpy(data->notify_data.data.string, temp, len);
3031 /*******************************************************************
3032 * fill a notify_info_data with the print processor options
3033 * jfm:xxxx send an empty string
3034 ********************************************************************/
3036 void spoolss_notify_parameters(int snum,
3037 SPOOL_NOTIFY_INFO_DATA *data,
3038 print_queue_struct *queue,
3039 NT_PRINTER_INFO_LEVEL *printer,
3040 TALLOC_CTX *mem_ctx)
3045 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3047 data->notify_data.data.length = len;
3048 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3050 if (!data->notify_data.data.string) {
3051 data->notify_data.data.length = 0;
3055 memcpy(data->notify_data.data.string, temp, len);
3058 /*******************************************************************
3059 * fill a notify_info_data with the data type
3060 * jfm:xxxx always send RAW as data type
3061 ********************************************************************/
3063 void spoolss_notify_datatype(int snum,
3064 SPOOL_NOTIFY_INFO_DATA *data,
3065 print_queue_struct *queue,
3066 NT_PRINTER_INFO_LEVEL *printer,
3067 TALLOC_CTX *mem_ctx)
3072 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3074 data->notify_data.data.length = len;
3075 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3077 if (!data->notify_data.data.string) {
3078 data->notify_data.data.length = 0;
3082 memcpy(data->notify_data.data.string, temp, len);
3085 /*******************************************************************
3086 * fill a notify_info_data with the security descriptor
3087 * jfm:xxxx send an null pointer to say no security desc
3088 * have to implement security before !
3089 ********************************************************************/
3091 static void spoolss_notify_security_desc(int snum,
3092 SPOOL_NOTIFY_INFO_DATA *data,
3093 print_queue_struct *queue,
3094 NT_PRINTER_INFO_LEVEL *printer,
3095 TALLOC_CTX *mem_ctx)
3097 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3098 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3101 /*******************************************************************
3102 * fill a notify_info_data with the attributes
3103 * jfm:xxxx a samba printer is always shared
3104 ********************************************************************/
3106 void spoolss_notify_attributes(int snum,
3107 SPOOL_NOTIFY_INFO_DATA *data,
3108 print_queue_struct *queue,
3109 NT_PRINTER_INFO_LEVEL *printer,
3110 TALLOC_CTX *mem_ctx)
3112 data->notify_data.value[0] = printer->info_2->attributes;
3113 data->notify_data.value[1] = 0;
3116 /*******************************************************************
3117 * fill a notify_info_data with the priority
3118 ********************************************************************/
3120 static void spoolss_notify_priority(int snum,
3121 SPOOL_NOTIFY_INFO_DATA *data,
3122 print_queue_struct *queue,
3123 NT_PRINTER_INFO_LEVEL *printer,
3124 TALLOC_CTX *mem_ctx)
3126 data->notify_data.value[0] = printer->info_2->priority;
3127 data->notify_data.value[1] = 0;
3130 /*******************************************************************
3131 * fill a notify_info_data with the default priority
3132 ********************************************************************/
3134 static void spoolss_notify_default_priority(int snum,
3135 SPOOL_NOTIFY_INFO_DATA *data,
3136 print_queue_struct *queue,
3137 NT_PRINTER_INFO_LEVEL *printer,
3138 TALLOC_CTX *mem_ctx)
3140 data->notify_data.value[0] = printer->info_2->default_priority;
3141 data->notify_data.value[1] = 0;
3144 /*******************************************************************
3145 * fill a notify_info_data with the start time
3146 ********************************************************************/
3148 static void spoolss_notify_start_time(int snum,
3149 SPOOL_NOTIFY_INFO_DATA *data,
3150 print_queue_struct *queue,
3151 NT_PRINTER_INFO_LEVEL *printer,
3152 TALLOC_CTX *mem_ctx)
3154 data->notify_data.value[0] = printer->info_2->starttime;
3155 data->notify_data.value[1] = 0;
3158 /*******************************************************************
3159 * fill a notify_info_data with the until time
3160 ********************************************************************/
3162 static void spoolss_notify_until_time(int snum,
3163 SPOOL_NOTIFY_INFO_DATA *data,
3164 print_queue_struct *queue,
3165 NT_PRINTER_INFO_LEVEL *printer,
3166 TALLOC_CTX *mem_ctx)
3168 data->notify_data.value[0] = printer->info_2->untiltime;
3169 data->notify_data.value[1] = 0;
3172 /*******************************************************************
3173 * fill a notify_info_data with the status
3174 ********************************************************************/
3176 static void spoolss_notify_status(int snum,
3177 SPOOL_NOTIFY_INFO_DATA *data,
3178 print_queue_struct *queue,
3179 NT_PRINTER_INFO_LEVEL *printer,
3180 TALLOC_CTX *mem_ctx)
3182 print_status_struct status;
3184 print_queue_length(snum, &status);
3185 data->notify_data.value[0]=(uint32) status.status;
3186 data->notify_data.value[1] = 0;
3189 /*******************************************************************
3190 * fill a notify_info_data with the number of jobs queued
3191 ********************************************************************/
3193 void spoolss_notify_cjobs(int snum,
3194 SPOOL_NOTIFY_INFO_DATA *data,
3195 print_queue_struct *queue,
3196 NT_PRINTER_INFO_LEVEL *printer,
3197 TALLOC_CTX *mem_ctx)
3199 data->notify_data.value[0] = print_queue_length(snum, NULL);
3200 data->notify_data.value[1] = 0;
3203 /*******************************************************************
3204 * fill a notify_info_data with the average ppm
3205 ********************************************************************/
3207 static void spoolss_notify_average_ppm(int snum,
3208 SPOOL_NOTIFY_INFO_DATA *data,
3209 print_queue_struct *queue,
3210 NT_PRINTER_INFO_LEVEL *printer,
3211 TALLOC_CTX *mem_ctx)
3213 /* always respond 8 pages per minutes */
3214 /* a little hard ! */
3215 data->notify_data.value[0] = printer->info_2->averageppm;
3216 data->notify_data.value[1] = 0;
3219 /*******************************************************************
3220 * fill a notify_info_data with username
3221 ********************************************************************/
3223 static void spoolss_notify_username(int snum,
3224 SPOOL_NOTIFY_INFO_DATA *data,
3225 print_queue_struct *queue,
3226 NT_PRINTER_INFO_LEVEL *printer,
3227 TALLOC_CTX *mem_ctx)
3232 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3234 data->notify_data.data.length = len;
3235 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3237 if (!data->notify_data.data.string) {
3238 data->notify_data.data.length = 0;
3242 memcpy(data->notify_data.data.string, temp, len);
3245 /*******************************************************************
3246 * fill a notify_info_data with job status
3247 ********************************************************************/
3249 static void spoolss_notify_job_status(int snum,
3250 SPOOL_NOTIFY_INFO_DATA *data,
3251 print_queue_struct *queue,
3252 NT_PRINTER_INFO_LEVEL *printer,
3253 TALLOC_CTX *mem_ctx)
3255 data->notify_data.value[0]=nt_printj_status(queue->status);
3256 data->notify_data.value[1] = 0;
3259 /*******************************************************************
3260 * fill a notify_info_data with job name
3261 ********************************************************************/
3263 static void spoolss_notify_job_name(int snum,
3264 SPOOL_NOTIFY_INFO_DATA *data,
3265 print_queue_struct *queue,
3266 NT_PRINTER_INFO_LEVEL *printer,
3267 TALLOC_CTX *mem_ctx)
3272 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3274 data->notify_data.data.length = len;
3275 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3277 if (!data->notify_data.data.string) {
3278 data->notify_data.data.length = 0;
3282 memcpy(data->notify_data.data.string, temp, len);
3285 /*******************************************************************
3286 * fill a notify_info_data with job status
3287 ********************************************************************/
3289 static void spoolss_notify_job_status_string(int snum,
3290 SPOOL_NOTIFY_INFO_DATA *data,
3291 print_queue_struct *queue,
3292 NT_PRINTER_INFO_LEVEL *printer,
3293 TALLOC_CTX *mem_ctx)
3296 * Now we're returning job status codes we just return a "" here. JRA.
3303 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3306 switch (queue->status) {
3311 p = ""; /* NT provides the paused string */
3320 #endif /* NO LONGER NEEDED. */
3322 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3324 data->notify_data.data.length = len;
3325 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3327 if (!data->notify_data.data.string) {
3328 data->notify_data.data.length = 0;
3332 memcpy(data->notify_data.data.string, temp, len);
3335 /*******************************************************************
3336 * fill a notify_info_data with job time
3337 ********************************************************************/
3339 static void spoolss_notify_job_time(int snum,
3340 SPOOL_NOTIFY_INFO_DATA *data,
3341 print_queue_struct *queue,
3342 NT_PRINTER_INFO_LEVEL *printer,
3343 TALLOC_CTX *mem_ctx)
3345 data->notify_data.value[0]=0x0;
3346 data->notify_data.value[1]=0;
3349 /*******************************************************************
3350 * fill a notify_info_data with job size
3351 ********************************************************************/
3353 static void spoolss_notify_job_size(int snum,
3354 SPOOL_NOTIFY_INFO_DATA *data,
3355 print_queue_struct *queue,
3356 NT_PRINTER_INFO_LEVEL *printer,
3357 TALLOC_CTX *mem_ctx)
3359 data->notify_data.value[0]=queue->size;
3360 data->notify_data.value[1]=0;
3363 /*******************************************************************
3364 * fill a notify_info_data with page info
3365 ********************************************************************/
3366 static void spoolss_notify_total_pages(int snum,
3367 SPOOL_NOTIFY_INFO_DATA *data,
3368 print_queue_struct *queue,
3369 NT_PRINTER_INFO_LEVEL *printer,
3370 TALLOC_CTX *mem_ctx)
3372 data->notify_data.value[0]=queue->page_count;
3373 data->notify_data.value[1]=0;
3376 /*******************************************************************
3377 * fill a notify_info_data with pages printed info.
3378 ********************************************************************/
3379 static void spoolss_notify_pages_printed(int snum,
3380 SPOOL_NOTIFY_INFO_DATA *data,
3381 print_queue_struct *queue,
3382 NT_PRINTER_INFO_LEVEL *printer,
3383 TALLOC_CTX *mem_ctx)
3385 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3386 data->notify_data.value[1]=0;
3389 /*******************************************************************
3390 Fill a notify_info_data with job position.
3391 ********************************************************************/
3393 static void spoolss_notify_job_position(int snum,
3394 SPOOL_NOTIFY_INFO_DATA *data,
3395 print_queue_struct *queue,
3396 NT_PRINTER_INFO_LEVEL *printer,
3397 TALLOC_CTX *mem_ctx)
3399 data->notify_data.value[0]=queue->job;
3400 data->notify_data.value[1]=0;
3403 /*******************************************************************
3404 Fill a notify_info_data with submitted time.
3405 ********************************************************************/
3407 static void spoolss_notify_submitted_time(int snum,
3408 SPOOL_NOTIFY_INFO_DATA *data,
3409 print_queue_struct *queue,
3410 NT_PRINTER_INFO_LEVEL *printer,
3411 TALLOC_CTX *mem_ctx)
3418 t=gmtime(&queue->time);
3420 len = sizeof(SYSTEMTIME);
3422 data->notify_data.data.length = len;
3423 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3425 if (!data->notify_data.data.string) {
3426 data->notify_data.data.length = 0;
3430 make_systemtime(&st, t);
3433 * Systemtime must be linearized as a set of UINT16's.
3434 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3437 p = (char *)data->notify_data.data.string;
3438 SSVAL(p, 0, st.year);
3439 SSVAL(p, 2, st.month);
3440 SSVAL(p, 4, st.dayofweek);
3441 SSVAL(p, 6, st.day);
3442 SSVAL(p, 8, st.hour);
3443 SSVAL(p, 10, st.minute);
3444 SSVAL(p, 12, st.second);
3445 SSVAL(p, 14, st.milliseconds);
3448 struct s_notify_info_data_table
3454 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3455 print_queue_struct *queue,
3456 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3459 /* A table describing the various print notification constants and
3460 whether the notification data is a pointer to a variable sized
3461 buffer, a one value uint32 or a two value uint32. */
3463 static const struct s_notify_info_data_table notify_info_data_table[] =
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3489 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3490 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3511 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3512 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3513 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3516 /*******************************************************************
3517 Return the size of info_data structure.
3518 ********************************************************************/
3520 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3524 for (i = 0; i < sizeof(notify_info_data_table); i++)
3526 if ( (notify_info_data_table[i].type == type)
3527 && (notify_info_data_table[i].field == field) )
3529 switch(notify_info_data_table[i].size)
3531 case NOTIFY_ONE_VALUE:
3532 case NOTIFY_TWO_VALUE:
3537 /* The only pointer notify data I have seen on
3538 the wire is the submitted time and this has
3539 the notify size set to 4. -tpot */
3541 case NOTIFY_POINTER:
3544 case NOTIFY_SECDESC:
3550 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3555 /*******************************************************************
3556 Return the type of notify_info_data.
3557 ********************************************************************/
3559 static int type_of_notify_info_data(uint16 type, uint16 field)
3563 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3564 if (notify_info_data_table[i].type == type &&
3565 notify_info_data_table[i].field == field)
3566 return notify_info_data_table[i].size;
3572 /****************************************************************************
3573 ****************************************************************************/
3575 static int search_notify(uint16 type, uint16 field, int *value)
3579 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3580 if (notify_info_data_table[i].type == type &&
3581 notify_info_data_table[i].field == field &&
3582 notify_info_data_table[i].fn != NULL) {
3591 /****************************************************************************
3592 ****************************************************************************/
3594 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3596 info_data->type = type;
3597 info_data->field = field;
3598 info_data->reserved = 0;
3600 info_data->size = size_of_notify_info_data(type, field);
3601 info_data->enc_type = type_of_notify_info_data(type, field);
3608 /*******************************************************************
3610 * fill a notify_info struct with info asked
3612 ********************************************************************/
3614 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3615 snum, SPOOL_NOTIFY_OPTION_TYPE
3616 *option_type, uint32 id,
3617 TALLOC_CTX *mem_ctx)
3623 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3624 NT_PRINTER_INFO_LEVEL *printer = NULL;
3625 print_queue_struct *queue=NULL;
3627 type=option_type->type;
3629 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3630 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3631 option_type->count, lp_servicename(snum)));
3633 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3636 for(field_num=0; field_num<option_type->count; field_num++) {
3637 field = option_type->fields[field_num];
3639 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3641 if (!search_notify(type, field, &j) )
3644 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3645 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3650 current_data = &info->data[info->count];
3652 construct_info_data(current_data, type, field, id);
3654 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3655 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3657 notify_info_data_table[j].fn(snum, current_data, queue,
3663 free_a_printer(&printer, 2);
3667 /*******************************************************************
3669 * fill a notify_info struct with info asked
3671 ********************************************************************/
3673 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3674 SPOOL_NOTIFY_INFO *info,
3675 NT_PRINTER_INFO_LEVEL *printer,
3676 int snum, SPOOL_NOTIFY_OPTION_TYPE
3677 *option_type, uint32 id,
3678 TALLOC_CTX *mem_ctx)
3684 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3686 DEBUG(4,("construct_notify_jobs_info\n"));
3688 type = option_type->type;
3690 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3691 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3692 option_type->count));
3694 for(field_num=0; field_num<option_type->count; field_num++) {
3695 field = option_type->fields[field_num];
3697 if (!search_notify(type, field, &j) )
3700 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3701 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3704 else info->data = tid;
3706 current_data=&(info->data[info->count]);
3708 construct_info_data(current_data, type, field, id);
3709 notify_info_data_table[j].fn(snum, current_data, queue,
3718 * JFM: The enumeration is not that simple, it's even non obvious.
3720 * let's take an example: I want to monitor the PRINTER SERVER for
3721 * the printer's name and the number of jobs currently queued.
3722 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3723 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3725 * I have 3 printers on the back of my server.
3727 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3730 * 1 printer 1 name 1
3731 * 2 printer 1 cjob 1
3732 * 3 printer 2 name 2
3733 * 4 printer 2 cjob 2
3734 * 5 printer 3 name 3
3735 * 6 printer 3 name 3
3737 * that's the print server case, the printer case is even worse.
3740 /*******************************************************************
3742 * enumerate all printers on the printserver
3743 * fill a notify_info struct with info asked
3745 ********************************************************************/
3747 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3748 SPOOL_NOTIFY_INFO *info,
3749 TALLOC_CTX *mem_ctx)
3752 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3753 int n_services=lp_numservices();
3755 SPOOL_NOTIFY_OPTION *option;
3756 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3758 DEBUG(4,("printserver_notify_info\n"));
3763 option=Printer->notify.option;
3768 for (i=0; i<option->count; i++) {
3769 option_type=&(option->ctr.type[i]);
3771 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3774 for (snum=0; snum<n_services; snum++)
3776 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3777 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3783 * Debugging information, don't delete.
3786 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3787 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3788 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3790 for (i=0; i<info->count; i++) {
3791 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3792 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3793 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3800 /*******************************************************************
3802 * fill a notify_info struct with info asked
3804 ********************************************************************/
3806 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3807 TALLOC_CTX *mem_ctx)
3810 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3813 SPOOL_NOTIFY_OPTION *option;
3814 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3816 print_queue_struct *queue=NULL;
3817 print_status_struct status;
3819 DEBUG(4,("printer_notify_info\n"));
3824 option=Printer->notify.option;
3830 get_printer_snum(p, hnd, &snum);
3832 for (i=0; i<option->count; i++) {
3833 option_type=&option->ctr.type[i];
3835 switch ( option_type->type ) {
3836 case PRINTER_NOTIFY_TYPE:
3837 if(construct_notify_printer_info(Printer, info, snum,
3843 case JOB_NOTIFY_TYPE: {
3844 NT_PRINTER_INFO_LEVEL *printer = NULL;
3846 count = print_queue_status(snum, &queue, &status);
3848 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3851 for (j=0; j<count; j++) {
3852 construct_notify_jobs_info(&queue[j], info,
3859 free_a_printer(&printer, 2);
3869 * Debugging information, don't delete.
3872 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3873 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3874 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3876 for (i=0; i<info->count; i++) {
3877 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3878 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3879 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3885 /********************************************************************
3887 ********************************************************************/
3889 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3891 POLICY_HND *handle = &q_u->handle;
3892 SPOOL_NOTIFY_INFO *info = &r_u->info;
3894 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3895 WERROR result = WERR_BADFID;
3897 /* we always have a NOTIFY_INFO struct */
3901 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3902 OUR_HANDLE(handle)));
3906 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3909 * We are now using the change value, and
3910 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3911 * I don't have a global notification system, I'm sending back all the
3912 * informations even when _NOTHING_ has changed.
3915 /* We need to keep track of the change value to send back in
3916 RRPCN replies otherwise our updates are ignored. */
3918 Printer->notify.fnpcn = True;
3920 if (Printer->notify.client_connected) {
3921 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3922 Printer->notify.change = q_u->change;
3925 /* just ignore the SPOOL_NOTIFY_OPTION */
3927 switch (Printer->printer_type) {
3928 case PRINTER_HANDLE_IS_PRINTSERVER:
3929 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3932 case PRINTER_HANDLE_IS_PRINTER:
3933 result = printer_notify_info(p, handle, info, p->mem_ctx);
3937 Printer->notify.fnpcn = False;
3943 /********************************************************************
3944 * construct_printer_info_0
3945 * fill a printer_info_0 struct
3946 ********************************************************************/
3948 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3952 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3953 counter_printer_0 *session_counter;
3954 uint32 global_counter;
3957 print_status_struct status;
3959 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3962 count = print_queue_length(snum, &status);
3964 /* check if we already have a counter for this printer */
3965 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3967 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3968 if (session_counter->snum == snum)
3972 /* it's the first time, add it to the list */
3973 if (session_counter==NULL) {
3974 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3975 free_a_printer(&ntprinter, 2);
3978 ZERO_STRUCTP(session_counter);
3979 session_counter->snum=snum;
3980 session_counter->counter=0;
3981 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3985 session_counter->counter++;
3988 * the global_counter should be stored in a TDB as it's common to all the clients
3989 * and should be zeroed on samba startup
3991 global_counter=session_counter->counter;
3993 pstrcpy(chaine,ntprinter->info_2->printername);
3995 init_unistr(&printer->printername, chaine);
3997 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3998 init_unistr(&printer->servername, chaine);
4000 printer->cjobs = count;
4001 printer->total_jobs = 0;
4002 printer->total_bytes = 0;
4004 setuptime = (time_t)ntprinter->info_2->setuptime;
4005 t=gmtime(&setuptime);
4007 printer->year = t->tm_year+1900;
4008 printer->month = t->tm_mon+1;
4009 printer->dayofweek = t->tm_wday;
4010 printer->day = t->tm_mday;
4011 printer->hour = t->tm_hour;
4012 printer->minute = t->tm_min;
4013 printer->second = t->tm_sec;
4014 printer->milliseconds = 0;
4016 printer->global_counter = global_counter;
4017 printer->total_pages = 0;
4019 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4020 printer->major_version = 0x0005; /* NT 5 */
4021 printer->build_version = 0x0893; /* build 2195 */
4023 printer->unknown7 = 0x1;
4024 printer->unknown8 = 0x0;
4025 printer->unknown9 = 0x0;
4026 printer->session_counter = session_counter->counter;
4027 printer->unknown11 = 0x0;
4028 printer->printer_errors = 0x0; /* number of print failure */
4029 printer->unknown13 = 0x0;
4030 printer->unknown14 = 0x1;
4031 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4032 printer->unknown16 = 0x0;
4033 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4034 printer->unknown18 = 0x0;
4035 printer->status = nt_printq_status(status.status);
4036 printer->unknown20 = 0x0;
4037 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4038 printer->unknown22 = 0x0;
4039 printer->unknown23 = 0x6; /* 6 ???*/
4040 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4041 printer->unknown25 = 0;
4042 printer->unknown26 = 0;
4043 printer->unknown27 = 0;
4044 printer->unknown28 = 0;
4045 printer->unknown29 = 0;
4047 free_a_printer(&ntprinter,2);
4051 /********************************************************************
4052 * construct_printer_info_1
4053 * fill a printer_info_1 struct
4054 ********************************************************************/
4055 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4059 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4061 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4064 printer->flags=flags;
4066 if (*ntprinter->info_2->comment == '\0') {
4067 init_unistr(&printer->comment, lp_comment(snum));
4068 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4069 ntprinter->info_2->drivername, lp_comment(snum));
4072 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4073 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4074 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4077 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4079 init_unistr(&printer->description, chaine);
4080 init_unistr(&printer->name, chaine2);
4082 free_a_printer(&ntprinter,2);
4087 /****************************************************************************
4088 Free a DEVMODE struct.
4089 ****************************************************************************/
4091 static void free_dev_mode(DEVICEMODE *dev)
4096 SAFE_FREE(dev->private);
4101 /****************************************************************************
4102 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4103 should be valid upon entry
4104 ****************************************************************************/
4106 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4108 if ( !devmode || !ntdevmode )
4111 init_unistr(&devmode->devicename, ntdevmode->devicename);
4113 init_unistr(&devmode->formname, ntdevmode->formname);
4115 devmode->specversion = ntdevmode->specversion;
4116 devmode->driverversion = ntdevmode->driverversion;
4117 devmode->size = ntdevmode->size;
4118 devmode->driverextra = ntdevmode->driverextra;
4119 devmode->fields = ntdevmode->fields;
4121 devmode->orientation = ntdevmode->orientation;
4122 devmode->papersize = ntdevmode->papersize;
4123 devmode->paperlength = ntdevmode->paperlength;
4124 devmode->paperwidth = ntdevmode->paperwidth;
4125 devmode->scale = ntdevmode->scale;
4126 devmode->copies = ntdevmode->copies;
4127 devmode->defaultsource = ntdevmode->defaultsource;
4128 devmode->printquality = ntdevmode->printquality;
4129 devmode->color = ntdevmode->color;
4130 devmode->duplex = ntdevmode->duplex;
4131 devmode->yresolution = ntdevmode->yresolution;
4132 devmode->ttoption = ntdevmode->ttoption;
4133 devmode->collate = ntdevmode->collate;
4134 devmode->icmmethod = ntdevmode->icmmethod;
4135 devmode->icmintent = ntdevmode->icmintent;
4136 devmode->mediatype = ntdevmode->mediatype;
4137 devmode->dithertype = ntdevmode->dithertype;
4139 if (ntdevmode->private != NULL) {
4140 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4147 /****************************************************************************
4148 Create a DEVMODE struct. Returns malloced memory.
4149 ****************************************************************************/
4151 DEVICEMODE *construct_dev_mode(int snum)
4153 NT_PRINTER_INFO_LEVEL *printer = NULL;
4154 DEVICEMODE *devmode = NULL;
4156 DEBUG(7,("construct_dev_mode\n"));
4158 DEBUGADD(8,("getting printer characteristics\n"));
4160 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4163 if ( !printer->info_2->devmode ) {
4164 DEBUG(5, ("BONG! There was no device mode!\n"));
4168 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4169 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4173 ZERO_STRUCTP(devmode);
4175 DEBUGADD(8,("loading DEVICEMODE\n"));
4177 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4178 free_dev_mode( devmode );
4183 free_a_printer(&printer,2);
4188 /********************************************************************
4189 * construct_printer_info_2
4190 * fill a printer_info_2 struct
4191 ********************************************************************/
4193 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4196 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4198 print_status_struct status;
4200 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4203 count = print_queue_length(snum, &status);
4205 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4206 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4207 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4208 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4209 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4211 if (*ntprinter->info_2->comment == '\0')
4212 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4214 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4216 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4217 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4218 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4219 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4220 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4222 printer->attributes = ntprinter->info_2->attributes;
4224 printer->priority = ntprinter->info_2->priority; /* priority */
4225 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4226 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4227 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4228 printer->status = nt_printq_status(status.status); /* status */
4229 printer->cjobs = count; /* jobs */
4230 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4232 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4233 DEBUG(8, ("Returning NULL Devicemode!\n"));
4236 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4237 /* steal the printer info sec_desc structure. [badly done]. */
4238 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4239 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4240 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4241 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4244 printer->secdesc = NULL;
4247 free_a_printer(&ntprinter, 2);
4251 /********************************************************************
4252 * construct_printer_info_3
4253 * fill a printer_info_3 struct
4254 ********************************************************************/
4256 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4258 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4259 PRINTER_INFO_3 *printer = NULL;
4261 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4265 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4266 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4270 ZERO_STRUCTP(printer);
4272 printer->flags = 4; /* These are the components of the SD we are returning. */
4273 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4274 /* steal the printer info sec_desc structure. [badly done]. */
4275 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4279 * Set the flags for the components we are returning.
4282 if (printer->secdesc->owner_sid)
4283 printer->flags |= OWNER_SECURITY_INFORMATION;
4285 if (printer->secdesc->grp_sid)
4286 printer->flags |= GROUP_SECURITY_INFORMATION;
4288 if (printer->secdesc->dacl)
4289 printer->flags |= DACL_SECURITY_INFORMATION;
4291 if (printer->secdesc->sacl)
4292 printer->flags |= SACL_SECURITY_INFORMATION;
4295 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4296 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4297 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4300 free_a_printer(&ntprinter, 2);
4302 *pp_printer = printer;
4306 /********************************************************************
4307 * construct_printer_info_4
4308 * fill a printer_info_4 struct
4309 ********************************************************************/
4311 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4313 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4315 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4318 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4319 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4320 printer->attributes = ntprinter->info_2->attributes;
4322 free_a_printer(&ntprinter, 2);
4326 /********************************************************************
4327 * construct_printer_info_5
4328 * fill a printer_info_5 struct
4329 ********************************************************************/
4331 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4333 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4335 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4338 init_unistr(&printer->printername, ntprinter->info_2->printername);
4339 init_unistr(&printer->portname, ntprinter->info_2->portname);
4340 printer->attributes = ntprinter->info_2->attributes;
4342 /* these two are not used by NT+ according to MSDN */
4344 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4345 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4347 free_a_printer(&ntprinter, 2);
4352 /********************************************************************
4353 * construct_printer_info_7
4354 * fill a printer_info_7 struct
4355 ********************************************************************/
4357 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4359 char *guid_str = NULL;
4362 if (is_printer_published(print_hnd, snum, &guid)) {
4363 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4364 strupper_m(guid_str);
4365 init_unistr(&printer->guid, guid_str);
4366 printer->action = SPOOL_DS_PUBLISH;
4368 init_unistr(&printer->guid, "");
4369 printer->action = SPOOL_DS_UNPUBLISH;
4375 /********************************************************************
4376 Spoolss_enumprinters.
4377 ********************************************************************/
4379 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4383 int n_services=lp_numservices();
4384 PRINTER_INFO_1 *tp, *printers=NULL;
4385 PRINTER_INFO_1 current_prt;
4387 DEBUG(4,("enum_all_printers_info_1\n"));
4389 for (snum=0; snum<n_services; snum++) {
4390 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4391 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4393 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4394 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4395 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4396 SAFE_FREE(printers);
4401 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4403 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4409 /* check the required size. */
4410 for (i=0; i<*returned; i++)
4411 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4413 if (!alloc_buffer_size(buffer, *needed))
4414 return WERR_INSUFFICIENT_BUFFER;
4416 /* fill the buffer with the structures */
4417 for (i=0; i<*returned; i++)
4418 smb_io_printer_info_1("", buffer, &printers[i], 0);
4421 SAFE_FREE(printers);
4423 if (*needed > offered) {
4425 return WERR_INSUFFICIENT_BUFFER;
4431 /********************************************************************
4432 enum_all_printers_info_1_local.
4433 *********************************************************************/
4435 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4437 DEBUG(4,("enum_all_printers_info_1_local\n"));
4439 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4442 /********************************************************************
4443 enum_all_printers_info_1_name.
4444 *********************************************************************/
4446 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4450 DEBUG(4,("enum_all_printers_info_1_name\n"));
4452 if ((name[0] == '\\') && (name[1] == '\\'))
4455 if (is_myname_or_ipaddr(s)) {
4456 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4459 return WERR_INVALID_NAME;
4462 /********************************************************************
4463 enum_all_printers_info_1_remote.
4464 *********************************************************************/
4466 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4468 PRINTER_INFO_1 *printer;
4469 fstring printername;
4472 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4474 /* JFM: currently it's more a place holder than anything else.
4475 * In the spooler world there is a notion of server registration.
4476 * the print servers are registring (sp ?) on the PDC (in the same domain)
4478 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4481 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4486 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4487 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4488 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4490 init_unistr(&printer->description, desc);
4491 init_unistr(&printer->name, printername);
4492 init_unistr(&printer->comment, comment);
4493 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4495 /* check the required size. */
4496 *needed += spoolss_size_printer_info_1(printer);
4498 if (!alloc_buffer_size(buffer, *needed)) {
4500 return WERR_INSUFFICIENT_BUFFER;
4503 /* fill the buffer with the structures */
4504 smb_io_printer_info_1("", buffer, printer, 0);
4509 if (*needed > offered) {
4511 return WERR_INSUFFICIENT_BUFFER;
4517 /********************************************************************
4518 enum_all_printers_info_1_network.
4519 *********************************************************************/
4521 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4525 DEBUG(4,("enum_all_printers_info_1_network\n"));
4527 /* If we respond to a enum_printers level 1 on our name with flags
4528 set to PRINTER_ENUM_REMOTE with a list of printers then these
4529 printers incorrectly appear in the APW browse list.
4530 Specifically the printers for the server appear at the workgroup
4531 level where all the other servers in the domain are
4532 listed. Windows responds to this call with a
4533 WERR_CAN_NOT_COMPLETE so we should do the same. */
4535 if (name[0] == '\\' && name[1] == '\\')
4538 if (is_myname_or_ipaddr(s))
4539 return WERR_CAN_NOT_COMPLETE;
4541 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4544 /********************************************************************
4545 * api_spoolss_enumprinters
4547 * called from api_spoolss_enumprinters (see this to understand)
4548 ********************************************************************/
4550 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4554 int n_services=lp_numservices();
4555 PRINTER_INFO_2 *tp, *printers=NULL;
4556 PRINTER_INFO_2 current_prt;
4558 for (snum=0; snum<n_services; snum++) {
4559 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4560 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4562 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4563 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4564 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4565 SAFE_FREE(printers);
4570 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4571 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4577 /* check the required size. */
4578 for (i=0; i<*returned; i++)
4579 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4581 if (!alloc_buffer_size(buffer, *needed)) {
4582 for (i=0; i<*returned; i++) {
4583 free_devmode(printers[i].devmode);
4585 SAFE_FREE(printers);
4586 return WERR_INSUFFICIENT_BUFFER;
4589 /* fill the buffer with the structures */
4590 for (i=0; i<*returned; i++)
4591 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4594 for (i=0; i<*returned; i++) {
4595 free_devmode(printers[i].devmode);
4597 SAFE_FREE(printers);
4599 if (*needed > offered) {
4601 return WERR_INSUFFICIENT_BUFFER;
4607 /********************************************************************
4608 * handle enumeration of printers at level 1
4609 ********************************************************************/
4611 static WERROR enumprinters_level1( uint32 flags, fstring name,
4612 NEW_BUFFER *buffer, uint32 offered,
4613 uint32 *needed, uint32 *returned)
4615 /* Not all the flags are equals */
4617 if (flags & PRINTER_ENUM_LOCAL)
4618 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4620 if (flags & PRINTER_ENUM_NAME)
4621 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4623 if (flags & PRINTER_ENUM_REMOTE)
4624 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4626 if (flags & PRINTER_ENUM_NETWORK)
4627 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4629 return WERR_OK; /* NT4sp5 does that */
4632 /********************************************************************
4633 * handle enumeration of printers at level 2
4634 ********************************************************************/
4636 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4637 NEW_BUFFER *buffer, uint32 offered,
4638 uint32 *needed, uint32 *returned)
4640 char *s = servername;
4642 if (flags & PRINTER_ENUM_LOCAL) {
4643 return enum_all_printers_info_2(buffer, offered, needed, returned);
4646 if (flags & PRINTER_ENUM_NAME) {
4647 if ((servername[0] == '\\') && (servername[1] == '\\'))
4649 if (is_myname_or_ipaddr(s))
4650 return enum_all_printers_info_2(buffer, offered, needed, returned);
4652 return WERR_INVALID_NAME;
4655 if (flags & PRINTER_ENUM_REMOTE)
4656 return WERR_UNKNOWN_LEVEL;
4661 /********************************************************************
4662 * handle enumeration of printers at level 5
4663 ********************************************************************/
4665 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4666 NEW_BUFFER *buffer, uint32 offered,
4667 uint32 *needed, uint32 *returned)
4669 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4673 /********************************************************************
4674 * api_spoolss_enumprinters
4676 * called from api_spoolss_enumprinters (see this to understand)
4677 ********************************************************************/
4679 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4681 uint32 flags = q_u->flags;
4682 UNISTR2 *servername = &q_u->servername;
4683 uint32 level = q_u->level;
4684 NEW_BUFFER *buffer = NULL;
4685 uint32 offered = q_u->offered;
4686 uint32 *needed = &r_u->needed;
4687 uint32 *returned = &r_u->returned;
4691 /* that's an [in out] buffer */
4692 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4693 buffer = r_u->buffer;
4695 DEBUG(4,("_spoolss_enumprinters\n"));
4702 * flags==PRINTER_ENUM_NAME
4703 * if name=="" then enumerates all printers
4704 * if name!="" then enumerate the printer
4705 * flags==PRINTER_ENUM_REMOTE
4706 * name is NULL, enumerate printers
4707 * Level 2: name!="" enumerates printers, name can't be NULL
4708 * Level 3: doesn't exist
4709 * Level 4: does a local registry lookup
4710 * Level 5: same as Level 2
4713 unistr2_to_ascii(name, servername, sizeof(name)-1);
4718 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4720 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4722 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4727 return WERR_UNKNOWN_LEVEL;
4730 /****************************************************************************
4731 ****************************************************************************/
4733 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4735 PRINTER_INFO_0 *printer=NULL;
4737 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4740 construct_printer_info_0(print_hnd, printer, snum);
4742 /* check the required size. */
4743 *needed += spoolss_size_printer_info_0(printer);
4745 if (!alloc_buffer_size(buffer, *needed)) {
4747 return WERR_INSUFFICIENT_BUFFER;
4750 /* fill the buffer with the structures */
4751 smb_io_printer_info_0("", buffer, printer, 0);
4756 if (*needed > offered) {
4757 return WERR_INSUFFICIENT_BUFFER;
4763 /****************************************************************************
4764 ****************************************************************************/
4766 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4768 PRINTER_INFO_1 *printer=NULL;
4770 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4773 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4775 /* check the required size. */
4776 *needed += spoolss_size_printer_info_1(printer);
4778 if (!alloc_buffer_size(buffer, *needed)) {
4780 return WERR_INSUFFICIENT_BUFFER;
4783 /* fill the buffer with the structures */
4784 smb_io_printer_info_1("", buffer, printer, 0);
4789 if (*needed > offered) {
4790 return WERR_INSUFFICIENT_BUFFER;
4796 /****************************************************************************
4797 ****************************************************************************/
4799 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4801 PRINTER_INFO_2 *printer=NULL;
4803 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4806 construct_printer_info_2(print_hnd, printer, snum);
4808 /* check the required size. */
4809 *needed += spoolss_size_printer_info_2(printer);
4811 if (!alloc_buffer_size(buffer, *needed)) {
4812 free_printer_info_2(printer);
4813 return WERR_INSUFFICIENT_BUFFER;
4816 /* fill the buffer with the structures */
4817 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4818 free_printer_info_2(printer);
4823 free_printer_info_2(printer);
4825 if (*needed > offered) {
4826 return WERR_INSUFFICIENT_BUFFER;
4832 /****************************************************************************
4833 ****************************************************************************/
4835 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4837 PRINTER_INFO_3 *printer=NULL;
4839 if (!construct_printer_info_3(print_hnd, &printer, snum))
4842 /* check the required size. */
4843 *needed += spoolss_size_printer_info_3(printer);
4845 if (!alloc_buffer_size(buffer, *needed)) {
4846 free_printer_info_3(printer);
4847 return WERR_INSUFFICIENT_BUFFER;
4850 /* fill the buffer with the structures */
4851 smb_io_printer_info_3("", buffer, printer, 0);
4854 free_printer_info_3(printer);
4856 if (*needed > offered) {
4857 return WERR_INSUFFICIENT_BUFFER;
4863 /****************************************************************************
4864 ****************************************************************************/
4866 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4868 PRINTER_INFO_4 *printer=NULL;
4870 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4873 if (!construct_printer_info_4(print_hnd, printer, snum))
4876 /* check the required size. */
4877 *needed += spoolss_size_printer_info_4(printer);
4879 if (!alloc_buffer_size(buffer, *needed)) {
4880 free_printer_info_4(printer);
4881 return WERR_INSUFFICIENT_BUFFER;
4884 /* fill the buffer with the structures */
4885 smb_io_printer_info_4("", buffer, printer, 0);
4888 free_printer_info_4(printer);
4890 if (*needed > offered) {
4891 return WERR_INSUFFICIENT_BUFFER;
4897 /****************************************************************************
4898 ****************************************************************************/
4900 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4902 PRINTER_INFO_5 *printer=NULL;
4904 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4907 if (!construct_printer_info_5(print_hnd, printer, snum))
4910 /* check the required size. */
4911 *needed += spoolss_size_printer_info_5(printer);
4913 if (!alloc_buffer_size(buffer, *needed)) {
4914 free_printer_info_5(printer);
4915 return WERR_INSUFFICIENT_BUFFER;
4918 /* fill the buffer with the structures */
4919 smb_io_printer_info_5("", buffer, printer, 0);
4922 free_printer_info_5(printer);
4924 if (*needed > offered) {
4925 return WERR_INSUFFICIENT_BUFFER;
4931 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4933 PRINTER_INFO_7 *printer=NULL;
4935 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4938 if (!construct_printer_info_7(print_hnd, printer, snum))
4941 /* check the required size. */
4942 *needed += spoolss_size_printer_info_7(printer);
4944 if (!alloc_buffer_size(buffer, *needed)) {
4945 free_printer_info_7(printer);
4946 return WERR_INSUFFICIENT_BUFFER;
4949 /* fill the buffer with the structures */
4950 smb_io_printer_info_7("", buffer, printer, 0);
4953 free_printer_info_7(printer);
4955 if (*needed > offered) {
4956 return WERR_INSUFFICIENT_BUFFER;
4962 /****************************************************************************
4963 ****************************************************************************/
4965 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4967 POLICY_HND *handle = &q_u->handle;
4968 uint32 level = q_u->level;
4969 NEW_BUFFER *buffer = NULL;
4970 uint32 offered = q_u->offered;
4971 uint32 *needed = &r_u->needed;
4972 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4976 /* that's an [in out] buffer */
4977 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4978 buffer = r_u->buffer;
4982 if (!get_printer_snum(p, handle, &snum))
4987 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4989 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4991 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4993 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4995 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4997 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4999 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5001 return WERR_UNKNOWN_LEVEL;
5004 /********************************************************************
5005 * fill a DRIVER_INFO_1 struct
5006 ********************************************************************/
5008 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5010 init_unistr( &info->name, driver.info_3->name);
5013 /********************************************************************
5014 * construct_printer_driver_info_1
5015 ********************************************************************/
5017 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5019 NT_PRINTER_INFO_LEVEL *printer = NULL;
5020 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5022 ZERO_STRUCT(driver);
5024 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5025 return WERR_INVALID_PRINTER_NAME;
5027 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5028 return WERR_UNKNOWN_PRINTER_DRIVER;
5030 fill_printer_driver_info_1(info, driver, servername, architecture);
5032 free_a_printer(&printer,2);
5037 /********************************************************************
5038 * construct_printer_driver_info_2
5039 * fill a printer_info_2 struct
5040 ********************************************************************/
5042 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5046 info->version=driver.info_3->cversion;
5048 init_unistr( &info->name, driver.info_3->name );
5049 init_unistr( &info->architecture, driver.info_3->environment );
5052 if (strlen(driver.info_3->driverpath)) {
5053 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5054 init_unistr( &info->driverpath, temp );
5056 init_unistr( &info->driverpath, "" );
5058 if (strlen(driver.info_3->datafile)) {
5059 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5060 init_unistr( &info->datafile, temp );
5062 init_unistr( &info->datafile, "" );
5064 if (strlen(driver.info_3->configfile)) {
5065 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5066 init_unistr( &info->configfile, temp );
5068 init_unistr( &info->configfile, "" );
5071 /********************************************************************
5072 * construct_printer_driver_info_2
5073 * fill a printer_info_2 struct
5074 ********************************************************************/
5076 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5078 NT_PRINTER_INFO_LEVEL *printer = NULL;
5079 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5081 ZERO_STRUCT(printer);
5082 ZERO_STRUCT(driver);
5084 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5085 return WERR_INVALID_PRINTER_NAME;
5087 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5088 return WERR_UNKNOWN_PRINTER_DRIVER;
5090 fill_printer_driver_info_2(info, driver, servername);
5092 free_a_printer(&printer,2);
5097 /********************************************************************
5098 * copy a strings array and convert to UNICODE
5100 * convert an array of ascii string to a UNICODE string
5101 ********************************************************************/
5103 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5111 DEBUG(6,("init_unistr_array\n"));
5122 v = ""; /* hack to handle null lists */
5125 /* hack to allow this to be used in places other than when generating
5126 the list of dependent files */
5129 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5133 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5135 /* add one extra unit16 for the second terminating NULL */
5137 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5138 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5146 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5151 /* special case for ""; we need to add both NULL's here */
5153 (*uni_array)[j++]=0x0000;
5154 (*uni_array)[j]=0x0000;
5157 DEBUGADD(6,("last one:done\n"));
5159 /* return size of array in uint16's */
5164 /********************************************************************
5165 * construct_printer_info_3
5166 * fill a printer_info_3 struct
5167 ********************************************************************/
5169 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5175 info->version=driver.info_3->cversion;
5177 init_unistr( &info->name, driver.info_3->name );
5178 init_unistr( &info->architecture, driver.info_3->environment );
5180 if (strlen(driver.info_3->driverpath)) {
5181 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5182 init_unistr( &info->driverpath, temp );
5184 init_unistr( &info->driverpath, "" );
5186 if (strlen(driver.info_3->datafile)) {
5187 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5188 init_unistr( &info->datafile, temp );
5190 init_unistr( &info->datafile, "" );
5192 if (strlen(driver.info_3->configfile)) {
5193 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5194 init_unistr( &info->configfile, temp );
5196 init_unistr( &info->configfile, "" );
5198 if (strlen(driver.info_3->helpfile)) {
5199 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5200 init_unistr( &info->helpfile, temp );
5202 init_unistr( &info->helpfile, "" );
5204 init_unistr( &info->monitorname, driver.info_3->monitorname );
5205 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5207 info->dependentfiles=NULL;
5208 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5211 /********************************************************************
5212 * construct_printer_info_3
5213 * fill a printer_info_3 struct
5214 ********************************************************************/
5216 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5218 NT_PRINTER_INFO_LEVEL *printer = NULL;
5219 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5221 ZERO_STRUCT(driver);
5223 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5224 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5225 if (!W_ERROR_IS_OK(status))
5226 return WERR_INVALID_PRINTER_NAME;
5228 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5229 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5234 * I put this code in during testing. Helpful when commenting out the
5235 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5236 * as win2k always queries the driver using an infor level of 6.
5237 * I've left it in (but ifdef'd out) because I'll probably
5238 * use it in experimentation again in the future. --jerry 22/01/2002
5241 if (!W_ERROR_IS_OK(status)) {
5243 * Is this a W2k client ?
5246 /* Yes - try again with a WinNT driver. */
5248 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5249 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5253 if (!W_ERROR_IS_OK(status)) {
5254 free_a_printer(&printer,2);
5255 return WERR_UNKNOWN_PRINTER_DRIVER;
5263 fill_printer_driver_info_3(info, driver, servername);
5265 free_a_printer(&printer,2);
5270 /********************************************************************
5271 * construct_printer_info_6
5272 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5273 ********************************************************************/
5275 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5281 memset(&nullstr, '\0', sizeof(fstring));
5283 info->version=driver.info_3->cversion;
5285 init_unistr( &info->name, driver.info_3->name );
5286 init_unistr( &info->architecture, driver.info_3->environment );
5288 if (strlen(driver.info_3->driverpath)) {
5289 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5290 init_unistr( &info->driverpath, temp );
5292 init_unistr( &info->driverpath, "" );
5294 if (strlen(driver.info_3->datafile)) {
5295 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5296 init_unistr( &info->datafile, temp );
5298 init_unistr( &info->datafile, "" );
5300 if (strlen(driver.info_3->configfile)) {
5301 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5302 init_unistr( &info->configfile, temp );
5304 init_unistr( &info->configfile, "" );
5306 if (strlen(driver.info_3->helpfile)) {
5307 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5308 init_unistr( &info->helpfile, temp );
5310 init_unistr( &info->helpfile, "" );
5312 init_unistr( &info->monitorname, driver.info_3->monitorname );
5313 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5315 info->dependentfiles = NULL;
5316 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5318 info->previousdrivernames=NULL;
5319 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5321 info->driver_date.low=0;
5322 info->driver_date.high=0;
5325 info->driver_version_low=0;
5326 info->driver_version_high=0;
5328 init_unistr( &info->mfgname, "");
5329 init_unistr( &info->oem_url, "");
5330 init_unistr( &info->hardware_id, "");
5331 init_unistr( &info->provider, "");
5334 /********************************************************************
5335 * construct_printer_info_6
5336 * fill a printer_info_6 struct
5337 ********************************************************************/
5339 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5340 fstring servername, fstring architecture, uint32 version)
5342 NT_PRINTER_INFO_LEVEL *printer = NULL;
5343 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5346 ZERO_STRUCT(driver);
5348 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5350 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5352 if (!W_ERROR_IS_OK(status))
5353 return WERR_INVALID_PRINTER_NAME;
5355 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5357 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5359 if (!W_ERROR_IS_OK(status))
5362 * Is this a W2k client ?
5366 free_a_printer(&printer,2);
5367 return WERR_UNKNOWN_PRINTER_DRIVER;
5370 /* Yes - try again with a WinNT driver. */
5372 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5373 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5374 if (!W_ERROR_IS_OK(status)) {
5375 free_a_printer(&printer,2);
5376 return WERR_UNKNOWN_PRINTER_DRIVER;
5380 fill_printer_driver_info_6(info, driver, servername);
5382 free_a_printer(&printer,2);
5383 free_a_printer_driver(driver, 3);
5388 /****************************************************************************
5389 ****************************************************************************/
5391 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5393 SAFE_FREE(info->dependentfiles);
5396 /****************************************************************************
5397 ****************************************************************************/
5399 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5401 SAFE_FREE(info->dependentfiles);
5405 /****************************************************************************
5406 ****************************************************************************/
5408 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5410 DRIVER_INFO_1 *info=NULL;
5413 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5416 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5417 if (!W_ERROR_IS_OK(status)) {
5422 /* check the required size. */
5423 *needed += spoolss_size_printer_driver_info_1(info);
5425 if (!alloc_buffer_size(buffer, *needed)) {
5427 return WERR_INSUFFICIENT_BUFFER;
5430 /* fill the buffer with the structures */
5431 smb_io_printer_driver_info_1("", buffer, info, 0);
5436 if (*needed > offered)
5437 return WERR_INSUFFICIENT_BUFFER;
5442 /****************************************************************************
5443 ****************************************************************************/
5445 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5447 DRIVER_INFO_2 *info=NULL;
5450 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5453 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5454 if (!W_ERROR_IS_OK(status)) {
5459 /* check the required size. */
5460 *needed += spoolss_size_printer_driver_info_2(info);
5462 if (!alloc_buffer_size(buffer, *needed)) {
5464 return WERR_INSUFFICIENT_BUFFER;
5467 /* fill the buffer with the structures */
5468 smb_io_printer_driver_info_2("", buffer, info, 0);
5473 if (*needed > offered)
5474 return WERR_INSUFFICIENT_BUFFER;
5479 /****************************************************************************
5480 ****************************************************************************/
5482 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5489 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5490 if (!W_ERROR_IS_OK(status)) {
5494 /* check the required size. */
5495 *needed += spoolss_size_printer_driver_info_3(&info);
5497 if (!alloc_buffer_size(buffer, *needed)) {
5498 free_printer_driver_info_3(&info);
5499 return WERR_INSUFFICIENT_BUFFER;
5502 /* fill the buffer with the structures */
5503 smb_io_printer_driver_info_3("", buffer, &info, 0);
5505 free_printer_driver_info_3(&info);
5507 if (*needed > offered)
5508 return WERR_INSUFFICIENT_BUFFER;
5513 /****************************************************************************
5514 ****************************************************************************/
5516 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5523 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5524 if (!W_ERROR_IS_OK(status)) {
5528 /* check the required size. */
5529 *needed += spoolss_size_printer_driver_info_6(&info);
5531 if (!alloc_buffer_size(buffer, *needed)) {
5532 free_printer_driver_info_6(&info);
5533 return WERR_INSUFFICIENT_BUFFER;
5536 /* fill the buffer with the structures */
5537 smb_io_printer_driver_info_6("", buffer, &info, 0);
5539 free_printer_driver_info_6(&info);
5541 if (*needed > offered)
5542 return WERR_INSUFFICIENT_BUFFER;
5547 /****************************************************************************
5548 ****************************************************************************/
5550 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5552 POLICY_HND *handle = &q_u->handle;
5553 UNISTR2 *uni_arch = &q_u->architecture;
5554 uint32 level = q_u->level;
5555 uint32 clientmajorversion = q_u->clientmajorversion;
5556 NEW_BUFFER *buffer = NULL;
5557 uint32 offered = q_u->offered;
5558 uint32 *needed = &r_u->needed;
5559 uint32 *servermajorversion = &r_u->servermajorversion;
5560 uint32 *serverminorversion = &r_u->serverminorversion;
5563 fstring architecture;
5566 /* that's an [in out] buffer */
5567 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5568 buffer = r_u->buffer;
5570 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5573 *servermajorversion = 0;
5574 *serverminorversion = 0;
5576 fstrcpy(servername, get_called_name());
5577 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5579 if (!get_printer_snum(p, handle, &snum))
5584 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5586 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5588 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5590 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5593 return WERR_UNKNOWN_LEVEL;
5596 /****************************************************************************
5597 ****************************************************************************/
5599 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5601 POLICY_HND *handle = &q_u->handle;
5603 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5606 DEBUG(3,("Error in startpageprinter printer handle\n"));
5610 Printer->page_started=True;
5614 /****************************************************************************
5615 ****************************************************************************/
5617 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5619 POLICY_HND *handle = &q_u->handle;
5622 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5625 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5629 if (!get_printer_snum(p, handle, &snum))
5632 Printer->page_started=False;
5633 print_job_endpage(snum, Printer->jobid);
5638 /********************************************************************
5639 * api_spoolss_getprinter
5640 * called from the spoolss dispatcher
5642 ********************************************************************/
5644 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5646 POLICY_HND *handle = &q_u->handle;
5647 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5648 uint32 *jobid = &r_u->jobid;
5650 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5654 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5655 struct current_user user;
5658 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5662 get_current_user(&user, p);
5665 * a nice thing with NT is it doesn't listen to what you tell it.
5666 * when asked to send _only_ RAW datas, it tries to send datas
5669 * So I add checks like in NT Server ...
5672 if (info_1->p_datatype != 0) {
5673 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5674 if (strcmp(datatype, "RAW") != 0) {
5676 return WERR_INVALID_DATATYPE;
5680 /* get the share number of the printer */
5681 if (!get_printer_snum(p, handle, &snum)) {
5685 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5687 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5689 /* An error occured in print_job_start() so return an appropriate
5692 if (Printer->jobid == -1) {
5693 return map_werror_from_unix(errno);
5696 Printer->document_started=True;
5697 (*jobid) = Printer->jobid;
5702 /********************************************************************
5703 * api_spoolss_getprinter
5704 * called from the spoolss dispatcher
5706 ********************************************************************/
5708 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5710 POLICY_HND *handle = &q_u->handle;
5712 return _spoolss_enddocprinter_internal(p, handle);
5715 /****************************************************************************
5716 ****************************************************************************/
5718 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5720 POLICY_HND *handle = &q_u->handle;
5721 uint32 buffer_size = q_u->buffer_size;
5722 uint8 *buffer = q_u->buffer;
5723 uint32 *buffer_written = &q_u->buffer_size2;
5725 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5728 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5729 r_u->buffer_written = q_u->buffer_size2;
5733 if (!get_printer_snum(p, handle, &snum))
5736 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5737 if (*buffer_written == -1) {
5738 r_u->buffer_written = 0;
5739 if (errno == ENOSPC)
5740 return WERR_NO_SPOOL_SPACE;
5742 return WERR_ACCESS_DENIED;
5745 r_u->buffer_written = q_u->buffer_size2;
5750 /********************************************************************
5751 * api_spoolss_getprinter
5752 * called from the spoolss dispatcher
5754 ********************************************************************/
5756 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5759 struct current_user user;
5761 WERROR errcode = WERR_BADFUNC;
5762 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5764 get_current_user(&user, p);
5767 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5771 if (!get_printer_snum(p, handle, &snum))
5775 case PRINTER_CONTROL_PAUSE:
5776 if (print_queue_pause(&user, snum, &errcode)) {
5780 case PRINTER_CONTROL_RESUME:
5781 case PRINTER_CONTROL_UNPAUSE:
5782 if (print_queue_resume(&user, snum, &errcode)) {
5786 case PRINTER_CONTROL_PURGE:
5787 if (print_queue_purge(&user, snum, &errcode)) {
5792 return WERR_UNKNOWN_LEVEL;
5798 /********************************************************************
5799 * api_spoolss_abortprinter
5800 * From MSDN: "Deletes printer's spool file if printer is configured
5802 ********************************************************************/
5804 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5806 POLICY_HND *handle = &q_u->handle;
5807 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5809 struct current_user user;
5810 WERROR errcode = WERR_OK;
5813 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5817 if (!get_printer_snum(p, handle, &snum))
5820 get_current_user( &user, p );
5822 print_job_delete( &user, snum, Printer->jobid, &errcode );
5827 /********************************************************************
5828 * called by spoolss_api_setprinter
5829 * when updating a printer description
5830 ********************************************************************/
5832 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5833 const SPOOL_PRINTER_INFO_LEVEL *info,
5834 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5836 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5837 struct current_user user;
5841 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5843 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5844 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5845 OUR_HANDLE(handle)));
5847 result = WERR_BADFID;
5851 /* NT seems to like setting the security descriptor even though
5852 nothing may have actually changed. This causes annoying
5853 dialog boxes when the user doesn't have permission to change
5854 the security descriptor. */
5856 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5858 if (DEBUGLEVEL >= 10) {
5862 the_acl = old_secdesc_ctr->sec->dacl;
5863 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5864 PRINTERNAME(snum), the_acl->num_aces));
5866 for (i = 0; i < the_acl->num_aces; i++) {
5869 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5871 DEBUG(10, ("%s 0x%08x\n", sid_str,
5872 the_acl->ace[i].info.mask));
5875 the_acl = secdesc_ctr->sec->dacl;
5878 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5879 PRINTERNAME(snum), the_acl->num_aces));
5881 for (i = 0; i < the_acl->num_aces; i++) {
5884 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5886 DEBUG(10, ("%s 0x%08x\n", sid_str,
5887 the_acl->ace[i].info.mask));
5890 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5894 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5896 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5901 /* Work out which user is performing the operation */
5903 get_current_user(&user, p);
5905 /* Check the user has permissions to change the security
5906 descriptor. By experimentation with two NT machines, the user
5907 requires Full Access to the printer to change security
5910 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5911 result = WERR_ACCESS_DENIED;
5915 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5922 /********************************************************************
5923 Do Samba sanity checks on a printer info struct.
5924 this has changed purpose: it now "canonicalises" printer
5925 info from a client rather than just checking it is correct
5926 ********************************************************************/
5928 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5930 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5931 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5933 /* we force some elements to "correct" values */
5934 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5935 fstrcpy(info->sharename, lp_servicename(snum));
5936 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5937 get_called_name(), info->sharename);
5938 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5944 /****************************************************************************
5945 ****************************************************************************/
5947 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5949 extern userdom_struct current_user_info;
5950 char *cmd = lp_addprinter_cmd();
5956 fstring remote_machine = "%m";
5958 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5960 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5961 cmd, printer->info_2->printername, printer->info_2->sharename,
5962 printer->info_2->portname, printer->info_2->drivername,
5963 printer->info_2->location, printer->info_2->comment, remote_machine);
5965 DEBUG(10,("Running [%s]\n", command));
5966 ret = smbrun(command, &fd);
5967 DEBUGADD(10,("returned [%d]\n", ret));
5976 /* Get lines and convert them back to dos-codepage */
5977 qlines = fd_lines_load(fd, &numlines);
5978 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5982 /* Set the portname to what the script says the portname should be. */
5983 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5984 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5986 /* Send SIGHUP to process group... is there a better way? */
5989 /* reload our services immediately */
5990 reload_services( False );
5993 file_lines_free(qlines);
5997 /********************************************************************
5998 * Called by spoolss_api_setprinter
5999 * when updating a printer description.
6000 ********************************************************************/
6002 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6003 const SPOOL_PRINTER_INFO_LEVEL *info,
6004 DEVICEMODE *devmode)
6007 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6008 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6013 DEBUG(8,("update_printer\n"));
6018 result = WERR_BADFID;
6022 if (!get_printer_snum(p, handle, &snum)) {
6023 result = WERR_BADFID;
6027 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6028 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6029 result = WERR_BADFID;
6033 DEBUGADD(8,("Converting info_2 struct\n"));
6036 * convert_printer_info converts the incoming
6037 * info from the client and overwrites the info
6038 * just read from the tdb in the pointer 'printer'.
6041 if (!convert_printer_info(info, printer, level)) {
6042 result = WERR_NOMEM;
6047 /* we have a valid devmode
6048 convert it and link it*/
6050 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6051 if (!convert_devicemode(printer->info_2->printername, devmode,
6052 &printer->info_2->devmode)) {
6053 result = WERR_NOMEM;
6058 /* Do sanity check on the requested changes for Samba */
6060 if (!check_printer_ok(printer->info_2, snum)) {
6061 result = WERR_INVALID_PARAM;
6065 /* FIXME!!! If the driver has changed we really should verify that
6066 it is installed before doing much else --jerry */
6068 /* Check calling user has permission to update printer description */
6070 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6071 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6072 result = WERR_ACCESS_DENIED;
6076 /* Call addprinter hook */
6077 /* Check changes to see if this is really needed */
6079 if ( *lp_addprinter_cmd()
6080 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6081 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6082 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6083 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6085 if ( !add_printer_hook(printer) ) {
6086 result = WERR_ACCESS_DENIED;
6091 * make sure we actually reload the services after
6092 * this as smb.conf could have a new section in it
6093 * .... shouldn't .... but could
6095 reload_services(False);
6099 * When a *new* driver is bound to a printer, the drivername is used to
6100 * lookup previously saved driver initialization info, which is then
6101 * bound to the printer, simulating what happens in the Windows arch.
6103 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6105 if (!set_driver_init(printer, 2))
6107 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6108 printer->info_2->drivername));
6111 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6112 printer->info_2->drivername));
6114 notify_printer_driver(snum, printer->info_2->drivername);
6118 * flag which changes actually occured. This is a small subset of
6119 * all the possible changes. We also have to update things in the
6123 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6124 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6125 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6126 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6128 notify_printer_comment(snum, printer->info_2->comment);
6131 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6132 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6133 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6134 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6135 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6136 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6138 notify_printer_sharename(snum, printer->info_2->sharename);
6141 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6142 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6143 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6144 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6146 notify_printer_port(snum, printer->info_2->portname);
6149 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6150 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6151 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6152 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6154 notify_printer_location(snum, printer->info_2->location);
6157 /* here we need to update some more DsSpooler keys */
6158 /* uNCName, serverName, shortServerName */
6160 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6161 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6162 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6163 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6164 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6166 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6167 global_myname(), printer->info_2->sharename );
6168 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6169 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6170 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6172 /* Update printer info */
6173 result = mod_a_printer(*printer, 2);
6176 free_a_printer(&printer, 2);
6177 free_a_printer(&old_printer, 2);
6183 /****************************************************************************
6184 ****************************************************************************/
6185 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6186 const SPOOL_PRINTER_INFO_LEVEL *info)
6189 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6191 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6193 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6198 if (!get_printer_snum(p, handle, &snum))
6201 nt_printer_publish(Printer, snum, info7->action);
6205 return WERR_UNKNOWN_LEVEL;
6208 /****************************************************************************
6209 ****************************************************************************/
6211 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6213 POLICY_HND *handle = &q_u->handle;
6214 uint32 level = q_u->level;
6215 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6216 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6217 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6218 uint32 command = q_u->command;
6220 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6223 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6227 /* check the level */
6230 return control_printer(handle, command, p);
6232 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6234 return update_printer_sec(handle, level, info, p,
6237 return publish_or_unpublish_printer(p, handle, info);
6239 return WERR_UNKNOWN_LEVEL;
6243 /****************************************************************************
6244 ****************************************************************************/
6246 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6248 POLICY_HND *handle = &q_u->handle;
6249 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6252 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6256 if (Printer->notify.client_connected==True) {
6259 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6261 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6262 !get_printer_snum(p, handle, &snum) )
6265 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6268 Printer->notify.flags=0;
6269 Printer->notify.options=0;
6270 Printer->notify.localmachine[0]='\0';
6271 Printer->notify.printerlocal=0;
6272 if (Printer->notify.option)
6273 free_spool_notify_option(&Printer->notify.option);
6274 Printer->notify.client_connected=False;
6279 /****************************************************************************
6280 ****************************************************************************/
6282 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6284 /* that's an [in out] buffer (despite appearences to the contrary) */
6285 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6288 return WERR_INVALID_PARAM; /* this is what a NT server
6289 returns for AddJob. AddJob
6290 must fail on non-local
6294 /****************************************************************************
6295 ****************************************************************************/
6297 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6298 int position, int snum)
6304 t=gmtime(&queue->time);
6305 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6307 job_info->jobid=queue->job;
6308 init_unistr(&job_info->printername, lp_servicename(snum));
6309 init_unistr(&job_info->machinename, temp_name);
6310 init_unistr(&job_info->username, queue->fs_user);
6311 init_unistr(&job_info->document, queue->fs_file);
6312 init_unistr(&job_info->datatype, "RAW");
6313 init_unistr(&job_info->text_status, "");
6314 job_info->status=nt_printj_status(queue->status);
6315 job_info->priority=queue->priority;
6316 job_info->position=position;
6317 job_info->totalpages=queue->page_count;
6318 job_info->pagesprinted=0;
6320 make_systemtime(&job_info->submitted, t);
6323 /****************************************************************************
6324 ****************************************************************************/
6326 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6327 int position, int snum,
6328 NT_PRINTER_INFO_LEVEL *ntprinter,
6329 DEVICEMODE *devmode)
6334 t=gmtime(&queue->time);
6335 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6337 job_info->jobid=queue->job;
6339 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6341 init_unistr(&job_info->machinename, temp_name);
6342 init_unistr(&job_info->username, queue->fs_user);
6343 init_unistr(&job_info->document, queue->fs_file);
6344 init_unistr(&job_info->notifyname, queue->fs_user);
6345 init_unistr(&job_info->datatype, "RAW");
6346 init_unistr(&job_info->printprocessor, "winprint");
6347 init_unistr(&job_info->parameters, "");
6348 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6349 init_unistr(&job_info->text_status, "");
6351 /* and here the security descriptor */
6353 job_info->status=nt_printj_status(queue->status);
6354 job_info->priority=queue->priority;
6355 job_info->position=position;
6356 job_info->starttime=0;
6357 job_info->untiltime=0;
6358 job_info->totalpages=queue->page_count;
6359 job_info->size=queue->size;
6360 make_systemtime(&(job_info->submitted), t);
6361 job_info->timeelapsed=0;
6362 job_info->pagesprinted=0;
6364 job_info->devmode = devmode;
6369 /****************************************************************************
6370 Enumjobs at level 1.
6371 ****************************************************************************/
6373 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6374 NEW_BUFFER *buffer, uint32 offered,
6375 uint32 *needed, uint32 *returned)
6380 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6387 for (i=0; i<*returned; i++)
6388 fill_job_info_1(&info[i], &queue[i], i, snum);
6392 /* check the required size. */
6393 for (i=0; i<*returned; i++)
6394 (*needed) += spoolss_size_job_info_1(&info[i]);
6396 if (!alloc_buffer_size(buffer, *needed)) {
6398 return WERR_INSUFFICIENT_BUFFER;
6401 /* fill the buffer with the structures */
6402 for (i=0; i<*returned; i++)
6403 smb_io_job_info_1("", buffer, &info[i], 0);
6408 if (*needed > offered) {
6410 return WERR_INSUFFICIENT_BUFFER;
6416 /****************************************************************************
6417 Enumjobs at level 2.
6418 ****************************************************************************/
6420 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6421 NEW_BUFFER *buffer, uint32 offered,
6422 uint32 *needed, uint32 *returned)
6424 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6425 JOB_INFO_2 *info = NULL;
6428 DEVICEMODE *devmode = NULL;
6430 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6433 result = WERR_NOMEM;
6437 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6438 if (!W_ERROR_IS_OK(result)) {
6443 /* this should not be a failure condition if the devmode is NULL */
6445 devmode = construct_dev_mode(snum);
6447 for (i=0; i<*returned; i++)
6448 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6451 free_a_printer(&ntprinter, 2);
6454 /* check the required size. */
6455 for (i=0; i<*returned; i++)
6456 (*needed) += spoolss_size_job_info_2(&info[i]);
6458 if (*needed > offered) {
6460 result = WERR_INSUFFICIENT_BUFFER;
6464 if (!alloc_buffer_size(buffer, *needed)) {
6466 result = WERR_INSUFFICIENT_BUFFER;
6470 /* fill the buffer with the structures */
6471 for (i=0; i<*returned; i++)
6472 smb_io_job_info_2("", buffer, &info[i], 0);
6477 free_a_printer(&ntprinter, 2);
6478 free_devmode(devmode);
6486 /****************************************************************************
6488 ****************************************************************************/
6490 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6492 POLICY_HND *handle = &q_u->handle;
6493 uint32 level = q_u->level;
6494 NEW_BUFFER *buffer = NULL;
6495 uint32 offered = q_u->offered;
6496 uint32 *needed = &r_u->needed;
6497 uint32 *returned = &r_u->returned;
6501 print_status_struct prt_status;
6502 print_queue_struct *queue=NULL;
6504 /* that's an [in out] buffer */
6505 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6506 buffer = r_u->buffer;
6508 DEBUG(4,("_spoolss_enumjobs\n"));
6513 if (!get_printer_snum(p, handle, &snum))
6516 *returned = print_queue_status(snum, &queue, &prt_status);
6517 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6519 if (*returned == 0) {
6520 set_enumjobs_timestamp(snum);
6527 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6528 set_enumjobs_timestamp(snum);
6531 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6532 set_enumjobs_timestamp(snum);
6537 return WERR_UNKNOWN_LEVEL;
6541 /****************************************************************************
6542 ****************************************************************************/
6544 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6549 /****************************************************************************
6550 ****************************************************************************/
6552 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6554 POLICY_HND *handle = &q_u->handle;
6555 uint32 jobid = q_u->jobid;
6556 uint32 command = q_u->command;
6558 struct current_user user;
6560 WERROR errcode = WERR_BADFUNC;
6562 if (!get_printer_snum(p, handle, &snum)) {
6566 if (!print_job_exists(snum, jobid)) {
6567 return WERR_INVALID_PRINTER_NAME;
6570 get_current_user(&user, p);
6573 case JOB_CONTROL_CANCEL:
6574 case JOB_CONTROL_DELETE:
6575 if (print_job_delete(&user, snum, jobid, &errcode)) {
6579 case JOB_CONTROL_PAUSE:
6580 if (print_job_pause(&user, snum, jobid, &errcode)) {
6584 case JOB_CONTROL_RESTART:
6585 case JOB_CONTROL_RESUME:
6586 if (print_job_resume(&user, snum, jobid, &errcode)) {
6591 return WERR_UNKNOWN_LEVEL;
6597 /****************************************************************************
6598 Enumerates all printer drivers at level 1.
6599 ****************************************************************************/
6601 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6606 fstring *list = NULL;
6608 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6609 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6613 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6615 ndrivers=get_ntdrivers(&list, architecture, version);
6616 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6622 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6623 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6624 SAFE_FREE(driver_info_1);
6628 else driver_info_1 = tdi1;
6631 for (i=0; i<ndrivers; i++) {
6633 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6634 ZERO_STRUCT(driver);
6635 status = get_a_printer_driver(&driver, 3, list[i],
6636 architecture, version);
6637 if (!W_ERROR_IS_OK(status)) {
6641 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6642 free_a_printer_driver(driver, 3);
6645 *returned+=ndrivers;
6649 /* check the required size. */
6650 for (i=0; i<*returned; i++) {
6651 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6652 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6655 if (!alloc_buffer_size(buffer, *needed)) {
6656 SAFE_FREE(driver_info_1);
6657 return WERR_INSUFFICIENT_BUFFER;
6660 /* fill the buffer with the driver structures */
6661 for (i=0; i<*returned; i++) {
6662 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6663 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6666 SAFE_FREE(driver_info_1);
6668 if (*needed > offered) {
6670 return WERR_INSUFFICIENT_BUFFER;
6676 /****************************************************************************
6677 Enumerates all printer drivers at level 2.
6678 ****************************************************************************/
6680 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6685 fstring *list = NULL;
6687 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6688 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6692 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6694 ndrivers=get_ntdrivers(&list, architecture, version);
6695 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6701 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6702 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6703 SAFE_FREE(driver_info_2);
6707 else driver_info_2 = tdi2;
6710 for (i=0; i<ndrivers; i++) {
6713 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6714 ZERO_STRUCT(driver);
6715 status = get_a_printer_driver(&driver, 3, list[i],
6716 architecture, version);
6717 if (!W_ERROR_IS_OK(status)) {
6721 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6722 free_a_printer_driver(driver, 3);
6725 *returned+=ndrivers;
6729 /* check the required size. */
6730 for (i=0; i<*returned; i++) {
6731 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6732 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6735 if (!alloc_buffer_size(buffer, *needed)) {
6736 SAFE_FREE(driver_info_2);
6737 return WERR_INSUFFICIENT_BUFFER;
6740 /* fill the buffer with the form structures */
6741 for (i=0; i<*returned; i++) {
6742 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6743 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6746 SAFE_FREE(driver_info_2);
6748 if (*needed > offered) {
6750 return WERR_INSUFFICIENT_BUFFER;
6756 /****************************************************************************
6757 Enumerates all printer drivers at level 3.
6758 ****************************************************************************/
6760 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6765 fstring *list = NULL;
6767 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6768 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6772 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6774 ndrivers=get_ntdrivers(&list, architecture, version);
6775 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6781 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6782 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6783 SAFE_FREE(driver_info_3);
6787 else driver_info_3 = tdi3;
6790 for (i=0; i<ndrivers; i++) {
6793 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6794 ZERO_STRUCT(driver);
6795 status = get_a_printer_driver(&driver, 3, list[i],
6796 architecture, version);
6797 if (!W_ERROR_IS_OK(status)) {
6801 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6802 free_a_printer_driver(driver, 3);
6805 *returned+=ndrivers;
6809 /* check the required size. */
6810 for (i=0; i<*returned; i++) {
6811 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6812 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6815 if (!alloc_buffer_size(buffer, *needed)) {
6816 SAFE_FREE(driver_info_3);
6817 return WERR_INSUFFICIENT_BUFFER;
6820 /* fill the buffer with the driver structures */
6821 for (i=0; i<*returned; i++) {
6822 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6823 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6826 for (i=0; i<*returned; i++)
6827 SAFE_FREE(driver_info_3[i].dependentfiles);
6829 SAFE_FREE(driver_info_3);
6831 if (*needed > offered) {
6833 return WERR_INSUFFICIENT_BUFFER;
6839 /****************************************************************************
6840 Enumerates all printer drivers.
6841 ****************************************************************************/
6843 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6845 UNISTR2 *environment = &q_u->environment;
6846 uint32 level = q_u->level;
6847 NEW_BUFFER *buffer = NULL;
6848 uint32 offered = q_u->offered;
6849 uint32 *needed = &r_u->needed;
6850 uint32 *returned = &r_u->returned;
6852 fstring *list = NULL;
6854 fstring architecture;
6856 /* that's an [in out] buffer */
6857 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6858 buffer = r_u->buffer;
6860 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6861 fstrcpy(servername, get_called_name());
6865 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6869 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6871 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6873 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6877 return WERR_UNKNOWN_LEVEL;
6881 /****************************************************************************
6882 ****************************************************************************/
6884 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6886 form->flag=list->flag;
6887 init_unistr(&form->name, list->name);
6888 form->width=list->width;
6889 form->length=list->length;
6890 form->left=list->left;
6891 form->top=list->top;
6892 form->right=list->right;
6893 form->bottom=list->bottom;
6896 /****************************************************************************
6897 ****************************************************************************/
6899 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6901 uint32 level = q_u->level;
6902 NEW_BUFFER *buffer = NULL;
6903 uint32 offered = q_u->offered;
6904 uint32 *needed = &r_u->needed;
6905 uint32 *numofforms = &r_u->numofforms;
6906 uint32 numbuiltinforms;
6908 nt_forms_struct *list=NULL;
6909 nt_forms_struct *builtinlist=NULL;
6914 /* that's an [in out] buffer */
6915 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6916 buffer = r_u->buffer;
6918 DEBUG(4,("_spoolss_enumforms\n"));
6919 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6920 DEBUGADD(5,("Info level [%d]\n", level));
6922 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6923 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6924 *numofforms = get_ntforms(&list);
6925 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6926 *numofforms += numbuiltinforms;
6928 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6932 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6937 /* construct the list of form structures */
6938 for (i=0; i<numbuiltinforms; i++) {
6939 DEBUGADD(6,("Filling form number [%d]\n",i));
6940 fill_form_1(&forms_1[i], &builtinlist[i]);
6943 SAFE_FREE(builtinlist);
6945 for (; i<*numofforms; i++) {
6946 DEBUGADD(6,("Filling form number [%d]\n",i));
6947 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6952 /* check the required size. */
6953 for (i=0; i<numbuiltinforms; i++) {
6954 DEBUGADD(6,("adding form [%d]'s size\n",i));
6955 buffer_size += spoolss_size_form_1(&forms_1[i]);
6957 for (; i<*numofforms; i++) {
6958 DEBUGADD(6,("adding form [%d]'s size\n",i));
6959 buffer_size += spoolss_size_form_1(&forms_1[i]);
6962 *needed=buffer_size;
6964 if (!alloc_buffer_size(buffer, buffer_size)){
6966 return WERR_INSUFFICIENT_BUFFER;
6969 /* fill the buffer with the form structures */
6970 for (i=0; i<numbuiltinforms; i++) {
6971 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6972 smb_io_form_1("", buffer, &forms_1[i], 0);
6974 for (; i<*numofforms; i++) {
6975 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6976 smb_io_form_1("", buffer, &forms_1[i], 0);
6981 if (*needed > offered) {
6983 return WERR_INSUFFICIENT_BUFFER;
6990 SAFE_FREE(builtinlist);
6991 return WERR_UNKNOWN_LEVEL;
6996 /****************************************************************************
6997 ****************************************************************************/
6999 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7001 uint32 level = q_u->level;
7002 UNISTR2 *uni_formname = &q_u->formname;
7003 NEW_BUFFER *buffer = NULL;
7004 uint32 offered = q_u->offered;
7005 uint32 *needed = &r_u->needed;
7007 nt_forms_struct *list=NULL;
7008 nt_forms_struct builtin_form;
7013 int numofforms=0, i=0;
7015 /* that's an [in out] buffer */
7016 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7017 buffer = r_u->buffer;
7019 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7021 DEBUG(4,("_spoolss_getform\n"));
7022 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7023 DEBUGADD(5,("Info level [%d]\n", level));
7025 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7026 if (!foundBuiltin) {
7027 numofforms = get_ntforms(&list);
7028 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7030 if (numofforms == 0)
7037 fill_form_1(&form_1, &builtin_form);
7040 /* Check if the requested name is in the list of form structures */
7041 for (i=0; i<numofforms; i++) {
7043 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7045 if (strequal(form_name, list[i].name)) {
7046 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7047 fill_form_1(&form_1, &list[i]);
7053 if (i == numofforms) {
7057 /* check the required size. */
7059 *needed=spoolss_size_form_1(&form_1);
7061 if (!alloc_buffer_size(buffer, buffer_size)){
7062 return WERR_INSUFFICIENT_BUFFER;
7065 if (*needed > offered) {
7066 return WERR_INSUFFICIENT_BUFFER;
7069 /* fill the buffer with the form structures */
7070 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7071 smb_io_form_1("", buffer, &form_1, 0);
7077 return WERR_UNKNOWN_LEVEL;
7081 /****************************************************************************
7082 ****************************************************************************/
7084 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7086 init_unistr(&port->port_name, name);
7089 /****************************************************************************
7090 ****************************************************************************/
7092 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7094 init_unistr(&port->port_name, name);
7095 init_unistr(&port->monitor_name, "Local Monitor");
7096 init_unistr(&port->description, "Local Port");
7097 port->port_type=PORT_TYPE_WRITE;
7101 /****************************************************************************
7103 ****************************************************************************/
7105 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7107 PORT_INFO_1 *ports=NULL;
7110 if (*lp_enumports_cmd()) {
7111 char *cmd = lp_enumports_cmd();
7118 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7120 DEBUG(10,("Running [%s]\n", command));
7121 ret = smbrun(command, &fd);
7122 DEBUG(10,("Returned [%d]\n", ret));
7126 /* Is this the best error to return here? */
7127 return WERR_ACCESS_DENIED;
7131 qlines = fd_lines_load(fd, &numlines);
7132 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7136 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7137 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7138 dos_errstr(WERR_NOMEM)));
7139 file_lines_free(qlines);
7143 for (i=0; i<numlines; i++) {
7144 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7145 fill_port_1(&ports[i], qlines[i]);
7148 file_lines_free(qlines);
7151 *returned = numlines;
7154 *returned = 1; /* Sole Samba port returned. */
7156 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7159 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7161 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7164 /* check the required size. */
7165 for (i=0; i<*returned; i++) {
7166 DEBUGADD(6,("adding port [%d]'s size\n", i));
7167 *needed += spoolss_size_port_info_1(&ports[i]);
7170 if (!alloc_buffer_size(buffer, *needed)) {
7172 return WERR_INSUFFICIENT_BUFFER;
7175 /* fill the buffer with the ports structures */
7176 for (i=0; i<*returned; i++) {
7177 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7178 smb_io_port_1("", buffer, &ports[i], 0);
7183 if (*needed > offered) {
7185 return WERR_INSUFFICIENT_BUFFER;
7191 /****************************************************************************
7193 ****************************************************************************/
7195 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7197 PORT_INFO_2 *ports=NULL;
7200 if (*lp_enumports_cmd()) {
7201 char *cmd = lp_enumports_cmd();
7210 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7211 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7213 path = lp_lockdir();
7215 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7216 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7219 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7220 ret = smbrun(command, &fd);
7221 DEBUGADD(10,("returned [%d]\n", ret));
7225 /* Is this the best error to return here? */
7226 return WERR_ACCESS_DENIED;
7230 qlines = fd_lines_load(fd, &numlines);
7231 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7235 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7236 file_lines_free(qlines);
7240 for (i=0; i<numlines; i++) {
7241 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7242 fill_port_2(&(ports[i]), qlines[i]);
7245 file_lines_free(qlines);
7248 *returned = numlines;
7254 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7257 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7259 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7262 /* check the required size. */
7263 for (i=0; i<*returned; i++) {
7264 DEBUGADD(6,("adding port [%d]'s size\n", i));
7265 *needed += spoolss_size_port_info_2(&ports[i]);
7268 if (!alloc_buffer_size(buffer, *needed)) {
7270 return WERR_INSUFFICIENT_BUFFER;
7273 /* fill the buffer with the ports structures */
7274 for (i=0; i<*returned; i++) {
7275 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7276 smb_io_port_2("", buffer, &ports[i], 0);
7281 if (*needed > offered) {
7283 return WERR_INSUFFICIENT_BUFFER;
7289 /****************************************************************************
7291 ****************************************************************************/
7293 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7295 uint32 level = q_u->level;
7296 NEW_BUFFER *buffer = NULL;
7297 uint32 offered = q_u->offered;
7298 uint32 *needed = &r_u->needed;
7299 uint32 *returned = &r_u->returned;
7301 /* that's an [in out] buffer */
7302 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7303 buffer = r_u->buffer;
7305 DEBUG(4,("_spoolss_enumports\n"));
7312 return enumports_level_1(buffer, offered, needed, returned);
7314 return enumports_level_2(buffer, offered, needed, returned);
7316 return WERR_UNKNOWN_LEVEL;
7320 /****************************************************************************
7321 ****************************************************************************/
7323 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7324 const SPOOL_PRINTER_INFO_LEVEL *info,
7325 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7326 uint32 user_switch, const SPOOL_USER_CTR *user,
7329 NT_PRINTER_INFO_LEVEL *printer = NULL;
7332 WERROR err = WERR_OK;
7334 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7335 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7339 ZERO_STRUCTP(printer);
7341 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7342 if (!convert_printer_info(info, printer, 2)) {
7343 free_a_printer(&printer, 2);
7347 /* check to see if the printer already exists */
7349 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7350 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7351 printer->info_2->sharename));
7352 free_a_printer(&printer, 2);
7353 return WERR_PRINTER_ALREADY_EXISTS;
7356 /* FIXME!!! smbd should check to see if the driver is installed before
7357 trying to add a printer like this --jerry */
7359 if (*lp_addprinter_cmd() ) {
7360 if ( !add_printer_hook(printer) ) {
7361 free_a_printer(&printer,2);
7362 return WERR_ACCESS_DENIED;
7366 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7367 printer->info_2->sharename);
7370 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7371 free_a_printer(&printer,2);
7372 return WERR_ACCESS_DENIED;
7375 /* you must be a printer admin to add a new printer */
7376 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7377 free_a_printer(&printer,2);
7378 return WERR_ACCESS_DENIED;
7382 * Do sanity check on the requested changes for Samba.
7385 if (!check_printer_ok(printer->info_2, snum)) {
7386 free_a_printer(&printer,2);
7387 return WERR_INVALID_PARAM;
7391 * When a printer is created, the drivername bound to the printer is used
7392 * to lookup previously saved driver initialization info, which is then
7393 * bound to the new printer, simulating what happens in the Windows arch.
7398 set_driver_init(printer, 2);
7402 /* A valid devmode was included, convert and link it
7404 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7406 if (!convert_devicemode(printer->info_2->printername, devmode,
7407 &printer->info_2->devmode))
7411 /* write the ASCII on disk */
7412 err = mod_a_printer(*printer, 2);
7413 if (!W_ERROR_IS_OK(err)) {
7414 free_a_printer(&printer,2);
7418 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7419 /* Handle open failed - remove addition. */
7420 del_a_printer(printer->info_2->sharename);
7421 free_a_printer(&printer,2);
7422 return WERR_ACCESS_DENIED;
7425 update_c_setprinter(False);
7426 free_a_printer(&printer,2);
7431 /****************************************************************************
7432 ****************************************************************************/
7434 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7436 UNISTR2 *uni_srv_name = &q_u->server_name;
7437 uint32 level = q_u->level;
7438 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7439 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7440 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7441 uint32 user_switch = q_u->user_switch;
7442 SPOOL_USER_CTR *user = &q_u->user_ctr;
7443 POLICY_HND *handle = &r_u->handle;
7447 /* we don't handle yet */
7448 /* but I know what to do ... */
7449 return WERR_UNKNOWN_LEVEL;
7451 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7453 user_switch, user, handle);
7455 return WERR_UNKNOWN_LEVEL;
7459 /****************************************************************************
7460 ****************************************************************************/
7462 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7464 uint32 level = q_u->level;
7465 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7466 WERROR err = WERR_OK;
7467 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7468 struct current_user user;
7469 fstring driver_name;
7472 ZERO_STRUCT(driver);
7474 get_current_user(&user, p);
7476 if (!convert_printer_driver_info(info, &driver, level)) {
7481 DEBUG(5,("Cleaning driver's information\n"));
7482 err = clean_up_driver_struct(driver, level, &user);
7483 if (!W_ERROR_IS_OK(err))
7486 DEBUG(5,("Moving driver to final destination\n"));
7487 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7488 if (W_ERROR_IS_OK(err))
7489 err = WERR_ACCESS_DENIED;
7493 if (add_a_printer_driver(driver, level)!=0) {
7494 err = WERR_ACCESS_DENIED;
7498 /* BEGIN_ADMIN_LOG */
7501 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7502 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7503 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7506 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7507 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7508 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7514 * I think this is where he DrvUpgradePrinter() hook would be
7515 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7516 * server. Right now, we just need to send ourselves a message
7517 * to update each printer bound to this driver. --jerry
7520 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7521 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7526 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7527 * decide if the driver init data should be deleted. The rules are:
7528 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7529 * 2) delete init data only if there is no 2k/Xp driver
7530 * 3) always delete init data
7531 * The generalized rule is always use init data from the highest order driver.
7532 * It is necessary to follow the driver install by an initialization step to
7533 * finish off this process.
7536 version = driver.info_3->cversion;
7537 else if (level == 6)
7538 version = driver.info_6->version;
7543 * 9x printer driver - never delete init data
7546 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7551 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7552 * there is no 2k/Xp driver init data for this driver name.
7556 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7558 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7560 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7562 if (!del_driver_init(driver_name))
7563 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7566 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7568 free_a_printer_driver(driver1,3);
7569 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7576 * 2k or Xp printer driver - always delete init data
7579 if (!del_driver_init(driver_name))
7580 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7584 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7590 free_a_printer_driver(driver, level);
7594 /********************************************************************
7595 * spoolss_addprinterdriverex
7596 ********************************************************************/
7598 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7600 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7601 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7604 * we only support the semantics of AddPrinterDriver()
7605 * i.e. only copy files that are newer than existing ones
7608 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7609 return WERR_ACCESS_DENIED;
7611 ZERO_STRUCT(q_u_local);
7612 ZERO_STRUCT(r_u_local);
7614 /* just pass the information off to _spoolss_addprinterdriver() */
7615 q_u_local.server_name_ptr = q_u->server_name_ptr;
7616 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7617 q_u_local.level = q_u->level;
7618 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7620 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7623 /****************************************************************************
7624 ****************************************************************************/
7626 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7628 init_unistr(&info->name, name);
7631 /****************************************************************************
7632 ****************************************************************************/
7634 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7638 const char *short_archi;
7639 DRIVER_DIRECTORY_1 *info=NULL;
7641 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7643 if (!(short_archi = get_short_archi(long_archi)))
7644 return WERR_INVALID_ENVIRONMENT;
7646 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7649 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7651 DEBUG(4,("printer driver directory: [%s]\n", path));
7653 fill_driverdir_1(info, path);
7655 *needed += spoolss_size_driverdir_info_1(info);
7657 if (!alloc_buffer_size(buffer, *needed)) {
7659 return WERR_INSUFFICIENT_BUFFER;
7662 smb_io_driverdir_1("", buffer, info, 0);
7666 if (*needed > offered)
7667 return WERR_INSUFFICIENT_BUFFER;
7672 /****************************************************************************
7673 ****************************************************************************/
7675 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7677 UNISTR2 *name = &q_u->name;
7678 UNISTR2 *uni_environment = &q_u->environment;
7679 uint32 level = q_u->level;
7680 NEW_BUFFER *buffer = NULL;
7681 uint32 offered = q_u->offered;
7682 uint32 *needed = &r_u->needed;
7684 /* that's an [in out] buffer */
7685 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7686 buffer = r_u->buffer;
7688 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7694 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7696 return WERR_UNKNOWN_LEVEL;
7700 /****************************************************************************
7701 ****************************************************************************/
7703 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7705 POLICY_HND *handle = &q_u->handle;
7706 uint32 idx = q_u->index;
7707 uint32 in_value_len = q_u->valuesize;
7708 uint32 in_data_len = q_u->datasize;
7709 uint32 *out_max_value_len = &r_u->valuesize;
7710 uint16 **out_value = &r_u->value;
7711 uint32 *out_value_len = &r_u->realvaluesize;
7712 uint32 *out_type = &r_u->type;
7713 uint32 *out_max_data_len = &r_u->datasize;
7714 uint8 **data_out = &r_u->data;
7715 uint32 *out_data_len = &r_u->realdatasize;
7717 NT_PRINTER_INFO_LEVEL *printer = NULL;
7719 uint32 biggest_valuesize;
7720 uint32 biggest_datasize;
7722 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7725 REGISTRY_VALUE *val = NULL;
7726 NT_PRINTER_DATA *p_data;
7727 int i, key_index, num_values;
7730 ZERO_STRUCT( printer );
7734 *out_max_data_len = 0;
7738 DEBUG(5,("spoolss_enumprinterdata\n"));
7741 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7745 if (!get_printer_snum(p,handle, &snum))
7748 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7749 if (!W_ERROR_IS_OK(result))
7752 p_data = &printer->info_2->data;
7753 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7758 * The NT machine wants to know the biggest size of value and data
7760 * cf: MSDN EnumPrinterData remark section
7763 if ( !in_value_len && !in_data_len && (key_index != -1) )
7765 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7767 biggest_valuesize = 0;
7768 biggest_datasize = 0;
7770 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7772 for ( i=0; i<num_values; i++ )
7774 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7776 name_length = strlen(val->valuename);
7777 if ( strlen(val->valuename) > biggest_valuesize )
7778 biggest_valuesize = name_length;
7780 if ( val->size > biggest_datasize )
7781 biggest_datasize = val->size;
7783 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7787 /* the value is an UNICODE string but real_value_size is the length
7788 in bytes including the trailing 0 */
7790 *out_value_len = 2 * (1+biggest_valuesize);
7791 *out_data_len = biggest_datasize;
7793 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7799 * the value len is wrong in NT sp3
7800 * that's the number of bytes not the number of unicode chars
7803 if ( key_index != -1 )
7804 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7809 /* out_value should default to "" or else NT4 has
7810 problems unmarshalling the response */
7812 *out_max_value_len=(in_value_len/sizeof(uint16));
7814 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7816 result = WERR_NOMEM;
7820 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7822 /* the data is counted in bytes */
7824 *out_max_data_len = in_data_len;
7825 *out_data_len = in_data_len;
7827 /* only allocate when given a non-zero data_len */
7829 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7831 result = WERR_NOMEM;
7835 result = WERR_NO_MORE_ITEMS;
7841 * - counted in bytes in the request
7842 * - counted in UNICODE chars in the max reply
7843 * - counted in bytes in the real size
7845 * take a pause *before* coding not *during* coding
7849 *out_max_value_len=(in_value_len/sizeof(uint16));
7850 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7852 result = WERR_NOMEM;
7856 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7860 *out_type = regval_type( val );
7862 /* data - counted in bytes */
7864 *out_max_data_len = in_data_len;
7865 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7867 result = WERR_NOMEM;
7870 data_len = (size_t)regval_size(val);
7871 memcpy( *data_out, regval_data_p(val), data_len );
7872 *out_data_len = data_len;
7876 free_a_printer(&printer, 2);
7880 /****************************************************************************
7881 ****************************************************************************/
7883 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7885 POLICY_HND *handle = &q_u->handle;
7886 UNISTR2 *value = &q_u->value;
7887 uint32 type = q_u->type;
7888 uint8 *data = q_u->data;
7889 uint32 real_len = q_u->real_len;
7891 NT_PRINTER_INFO_LEVEL *printer = NULL;
7893 WERROR status = WERR_OK;
7894 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7897 DEBUG(5,("spoolss_setprinterdata\n"));
7900 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7904 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7905 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7906 return WERR_INVALID_PARAM;
7909 if (!get_printer_snum(p,handle, &snum))
7913 * Access check : NT returns "access denied" if you make a
7914 * SetPrinterData call without the necessary privildge.
7915 * we were originally returning OK if nothing changed
7916 * which made Win2k issue **a lot** of SetPrinterData
7917 * when connecting to a printer --jerry
7920 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7922 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7923 status = WERR_ACCESS_DENIED;
7927 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7928 if (!W_ERROR_IS_OK(status))
7931 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7934 * When client side code sets a magic printer data key, detect it and save
7935 * the current printer data and the magic key's data (its the DEVMODE) for
7936 * future printer/driver initializations.
7938 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7940 /* Set devmode and printer initialization info */
7941 status = save_driver_init( printer, 2, data, real_len );
7943 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7947 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7948 type, data, real_len );
7949 if ( W_ERROR_IS_OK(status) )
7950 status = mod_a_printer(*printer, 2);
7954 free_a_printer(&printer, 2);
7959 /****************************************************************************
7960 ****************************************************************************/
7962 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7964 POLICY_HND *handle = &q_u->handle;
7965 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7968 DEBUG(5,("_spoolss_resetprinter\n"));
7971 * All we do is to check to see if the handle and queue is valid.
7972 * This call really doesn't mean anything to us because we only
7973 * support RAW printing. --jerry
7977 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7981 if (!get_printer_snum(p,handle, &snum))
7985 /* blindly return success */
7990 /****************************************************************************
7991 ****************************************************************************/
7993 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7995 POLICY_HND *handle = &q_u->handle;
7996 UNISTR2 *value = &q_u->valuename;
7998 NT_PRINTER_INFO_LEVEL *printer = NULL;
8000 WERROR status = WERR_OK;
8001 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8004 DEBUG(5,("spoolss_deleteprinterdata\n"));
8007 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8011 if (!get_printer_snum(p, handle, &snum))
8014 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8015 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8016 return WERR_ACCESS_DENIED;
8019 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8020 if (!W_ERROR_IS_OK(status))
8023 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8025 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8027 if ( W_ERROR_IS_OK(status) )
8028 mod_a_printer( *printer, 2 );
8030 free_a_printer(&printer, 2);
8035 /****************************************************************************
8036 ****************************************************************************/
8038 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8040 POLICY_HND *handle = &q_u->handle;
8041 FORM *form = &q_u->form;
8042 nt_forms_struct tmpForm;
8044 WERROR status = WERR_OK;
8045 NT_PRINTER_INFO_LEVEL *printer = NULL;
8048 nt_forms_struct *list=NULL;
8049 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8051 DEBUG(5,("spoolss_addform\n"));
8054 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8059 /* forms can be added on printer of on the print server handle */
8061 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8063 if (!get_printer_snum(p,handle, &snum))
8066 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8067 if (!W_ERROR_IS_OK(status))
8071 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8072 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8073 status = WERR_ACCESS_DENIED;
8077 /* can't add if builtin */
8079 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8080 status = WERR_ALREADY_EXISTS;
8084 count = get_ntforms(&list);
8086 if(!add_a_form(&list, form, &count)) {
8087 status = WERR_NOMEM;
8091 write_ntforms(&list, count);
8094 * ChangeID must always be set if this is a printer
8097 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8098 status = mod_a_printer(*printer, 2);
8102 free_a_printer(&printer, 2);
8108 /****************************************************************************
8109 ****************************************************************************/
8111 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8113 POLICY_HND *handle = &q_u->handle;
8114 UNISTR2 *form_name = &q_u->name;
8115 nt_forms_struct tmpForm;
8117 nt_forms_struct *list=NULL;
8118 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8120 WERROR status = WERR_OK;
8121 NT_PRINTER_INFO_LEVEL *printer = NULL;
8123 DEBUG(5,("spoolss_deleteform\n"));
8126 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8130 /* forms can be deleted on printer of on the print server handle */
8132 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8134 if (!get_printer_snum(p,handle, &snum))
8137 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8138 if (!W_ERROR_IS_OK(status))
8142 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8143 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8144 status = WERR_ACCESS_DENIED;
8148 /* can't delete if builtin */
8150 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8151 status = WERR_INVALID_PARAM;
8155 count = get_ntforms(&list);
8157 if ( !delete_a_form(&list, form_name, &count, &status ))
8161 * ChangeID must always be set if this is a printer
8164 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8165 status = mod_a_printer(*printer, 2);
8169 free_a_printer(&printer, 2);
8175 /****************************************************************************
8176 ****************************************************************************/
8178 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8180 POLICY_HND *handle = &q_u->handle;
8181 FORM *form = &q_u->form;
8182 nt_forms_struct tmpForm;
8184 WERROR status = WERR_OK;
8185 NT_PRINTER_INFO_LEVEL *printer = NULL;
8188 nt_forms_struct *list=NULL;
8189 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8191 DEBUG(5,("spoolss_setform\n"));
8194 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8198 /* forms can be modified on printer of on the print server handle */
8200 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8202 if (!get_printer_snum(p,handle, &snum))
8205 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8206 if (!W_ERROR_IS_OK(status))
8210 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8211 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8212 status = WERR_ACCESS_DENIED;
8216 /* can't set if builtin */
8217 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8218 status = WERR_INVALID_PARAM;
8222 count = get_ntforms(&list);
8223 update_a_form(&list, form, count);
8224 write_ntforms(&list, count);
8227 * ChangeID must always be set if this is a printer
8230 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8231 status = mod_a_printer(*printer, 2);
8236 free_a_printer(&printer, 2);
8242 /****************************************************************************
8243 enumprintprocessors level 1.
8244 ****************************************************************************/
8246 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8248 PRINTPROCESSOR_1 *info_1=NULL;
8250 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8255 init_unistr(&info_1->name, "winprint");
8257 *needed += spoolss_size_printprocessor_info_1(info_1);
8259 if (!alloc_buffer_size(buffer, *needed))
8260 return WERR_INSUFFICIENT_BUFFER;
8262 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8266 if (*needed > offered) {
8268 return WERR_INSUFFICIENT_BUFFER;
8274 /****************************************************************************
8275 ****************************************************************************/
8277 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8279 uint32 level = q_u->level;
8280 NEW_BUFFER *buffer = NULL;
8281 uint32 offered = q_u->offered;
8282 uint32 *needed = &r_u->needed;
8283 uint32 *returned = &r_u->returned;
8285 /* that's an [in out] buffer */
8286 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8287 buffer = r_u->buffer;
8289 DEBUG(5,("spoolss_enumprintprocessors\n"));
8292 * Enumerate the print processors ...
8294 * Just reply with "winprint", to keep NT happy
8295 * and I can use my nice printer checker.
8303 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8305 return WERR_UNKNOWN_LEVEL;
8309 /****************************************************************************
8310 enumprintprocdatatypes level 1.
8311 ****************************************************************************/
8313 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8315 PRINTPROCDATATYPE_1 *info_1=NULL;
8317 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8322 init_unistr(&info_1->name, "RAW");
8324 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8326 if (!alloc_buffer_size(buffer, *needed))
8327 return WERR_INSUFFICIENT_BUFFER;
8329 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8333 if (*needed > offered) {
8335 return WERR_INSUFFICIENT_BUFFER;
8341 /****************************************************************************
8342 ****************************************************************************/
8344 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8346 uint32 level = q_u->level;
8347 NEW_BUFFER *buffer = NULL;
8348 uint32 offered = q_u->offered;
8349 uint32 *needed = &r_u->needed;
8350 uint32 *returned = &r_u->returned;
8352 /* that's an [in out] buffer */
8353 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8354 buffer = r_u->buffer;
8356 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8363 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8365 return WERR_UNKNOWN_LEVEL;
8369 /****************************************************************************
8370 enumprintmonitors level 1.
8371 ****************************************************************************/
8373 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8375 PRINTMONITOR_1 *info_1=NULL;
8377 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8382 init_unistr(&info_1->name, "Local Port");
8384 *needed += spoolss_size_printmonitor_info_1(info_1);
8386 if (!alloc_buffer_size(buffer, *needed))
8387 return WERR_INSUFFICIENT_BUFFER;
8389 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8393 if (*needed > offered) {
8395 return WERR_INSUFFICIENT_BUFFER;
8401 /****************************************************************************
8402 enumprintmonitors level 2.
8403 ****************************************************************************/
8405 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8407 PRINTMONITOR_2 *info_2=NULL;
8409 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8414 init_unistr(&info_2->name, "Local Port");
8415 init_unistr(&info_2->environment, "Windows NT X86");
8416 init_unistr(&info_2->dll_name, "localmon.dll");
8418 *needed += spoolss_size_printmonitor_info_2(info_2);
8420 if (!alloc_buffer_size(buffer, *needed))
8421 return WERR_INSUFFICIENT_BUFFER;
8423 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8427 if (*needed > offered) {
8429 return WERR_INSUFFICIENT_BUFFER;
8435 /****************************************************************************
8436 ****************************************************************************/
8438 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8440 uint32 level = q_u->level;
8441 NEW_BUFFER *buffer = NULL;
8442 uint32 offered = q_u->offered;
8443 uint32 *needed = &r_u->needed;
8444 uint32 *returned = &r_u->returned;
8446 /* that's an [in out] buffer */
8447 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8448 buffer = r_u->buffer;
8450 DEBUG(5,("spoolss_enumprintmonitors\n"));
8453 * Enumerate the print monitors ...
8455 * Just reply with "Local Port", to keep NT happy
8456 * and I can use my nice printer checker.
8464 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8466 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8468 return WERR_UNKNOWN_LEVEL;
8472 /****************************************************************************
8473 ****************************************************************************/
8475 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8479 JOB_INFO_1 *info_1=NULL;
8481 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8483 if (info_1 == NULL) {
8487 for (i=0; i<count && found==False; i++) {
8488 if ((*queue)[i].job==(int)jobid)
8494 /* NT treats not found as bad param... yet another bad choice */
8495 return WERR_INVALID_PARAM;
8498 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8500 *needed += spoolss_size_job_info_1(info_1);
8502 if (!alloc_buffer_size(buffer, *needed)) {
8504 return WERR_INSUFFICIENT_BUFFER;
8507 smb_io_job_info_1("", buffer, info_1, 0);
8511 if (*needed > offered)
8512 return WERR_INSUFFICIENT_BUFFER;
8517 /****************************************************************************
8518 ****************************************************************************/
8520 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8525 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8527 DEVICEMODE *devmode = NULL;
8528 NT_DEVICEMODE *nt_devmode = NULL;
8530 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8532 ZERO_STRUCTP(info_2);
8534 if (info_2 == NULL) {
8539 for ( i=0; i<count && found==False; i++ )
8541 if ((*queue)[i].job == (int)jobid)
8547 /* NT treats not found as bad param... yet another bad
8549 ret = WERR_INVALID_PARAM;
8553 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8554 if (!W_ERROR_IS_OK(ret))
8558 * if the print job does not have a DEVMODE associated with it,
8559 * just use the one for the printer. A NULL devicemode is not
8560 * a failure condition
8563 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8564 devmode = construct_dev_mode(snum);
8566 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8567 ZERO_STRUCTP( devmode );
8568 convert_nt_devicemode( devmode, nt_devmode );
8572 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8574 *needed += spoolss_size_job_info_2(info_2);
8576 if (!alloc_buffer_size(buffer, *needed)) {
8577 ret = WERR_INSUFFICIENT_BUFFER;
8581 smb_io_job_info_2("", buffer, info_2, 0);
8583 if (*needed > offered) {
8584 ret = WERR_INSUFFICIENT_BUFFER;
8591 /* Cleanup allocated memory */
8593 free_job_info_2(info_2); /* Also frees devmode */
8595 free_a_printer(&ntprinter, 2);
8600 /****************************************************************************
8601 ****************************************************************************/
8603 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8605 POLICY_HND *handle = &q_u->handle;
8606 uint32 jobid = q_u->jobid;
8607 uint32 level = q_u->level;
8608 NEW_BUFFER *buffer = NULL;
8609 uint32 offered = q_u->offered;
8610 uint32 *needed = &r_u->needed;
8611 WERROR wstatus = WERR_OK;
8615 print_queue_struct *queue = NULL;
8616 print_status_struct prt_status;
8618 /* that's an [in out] buffer */
8619 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8620 buffer = r_u->buffer;
8622 DEBUG(5,("spoolss_getjob\n"));
8626 if (!get_printer_snum(p, handle, &snum))
8629 count = print_queue_status(snum, &queue, &prt_status);
8631 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8632 count, prt_status.status, prt_status.message));
8636 wstatus = getjob_level_1(&queue, count, snum, jobid,
8637 buffer, offered, needed);
8640 wstatus = getjob_level_2(&queue, count, snum, jobid,
8641 buffer, offered, needed);
8644 wstatus = WERR_UNKNOWN_LEVEL;
8652 /********************************************************************
8653 spoolss_getprinterdataex
8655 From MSDN documentation of GetPrinterDataEx: pass request
8656 to GetPrinterData if key is "PrinterDriverData".
8657 ********************************************************************/
8659 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8661 POLICY_HND *handle = &q_u->handle;
8662 uint32 in_size = q_u->size;
8663 uint32 *type = &r_u->type;
8664 uint32 *out_size = &r_u->size;
8665 uint8 **data = &r_u->data;
8666 uint32 *needed = &r_u->needed;
8667 fstring keyname, valuename;
8669 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8671 NT_PRINTER_INFO_LEVEL *printer = NULL;
8673 WERROR status = WERR_OK;
8675 DEBUG(4,("_spoolss_getprinterdataex\n"));
8677 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8678 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8680 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8681 keyname, valuename));
8683 /* in case of problem, return some default values */
8687 *out_size = in_size;
8690 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8691 status = WERR_BADFID;
8695 /* Is the handle to a printer or to the server? */
8697 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8698 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8699 status = WERR_INVALID_PARAM;
8703 if ( !get_printer_snum(p,handle, &snum) )
8706 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8707 if ( !W_ERROR_IS_OK(status) )
8710 /* check to see if the keyname is valid */
8711 if ( !strlen(keyname) ) {
8712 status = WERR_INVALID_PARAM;
8716 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8717 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8718 free_a_printer( &printer, 2 );
8719 status = WERR_BADFILE;
8723 /* When given a new keyname, we should just create it */
8725 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8727 if (*needed > *out_size)
8728 status = WERR_MORE_DATA;
8731 if ( !W_ERROR_IS_OK(status) )
8733 DEBUG(5, ("error: allocating %d\n", *out_size));
8735 /* reply this param doesn't exist */
8739 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8740 status = WERR_NOMEM;
8750 free_a_printer( &printer, 2 );
8755 /********************************************************************
8756 * spoolss_setprinterdataex
8757 ********************************************************************/
8759 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8761 POLICY_HND *handle = &q_u->handle;
8762 uint32 type = q_u->type;
8763 uint8 *data = q_u->data;
8764 uint32 real_len = q_u->real_len;
8766 NT_PRINTER_INFO_LEVEL *printer = NULL;
8768 WERROR status = WERR_OK;
8769 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8774 DEBUG(4,("_spoolss_setprinterdataex\n"));
8776 /* From MSDN documentation of SetPrinterDataEx: pass request to
8777 SetPrinterData if key is "PrinterDriverData" */
8780 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8784 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8785 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8786 return WERR_INVALID_PARAM;
8789 if ( !get_printer_snum(p,handle, &snum) )
8793 * Access check : NT returns "access denied" if you make a
8794 * SetPrinterData call without the necessary privildge.
8795 * we were originally returning OK if nothing changed
8796 * which made Win2k issue **a lot** of SetPrinterData
8797 * when connecting to a printer --jerry
8800 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8802 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8803 return WERR_ACCESS_DENIED;
8806 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8807 if (!W_ERROR_IS_OK(status))
8810 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8811 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8813 /* check for OID in valuename */
8815 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8821 /* save the registry data */
8823 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8825 if ( W_ERROR_IS_OK(status) )
8827 /* save the OID if one was specified */
8829 fstrcat( keyname, "\\" );
8830 fstrcat( keyname, SPOOL_OID_KEY );
8833 * I'm not checking the status here on purpose. Don't know
8834 * if this is right, but I'm returning the status from the
8835 * previous set_printer_dataex() call. I have no idea if
8836 * this is right. --jerry
8839 set_printer_dataex( printer, keyname, valuename,
8840 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8843 status = mod_a_printer(*printer, 2);
8846 free_a_printer(&printer, 2);
8852 /********************************************************************
8853 * spoolss_deleteprinterdataex
8854 ********************************************************************/
8856 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8858 POLICY_HND *handle = &q_u->handle;
8859 UNISTR2 *value = &q_u->valuename;
8860 UNISTR2 *key = &q_u->keyname;
8862 NT_PRINTER_INFO_LEVEL *printer = NULL;
8864 WERROR status = WERR_OK;
8865 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8866 pstring valuename, keyname;
8868 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8871 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8875 if (!get_printer_snum(p, handle, &snum))
8878 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8879 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8880 return WERR_ACCESS_DENIED;
8883 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8884 if (!W_ERROR_IS_OK(status))
8887 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8888 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8890 status = delete_printer_dataex( printer, keyname, valuename );
8892 if ( W_ERROR_IS_OK(status) )
8893 mod_a_printer( *printer, 2 );
8895 free_a_printer(&printer, 2);
8900 /********************************************************************
8901 * spoolss_enumprinterkey
8902 ********************************************************************/
8905 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8908 fstring *keynames = NULL;
8909 uint16 *enumkeys = NULL;
8912 POLICY_HND *handle = &q_u->handle;
8913 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8914 NT_PRINTER_DATA *data;
8915 NT_PRINTER_INFO_LEVEL *printer = NULL;
8917 WERROR status = WERR_BADFILE;
8920 DEBUG(4,("_spoolss_enumprinterkey\n"));
8923 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8927 if ( !get_printer_snum(p,handle, &snum) )
8930 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8931 if (!W_ERROR_IS_OK(status))
8934 /* get the list of subkey names */
8936 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8937 data = &printer->info_2->data;
8939 num_keys = get_printer_subkeys( data, key, &keynames );
8941 if ( num_keys == -1 ) {
8942 status = WERR_BADFILE;
8946 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8948 r_u->needed = printerkey_len*2;
8950 if ( q_u->size < r_u->needed ) {
8951 status = WERR_MORE_DATA;
8955 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8956 status = WERR_NOMEM;
8962 if ( q_u->size < r_u->needed )
8963 status = WERR_MORE_DATA;
8966 free_a_printer( &printer, 2 );
8967 SAFE_FREE( keynames );
8972 /********************************************************************
8973 * spoolss_deleteprinterkey
8974 ********************************************************************/
8976 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8978 POLICY_HND *handle = &q_u->handle;
8979 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8981 NT_PRINTER_INFO_LEVEL *printer = NULL;
8985 DEBUG(5,("spoolss_deleteprinterkey\n"));
8988 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8992 /* if keyname == NULL, return error */
8994 if ( !q_u->keyname.buffer )
8995 return WERR_INVALID_PARAM;
8997 if (!get_printer_snum(p, handle, &snum))
9000 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9001 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9002 return WERR_ACCESS_DENIED;
9005 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9006 if (!W_ERROR_IS_OK(status))
9009 /* delete the key and all subneys */
9011 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9013 status = delete_all_printer_data( printer->info_2, key );
9015 if ( W_ERROR_IS_OK(status) )
9016 status = mod_a_printer(*printer, 2);
9018 free_a_printer( &printer, 2 );
9024 /********************************************************************
9025 * spoolss_enumprinterdataex
9026 ********************************************************************/
9028 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9030 POLICY_HND *handle = &q_u->handle;
9031 uint32 in_size = q_u->size;
9034 NT_PRINTER_INFO_LEVEL *printer = NULL;
9035 PRINTER_ENUM_VALUES *enum_values = NULL;
9036 NT_PRINTER_DATA *p_data;
9038 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9043 REGISTRY_VALUE *val;
9048 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9051 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9056 * first check for a keyname of NULL or "". Win2k seems to send
9057 * this a lot and we should send back WERR_INVALID_PARAM
9058 * no need to spend time looking up the printer in this case.
9062 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9063 if ( !strlen(key) ) {
9064 result = WERR_INVALID_PARAM;
9068 /* get the printer off of disk */
9070 if (!get_printer_snum(p,handle, &snum))
9073 ZERO_STRUCT(printer);
9074 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9075 if (!W_ERROR_IS_OK(result))
9078 /* now look for a match on the key name */
9080 p_data = &printer->info_2->data;
9082 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9083 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9085 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9086 result = WERR_INVALID_PARAM;
9093 /* allocate the memory for the array of pointers -- if necessary */
9095 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9098 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9100 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9101 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9102 result = WERR_NOMEM;
9106 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9110 * loop through all params and build the array to pass
9111 * back to the client
9114 for ( i=0; i<num_entries; i++ )
9116 /* lookup the registry value */
9118 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9119 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9123 value_name = regval_name( val );
9124 init_unistr( &enum_values[i].valuename, value_name );
9125 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9126 enum_values[i].type = regval_type( val );
9128 data_len = regval_size( val );
9130 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9132 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9134 result = WERR_NOMEM;
9138 enum_values[i].data_len = data_len;
9140 /* keep track of the size of the array in bytes */
9142 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9145 /* housekeeping information in the reply */
9147 r_u->needed = needed;
9148 r_u->returned = num_entries;
9150 if (needed > in_size) {
9151 result = WERR_MORE_DATA;
9155 /* copy data into the reply */
9157 r_u->ctr.size = r_u->needed;
9158 r_u->ctr.size_of_array = r_u->returned;
9159 r_u->ctr.values = enum_values;
9165 free_a_printer(&printer, 2);
9170 /****************************************************************************
9171 ****************************************************************************/
9173 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9175 init_unistr(&info->name, name);
9178 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9179 UNISTR2 *environment,
9186 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9188 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9190 if (!get_short_archi(long_archi))
9191 return WERR_INVALID_ENVIRONMENT;
9193 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9196 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9198 fill_printprocessordirectory_1(info, path);
9200 *needed += spoolss_size_printprocessordirectory_info_1(info);
9202 if (!alloc_buffer_size(buffer, *needed)) {
9204 return WERR_INSUFFICIENT_BUFFER;
9207 smb_io_printprocessordirectory_1("", buffer, info, 0);
9211 if (*needed > offered)
9212 return WERR_INSUFFICIENT_BUFFER;
9217 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9219 uint32 level = q_u->level;
9220 NEW_BUFFER *buffer = NULL;
9221 uint32 offered = q_u->offered;
9222 uint32 *needed = &r_u->needed;
9225 /* that's an [in out] buffer */
9226 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9227 buffer = r_u->buffer;
9229 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9235 result = getprintprocessordirectory_level_1
9236 (&q_u->name, &q_u->environment, buffer, offered, needed);
9239 result = WERR_UNKNOWN_LEVEL;
9247 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9248 SPOOL_R_REPLYOPENPRINTER *r_u)
9250 DEBUG(5,("_spoolss_replyopenprinter\n"));
9252 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9257 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9258 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9260 DEBUG(5,("_spoolss_replycloseprinter\n"));