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"));
1806 sys_usleep( 500000 );
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;
2601 cli_setup_signing_state(the_cli, lp_client_signing());
2603 if (!cli_negprot(the_cli)) {
2604 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2605 cli_shutdown(the_cli);
2609 if (the_cli->protocol != PROTOCOL_NT1) {
2610 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2611 cli_shutdown(the_cli);
2616 * Do an anonymous session setup.
2619 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2620 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2621 cli_shutdown(the_cli);
2625 if (!(the_cli->sec_mode & 1)) {
2626 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2627 cli_shutdown(the_cli);
2631 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2632 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) ));
2633 cli_shutdown(the_cli);
2638 * Ok - we have an anonymous connection to the IPC$ share.
2639 * Now start the NT Domain stuff :-).
2642 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2643 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)));
2644 cli_nt_session_close(the_cli);
2645 cli_ulogoff(the_cli);
2646 cli_shutdown(the_cli);
2653 /***************************************************************************
2654 Connect to the client.
2655 ****************************************************************************/
2657 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2658 uint32 localprinter, uint32 type,
2659 POLICY_HND *handle, struct in_addr *client_ip)
2664 * If it's the first connection, contact the client
2665 * and connect to the IPC$ share anonymously
2667 if (smb_connections==0) {
2668 fstring unix_printer;
2670 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2672 ZERO_STRUCT(notify_cli);
2674 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2677 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2678 /* Tell the connections db we're now interested in printer
2679 * notify messages. */
2680 register_message_flags( True, FLAG_MSG_PRINTING );
2684 * Tell the specific printing tdb we want messages for this printer
2685 * by registering our PID.
2688 if (!print_notify_register_pid(snum))
2689 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2693 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2696 if (!W_ERROR_IS_OK(result))
2697 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2698 dos_errstr(result)));
2700 return (W_ERROR_IS_OK(result));
2703 /********************************************************************
2705 * ReplyFindFirstPrinterChangeNotifyEx
2707 * before replying OK: status=0 a rpc call is made to the workstation
2708 * asking ReplyOpenPrinter
2710 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2711 * called from api_spoolss_rffpcnex
2712 ********************************************************************/
2714 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2716 POLICY_HND *handle = &q_u->handle;
2717 uint32 flags = q_u->flags;
2718 uint32 options = q_u->options;
2719 UNISTR2 *localmachine = &q_u->localmachine;
2720 uint32 printerlocal = q_u->printerlocal;
2722 SPOOL_NOTIFY_OPTION *option = q_u->option;
2723 struct in_addr client_ip;
2725 /* store the notify value in the printer struct */
2727 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2730 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2734 Printer->notify.flags=flags;
2735 Printer->notify.options=options;
2736 Printer->notify.printerlocal=printerlocal;
2738 if (Printer->notify.option)
2739 free_spool_notify_option(&Printer->notify.option);
2741 Printer->notify.option=dup_spool_notify_option(option);
2743 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2744 sizeof(Printer->notify.localmachine)-1);
2746 /* Connect to the client machine and send a ReplyOpenPrinter */
2748 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2750 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2751 !get_printer_snum(p, handle, &snum) )
2754 client_ip.s_addr = inet_addr(p->conn->client_address);
2756 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2757 Printer->notify.printerlocal, 1,
2758 &Printer->notify.client_hnd, &client_ip))
2759 return WERR_SERVER_UNAVAILABLE;
2761 Printer->notify.client_connected=True;
2766 /*******************************************************************
2767 * fill a notify_info_data with the servername
2768 ********************************************************************/
2770 void spoolss_notify_server_name(int snum,
2771 SPOOL_NOTIFY_INFO_DATA *data,
2772 print_queue_struct *queue,
2773 NT_PRINTER_INFO_LEVEL *printer,
2774 TALLOC_CTX *mem_ctx)
2776 pstring temp_name, temp;
2779 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2781 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2783 data->notify_data.data.length = len;
2784 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2786 if (!data->notify_data.data.string) {
2787 data->notify_data.data.length = 0;
2791 memcpy(data->notify_data.data.string, temp, len);
2794 /*******************************************************************
2795 * fill a notify_info_data with the printername (not including the servername).
2796 ********************************************************************/
2798 void spoolss_notify_printer_name(int snum,
2799 SPOOL_NOTIFY_INFO_DATA *data,
2800 print_queue_struct *queue,
2801 NT_PRINTER_INFO_LEVEL *printer,
2802 TALLOC_CTX *mem_ctx)
2807 /* the notify name should not contain the \\server\ part */
2808 char *p = strrchr(printer->info_2->printername, '\\');
2811 p = printer->info_2->printername;
2816 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2818 data->notify_data.data.length = len;
2819 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2821 if (!data->notify_data.data.string) {
2822 data->notify_data.data.length = 0;
2826 memcpy(data->notify_data.data.string, temp, len);
2829 /*******************************************************************
2830 * fill a notify_info_data with the servicename
2831 ********************************************************************/
2833 void spoolss_notify_share_name(int snum,
2834 SPOOL_NOTIFY_INFO_DATA *data,
2835 print_queue_struct *queue,
2836 NT_PRINTER_INFO_LEVEL *printer,
2837 TALLOC_CTX *mem_ctx)
2842 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2844 data->notify_data.data.length = len;
2845 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2847 if (!data->notify_data.data.string) {
2848 data->notify_data.data.length = 0;
2852 memcpy(data->notify_data.data.string, temp, len);
2855 /*******************************************************************
2856 * fill a notify_info_data with the port name
2857 ********************************************************************/
2859 void spoolss_notify_port_name(int snum,
2860 SPOOL_NOTIFY_INFO_DATA *data,
2861 print_queue_struct *queue,
2862 NT_PRINTER_INFO_LEVEL *printer,
2863 TALLOC_CTX *mem_ctx)
2868 /* even if it's strange, that's consistant in all the code */
2870 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2872 data->notify_data.data.length = len;
2873 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2875 if (!data->notify_data.data.string) {
2876 data->notify_data.data.length = 0;
2880 memcpy(data->notify_data.data.string, temp, len);
2883 /*******************************************************************
2884 * fill a notify_info_data with the printername
2885 * but it doesn't exist, have to see what to do
2886 ********************************************************************/
2888 void spoolss_notify_driver_name(int snum,
2889 SPOOL_NOTIFY_INFO_DATA *data,
2890 print_queue_struct *queue,
2891 NT_PRINTER_INFO_LEVEL *printer,
2892 TALLOC_CTX *mem_ctx)
2897 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2899 data->notify_data.data.length = len;
2900 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2902 if (!data->notify_data.data.string) {
2903 data->notify_data.data.length = 0;
2907 memcpy(data->notify_data.data.string, temp, len);
2910 /*******************************************************************
2911 * fill a notify_info_data with the comment
2912 ********************************************************************/
2914 void spoolss_notify_comment(int snum,
2915 SPOOL_NOTIFY_INFO_DATA *data,
2916 print_queue_struct *queue,
2917 NT_PRINTER_INFO_LEVEL *printer,
2918 TALLOC_CTX *mem_ctx)
2923 if (*printer->info_2->comment == '\0')
2924 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2926 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2928 data->notify_data.data.length = len;
2929 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2931 if (!data->notify_data.data.string) {
2932 data->notify_data.data.length = 0;
2936 memcpy(data->notify_data.data.string, temp, len);
2939 /*******************************************************************
2940 * fill a notify_info_data with the comment
2941 * location = "Room 1, floor 2, building 3"
2942 ********************************************************************/
2944 void spoolss_notify_location(int snum,
2945 SPOOL_NOTIFY_INFO_DATA *data,
2946 print_queue_struct *queue,
2947 NT_PRINTER_INFO_LEVEL *printer,
2948 TALLOC_CTX *mem_ctx)
2953 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2955 data->notify_data.data.length = len;
2956 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2958 if (!data->notify_data.data.string) {
2959 data->notify_data.data.length = 0;
2963 memcpy(data->notify_data.data.string, temp, len);
2966 /*******************************************************************
2967 * fill a notify_info_data with the device mode
2968 * jfm:xxxx don't to it for know but that's a real problem !!!
2969 ********************************************************************/
2971 static void spoolss_notify_devmode(int snum,
2972 SPOOL_NOTIFY_INFO_DATA *data,
2973 print_queue_struct *queue,
2974 NT_PRINTER_INFO_LEVEL *printer,
2975 TALLOC_CTX *mem_ctx)
2979 /*******************************************************************
2980 * fill a notify_info_data with the separator file name
2981 ********************************************************************/
2983 void spoolss_notify_sepfile(int snum,
2984 SPOOL_NOTIFY_INFO_DATA *data,
2985 print_queue_struct *queue,
2986 NT_PRINTER_INFO_LEVEL *printer,
2987 TALLOC_CTX *mem_ctx)
2992 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2994 data->notify_data.data.length = len;
2995 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2997 if (!data->notify_data.data.string) {
2998 data->notify_data.data.length = 0;
3002 memcpy(data->notify_data.data.string, temp, len);
3005 /*******************************************************************
3006 * fill a notify_info_data with the print processor
3007 * jfm:xxxx return always winprint to indicate we don't do anything to it
3008 ********************************************************************/
3010 void spoolss_notify_print_processor(int snum,
3011 SPOOL_NOTIFY_INFO_DATA *data,
3012 print_queue_struct *queue,
3013 NT_PRINTER_INFO_LEVEL *printer,
3014 TALLOC_CTX *mem_ctx)
3019 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3021 data->notify_data.data.length = len;
3022 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3024 if (!data->notify_data.data.string) {
3025 data->notify_data.data.length = 0;
3029 memcpy(data->notify_data.data.string, temp, len);
3032 /*******************************************************************
3033 * fill a notify_info_data with the print processor options
3034 * jfm:xxxx send an empty string
3035 ********************************************************************/
3037 void spoolss_notify_parameters(int snum,
3038 SPOOL_NOTIFY_INFO_DATA *data,
3039 print_queue_struct *queue,
3040 NT_PRINTER_INFO_LEVEL *printer,
3041 TALLOC_CTX *mem_ctx)
3046 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3048 data->notify_data.data.length = len;
3049 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3051 if (!data->notify_data.data.string) {
3052 data->notify_data.data.length = 0;
3056 memcpy(data->notify_data.data.string, temp, len);
3059 /*******************************************************************
3060 * fill a notify_info_data with the data type
3061 * jfm:xxxx always send RAW as data type
3062 ********************************************************************/
3064 void spoolss_notify_datatype(int snum,
3065 SPOOL_NOTIFY_INFO_DATA *data,
3066 print_queue_struct *queue,
3067 NT_PRINTER_INFO_LEVEL *printer,
3068 TALLOC_CTX *mem_ctx)
3073 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3075 data->notify_data.data.length = len;
3076 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3078 if (!data->notify_data.data.string) {
3079 data->notify_data.data.length = 0;
3083 memcpy(data->notify_data.data.string, temp, len);
3086 /*******************************************************************
3087 * fill a notify_info_data with the security descriptor
3088 * jfm:xxxx send an null pointer to say no security desc
3089 * have to implement security before !
3090 ********************************************************************/
3092 static void spoolss_notify_security_desc(int snum,
3093 SPOOL_NOTIFY_INFO_DATA *data,
3094 print_queue_struct *queue,
3095 NT_PRINTER_INFO_LEVEL *printer,
3096 TALLOC_CTX *mem_ctx)
3098 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3099 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3102 /*******************************************************************
3103 * fill a notify_info_data with the attributes
3104 * jfm:xxxx a samba printer is always shared
3105 ********************************************************************/
3107 void spoolss_notify_attributes(int snum,
3108 SPOOL_NOTIFY_INFO_DATA *data,
3109 print_queue_struct *queue,
3110 NT_PRINTER_INFO_LEVEL *printer,
3111 TALLOC_CTX *mem_ctx)
3113 data->notify_data.value[0] = printer->info_2->attributes;
3114 data->notify_data.value[1] = 0;
3117 /*******************************************************************
3118 * fill a notify_info_data with the priority
3119 ********************************************************************/
3121 static void spoolss_notify_priority(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3127 data->notify_data.value[0] = printer->info_2->priority;
3128 data->notify_data.value[1] = 0;
3131 /*******************************************************************
3132 * fill a notify_info_data with the default priority
3133 ********************************************************************/
3135 static void spoolss_notify_default_priority(int snum,
3136 SPOOL_NOTIFY_INFO_DATA *data,
3137 print_queue_struct *queue,
3138 NT_PRINTER_INFO_LEVEL *printer,
3139 TALLOC_CTX *mem_ctx)
3141 data->notify_data.value[0] = printer->info_2->default_priority;
3142 data->notify_data.value[1] = 0;
3145 /*******************************************************************
3146 * fill a notify_info_data with the start time
3147 ********************************************************************/
3149 static void spoolss_notify_start_time(int snum,
3150 SPOOL_NOTIFY_INFO_DATA *data,
3151 print_queue_struct *queue,
3152 NT_PRINTER_INFO_LEVEL *printer,
3153 TALLOC_CTX *mem_ctx)
3155 data->notify_data.value[0] = printer->info_2->starttime;
3156 data->notify_data.value[1] = 0;
3159 /*******************************************************************
3160 * fill a notify_info_data with the until time
3161 ********************************************************************/
3163 static void spoolss_notify_until_time(int snum,
3164 SPOOL_NOTIFY_INFO_DATA *data,
3165 print_queue_struct *queue,
3166 NT_PRINTER_INFO_LEVEL *printer,
3167 TALLOC_CTX *mem_ctx)
3169 data->notify_data.value[0] = printer->info_2->untiltime;
3170 data->notify_data.value[1] = 0;
3173 /*******************************************************************
3174 * fill a notify_info_data with the status
3175 ********************************************************************/
3177 static void spoolss_notify_status(int snum,
3178 SPOOL_NOTIFY_INFO_DATA *data,
3179 print_queue_struct *queue,
3180 NT_PRINTER_INFO_LEVEL *printer,
3181 TALLOC_CTX *mem_ctx)
3183 print_status_struct status;
3185 print_queue_length(snum, &status);
3186 data->notify_data.value[0]=(uint32) status.status;
3187 data->notify_data.value[1] = 0;
3190 /*******************************************************************
3191 * fill a notify_info_data with the number of jobs queued
3192 ********************************************************************/
3194 void spoolss_notify_cjobs(int snum,
3195 SPOOL_NOTIFY_INFO_DATA *data,
3196 print_queue_struct *queue,
3197 NT_PRINTER_INFO_LEVEL *printer,
3198 TALLOC_CTX *mem_ctx)
3200 data->notify_data.value[0] = print_queue_length(snum, NULL);
3201 data->notify_data.value[1] = 0;
3204 /*******************************************************************
3205 * fill a notify_info_data with the average ppm
3206 ********************************************************************/
3208 static void spoolss_notify_average_ppm(int snum,
3209 SPOOL_NOTIFY_INFO_DATA *data,
3210 print_queue_struct *queue,
3211 NT_PRINTER_INFO_LEVEL *printer,
3212 TALLOC_CTX *mem_ctx)
3214 /* always respond 8 pages per minutes */
3215 /* a little hard ! */
3216 data->notify_data.value[0] = printer->info_2->averageppm;
3217 data->notify_data.value[1] = 0;
3220 /*******************************************************************
3221 * fill a notify_info_data with username
3222 ********************************************************************/
3224 static void spoolss_notify_username(int snum,
3225 SPOOL_NOTIFY_INFO_DATA *data,
3226 print_queue_struct *queue,
3227 NT_PRINTER_INFO_LEVEL *printer,
3228 TALLOC_CTX *mem_ctx)
3233 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3235 data->notify_data.data.length = len;
3236 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3238 if (!data->notify_data.data.string) {
3239 data->notify_data.data.length = 0;
3243 memcpy(data->notify_data.data.string, temp, len);
3246 /*******************************************************************
3247 * fill a notify_info_data with job status
3248 ********************************************************************/
3250 static void spoolss_notify_job_status(int snum,
3251 SPOOL_NOTIFY_INFO_DATA *data,
3252 print_queue_struct *queue,
3253 NT_PRINTER_INFO_LEVEL *printer,
3254 TALLOC_CTX *mem_ctx)
3256 data->notify_data.value[0]=nt_printj_status(queue->status);
3257 data->notify_data.value[1] = 0;
3260 /*******************************************************************
3261 * fill a notify_info_data with job name
3262 ********************************************************************/
3264 static void spoolss_notify_job_name(int snum,
3265 SPOOL_NOTIFY_INFO_DATA *data,
3266 print_queue_struct *queue,
3267 NT_PRINTER_INFO_LEVEL *printer,
3268 TALLOC_CTX *mem_ctx)
3273 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3275 data->notify_data.data.length = len;
3276 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3278 if (!data->notify_data.data.string) {
3279 data->notify_data.data.length = 0;
3283 memcpy(data->notify_data.data.string, temp, len);
3286 /*******************************************************************
3287 * fill a notify_info_data with job status
3288 ********************************************************************/
3290 static void spoolss_notify_job_status_string(int snum,
3291 SPOOL_NOTIFY_INFO_DATA *data,
3292 print_queue_struct *queue,
3293 NT_PRINTER_INFO_LEVEL *printer,
3294 TALLOC_CTX *mem_ctx)
3297 * Now we're returning job status codes we just return a "" here. JRA.
3304 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3307 switch (queue->status) {
3312 p = ""; /* NT provides the paused string */
3321 #endif /* NO LONGER NEEDED. */
3323 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3325 data->notify_data.data.length = len;
3326 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3328 if (!data->notify_data.data.string) {
3329 data->notify_data.data.length = 0;
3333 memcpy(data->notify_data.data.string, temp, len);
3336 /*******************************************************************
3337 * fill a notify_info_data with job time
3338 ********************************************************************/
3340 static void spoolss_notify_job_time(int snum,
3341 SPOOL_NOTIFY_INFO_DATA *data,
3342 print_queue_struct *queue,
3343 NT_PRINTER_INFO_LEVEL *printer,
3344 TALLOC_CTX *mem_ctx)
3346 data->notify_data.value[0]=0x0;
3347 data->notify_data.value[1]=0;
3350 /*******************************************************************
3351 * fill a notify_info_data with job size
3352 ********************************************************************/
3354 static void spoolss_notify_job_size(int snum,
3355 SPOOL_NOTIFY_INFO_DATA *data,
3356 print_queue_struct *queue,
3357 NT_PRINTER_INFO_LEVEL *printer,
3358 TALLOC_CTX *mem_ctx)
3360 data->notify_data.value[0]=queue->size;
3361 data->notify_data.value[1]=0;
3364 /*******************************************************************
3365 * fill a notify_info_data with page info
3366 ********************************************************************/
3367 static void spoolss_notify_total_pages(int snum,
3368 SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer,
3371 TALLOC_CTX *mem_ctx)
3373 data->notify_data.value[0]=queue->page_count;
3374 data->notify_data.value[1]=0;
3377 /*******************************************************************
3378 * fill a notify_info_data with pages printed info.
3379 ********************************************************************/
3380 static void spoolss_notify_pages_printed(int snum,
3381 SPOOL_NOTIFY_INFO_DATA *data,
3382 print_queue_struct *queue,
3383 NT_PRINTER_INFO_LEVEL *printer,
3384 TALLOC_CTX *mem_ctx)
3386 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3387 data->notify_data.value[1]=0;
3390 /*******************************************************************
3391 Fill a notify_info_data with job position.
3392 ********************************************************************/
3394 static void spoolss_notify_job_position(int snum,
3395 SPOOL_NOTIFY_INFO_DATA *data,
3396 print_queue_struct *queue,
3397 NT_PRINTER_INFO_LEVEL *printer,
3398 TALLOC_CTX *mem_ctx)
3400 data->notify_data.value[0]=queue->job;
3401 data->notify_data.value[1]=0;
3404 /*******************************************************************
3405 Fill a notify_info_data with submitted time.
3406 ********************************************************************/
3408 static void spoolss_notify_submitted_time(int snum,
3409 SPOOL_NOTIFY_INFO_DATA *data,
3410 print_queue_struct *queue,
3411 NT_PRINTER_INFO_LEVEL *printer,
3412 TALLOC_CTX *mem_ctx)
3419 t=gmtime(&queue->time);
3421 len = sizeof(SYSTEMTIME);
3423 data->notify_data.data.length = len;
3424 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3426 if (!data->notify_data.data.string) {
3427 data->notify_data.data.length = 0;
3431 make_systemtime(&st, t);
3434 * Systemtime must be linearized as a set of UINT16's.
3435 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3438 p = (char *)data->notify_data.data.string;
3439 SSVAL(p, 0, st.year);
3440 SSVAL(p, 2, st.month);
3441 SSVAL(p, 4, st.dayofweek);
3442 SSVAL(p, 6, st.day);
3443 SSVAL(p, 8, st.hour);
3444 SSVAL(p, 10, st.minute);
3445 SSVAL(p, 12, st.second);
3446 SSVAL(p, 14, st.milliseconds);
3449 struct s_notify_info_data_table
3455 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3456 print_queue_struct *queue,
3457 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3460 /* A table describing the various print notification constants and
3461 whether the notification data is a pointer to a variable sized
3462 buffer, a one value uint32 or a two value uint32. */
3464 static const struct s_notify_info_data_table notify_info_data_table[] =
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3489 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3490 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3491 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3511 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3512 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3513 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3514 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3517 /*******************************************************************
3518 Return the size of info_data structure.
3519 ********************************************************************/
3521 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3525 for (i = 0; i < sizeof(notify_info_data_table); i++)
3527 if ( (notify_info_data_table[i].type == type)
3528 && (notify_info_data_table[i].field == field) )
3530 switch(notify_info_data_table[i].size)
3532 case NOTIFY_ONE_VALUE:
3533 case NOTIFY_TWO_VALUE:
3538 /* The only pointer notify data I have seen on
3539 the wire is the submitted time and this has
3540 the notify size set to 4. -tpot */
3542 case NOTIFY_POINTER:
3545 case NOTIFY_SECDESC:
3551 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3556 /*******************************************************************
3557 Return the type of notify_info_data.
3558 ********************************************************************/
3560 static int type_of_notify_info_data(uint16 type, uint16 field)
3564 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3565 if (notify_info_data_table[i].type == type &&
3566 notify_info_data_table[i].field == field)
3567 return notify_info_data_table[i].size;
3573 /****************************************************************************
3574 ****************************************************************************/
3576 static int search_notify(uint16 type, uint16 field, int *value)
3580 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3581 if (notify_info_data_table[i].type == type &&
3582 notify_info_data_table[i].field == field &&
3583 notify_info_data_table[i].fn != NULL) {
3592 /****************************************************************************
3593 ****************************************************************************/
3595 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3597 info_data->type = type;
3598 info_data->field = field;
3599 info_data->reserved = 0;
3601 info_data->size = size_of_notify_info_data(type, field);
3602 info_data->enc_type = type_of_notify_info_data(type, field);
3609 /*******************************************************************
3611 * fill a notify_info struct with info asked
3613 ********************************************************************/
3615 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3616 snum, SPOOL_NOTIFY_OPTION_TYPE
3617 *option_type, uint32 id,
3618 TALLOC_CTX *mem_ctx)
3624 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3625 NT_PRINTER_INFO_LEVEL *printer = NULL;
3626 print_queue_struct *queue=NULL;
3628 type=option_type->type;
3630 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3631 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3632 option_type->count, lp_servicename(snum)));
3634 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3637 for(field_num=0; field_num<option_type->count; field_num++) {
3638 field = option_type->fields[field_num];
3640 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3642 if (!search_notify(type, field, &j) )
3645 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3646 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3651 current_data = &info->data[info->count];
3653 construct_info_data(current_data, type, field, id);
3655 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3656 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3658 notify_info_data_table[j].fn(snum, current_data, queue,
3664 free_a_printer(&printer, 2);
3668 /*******************************************************************
3670 * fill a notify_info struct with info asked
3672 ********************************************************************/
3674 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3675 SPOOL_NOTIFY_INFO *info,
3676 NT_PRINTER_INFO_LEVEL *printer,
3677 int snum, SPOOL_NOTIFY_OPTION_TYPE
3678 *option_type, uint32 id,
3679 TALLOC_CTX *mem_ctx)
3685 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3687 DEBUG(4,("construct_notify_jobs_info\n"));
3689 type = option_type->type;
3691 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3692 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3693 option_type->count));
3695 for(field_num=0; field_num<option_type->count; field_num++) {
3696 field = option_type->fields[field_num];
3698 if (!search_notify(type, field, &j) )
3701 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3702 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3705 else info->data = tid;
3707 current_data=&(info->data[info->count]);
3709 construct_info_data(current_data, type, field, id);
3710 notify_info_data_table[j].fn(snum, current_data, queue,
3719 * JFM: The enumeration is not that simple, it's even non obvious.
3721 * let's take an example: I want to monitor the PRINTER SERVER for
3722 * the printer's name and the number of jobs currently queued.
3723 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3724 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3726 * I have 3 printers on the back of my server.
3728 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3731 * 1 printer 1 name 1
3732 * 2 printer 1 cjob 1
3733 * 3 printer 2 name 2
3734 * 4 printer 2 cjob 2
3735 * 5 printer 3 name 3
3736 * 6 printer 3 name 3
3738 * that's the print server case, the printer case is even worse.
3741 /*******************************************************************
3743 * enumerate all printers on the printserver
3744 * fill a notify_info struct with info asked
3746 ********************************************************************/
3748 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3749 SPOOL_NOTIFY_INFO *info,
3750 TALLOC_CTX *mem_ctx)
3753 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3754 int n_services=lp_numservices();
3756 SPOOL_NOTIFY_OPTION *option;
3757 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3759 DEBUG(4,("printserver_notify_info\n"));
3764 option=Printer->notify.option;
3769 for (i=0; i<option->count; i++) {
3770 option_type=&(option->ctr.type[i]);
3772 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3775 for (snum=0; snum<n_services; snum++)
3777 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3778 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3784 * Debugging information, don't delete.
3787 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3788 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3789 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3791 for (i=0; i<info->count; i++) {
3792 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3793 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3794 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3801 /*******************************************************************
3803 * fill a notify_info struct with info asked
3805 ********************************************************************/
3807 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3808 TALLOC_CTX *mem_ctx)
3811 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3814 SPOOL_NOTIFY_OPTION *option;
3815 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3817 print_queue_struct *queue=NULL;
3818 print_status_struct status;
3820 DEBUG(4,("printer_notify_info\n"));
3825 option=Printer->notify.option;
3831 get_printer_snum(p, hnd, &snum);
3833 for (i=0; i<option->count; i++) {
3834 option_type=&option->ctr.type[i];
3836 switch ( option_type->type ) {
3837 case PRINTER_NOTIFY_TYPE:
3838 if(construct_notify_printer_info(Printer, info, snum,
3844 case JOB_NOTIFY_TYPE: {
3845 NT_PRINTER_INFO_LEVEL *printer = NULL;
3847 count = print_queue_status(snum, &queue, &status);
3849 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3852 for (j=0; j<count; j++) {
3853 construct_notify_jobs_info(&queue[j], info,
3860 free_a_printer(&printer, 2);
3870 * Debugging information, don't delete.
3873 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3874 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3875 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3877 for (i=0; i<info->count; i++) {
3878 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3879 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3880 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3886 /********************************************************************
3888 ********************************************************************/
3890 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3892 POLICY_HND *handle = &q_u->handle;
3893 SPOOL_NOTIFY_INFO *info = &r_u->info;
3895 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3896 WERROR result = WERR_BADFID;
3898 /* we always have a NOTIFY_INFO struct */
3902 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3903 OUR_HANDLE(handle)));
3907 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3910 * We are now using the change value, and
3911 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3912 * I don't have a global notification system, I'm sending back all the
3913 * informations even when _NOTHING_ has changed.
3916 /* We need to keep track of the change value to send back in
3917 RRPCN replies otherwise our updates are ignored. */
3919 Printer->notify.fnpcn = True;
3921 if (Printer->notify.client_connected) {
3922 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3923 Printer->notify.change = q_u->change;
3926 /* just ignore the SPOOL_NOTIFY_OPTION */
3928 switch (Printer->printer_type) {
3929 case PRINTER_HANDLE_IS_PRINTSERVER:
3930 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3933 case PRINTER_HANDLE_IS_PRINTER:
3934 result = printer_notify_info(p, handle, info, p->mem_ctx);
3938 Printer->notify.fnpcn = False;
3944 /********************************************************************
3945 * construct_printer_info_0
3946 * fill a printer_info_0 struct
3947 ********************************************************************/
3949 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3953 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3954 counter_printer_0 *session_counter;
3955 uint32 global_counter;
3958 print_status_struct status;
3960 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3963 count = print_queue_length(snum, &status);
3965 /* check if we already have a counter for this printer */
3966 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3968 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3969 if (session_counter->snum == snum)
3973 /* it's the first time, add it to the list */
3974 if (session_counter==NULL) {
3975 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3976 free_a_printer(&ntprinter, 2);
3979 ZERO_STRUCTP(session_counter);
3980 session_counter->snum=snum;
3981 session_counter->counter=0;
3982 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3986 session_counter->counter++;
3989 * the global_counter should be stored in a TDB as it's common to all the clients
3990 * and should be zeroed on samba startup
3992 global_counter=session_counter->counter;
3994 pstrcpy(chaine,ntprinter->info_2->printername);
3996 init_unistr(&printer->printername, chaine);
3998 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3999 init_unistr(&printer->servername, chaine);
4001 printer->cjobs = count;
4002 printer->total_jobs = 0;
4003 printer->total_bytes = 0;
4005 setuptime = (time_t)ntprinter->info_2->setuptime;
4006 t=gmtime(&setuptime);
4008 printer->year = t->tm_year+1900;
4009 printer->month = t->tm_mon+1;
4010 printer->dayofweek = t->tm_wday;
4011 printer->day = t->tm_mday;
4012 printer->hour = t->tm_hour;
4013 printer->minute = t->tm_min;
4014 printer->second = t->tm_sec;
4015 printer->milliseconds = 0;
4017 printer->global_counter = global_counter;
4018 printer->total_pages = 0;
4020 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4021 printer->major_version = 0x0005; /* NT 5 */
4022 printer->build_version = 0x0893; /* build 2195 */
4024 printer->unknown7 = 0x1;
4025 printer->unknown8 = 0x0;
4026 printer->unknown9 = 0x0;
4027 printer->session_counter = session_counter->counter;
4028 printer->unknown11 = 0x0;
4029 printer->printer_errors = 0x0; /* number of print failure */
4030 printer->unknown13 = 0x0;
4031 printer->unknown14 = 0x1;
4032 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4033 printer->unknown16 = 0x0;
4034 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4035 printer->unknown18 = 0x0;
4036 printer->status = nt_printq_status(status.status);
4037 printer->unknown20 = 0x0;
4038 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4039 printer->unknown22 = 0x0;
4040 printer->unknown23 = 0x6; /* 6 ???*/
4041 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4042 printer->unknown25 = 0;
4043 printer->unknown26 = 0;
4044 printer->unknown27 = 0;
4045 printer->unknown28 = 0;
4046 printer->unknown29 = 0;
4048 free_a_printer(&ntprinter,2);
4052 /********************************************************************
4053 * construct_printer_info_1
4054 * fill a printer_info_1 struct
4055 ********************************************************************/
4056 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4060 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4062 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4065 printer->flags=flags;
4067 if (*ntprinter->info_2->comment == '\0') {
4068 init_unistr(&printer->comment, lp_comment(snum));
4069 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4070 ntprinter->info_2->drivername, lp_comment(snum));
4073 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4074 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4075 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4078 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4080 init_unistr(&printer->description, chaine);
4081 init_unistr(&printer->name, chaine2);
4083 free_a_printer(&ntprinter,2);
4088 /****************************************************************************
4089 Free a DEVMODE struct.
4090 ****************************************************************************/
4092 static void free_dev_mode(DEVICEMODE *dev)
4097 SAFE_FREE(dev->private);
4102 /****************************************************************************
4103 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4104 should be valid upon entry
4105 ****************************************************************************/
4107 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4109 if ( !devmode || !ntdevmode )
4112 init_unistr(&devmode->devicename, ntdevmode->devicename);
4114 init_unistr(&devmode->formname, ntdevmode->formname);
4116 devmode->specversion = ntdevmode->specversion;
4117 devmode->driverversion = ntdevmode->driverversion;
4118 devmode->size = ntdevmode->size;
4119 devmode->driverextra = ntdevmode->driverextra;
4120 devmode->fields = ntdevmode->fields;
4122 devmode->orientation = ntdevmode->orientation;
4123 devmode->papersize = ntdevmode->papersize;
4124 devmode->paperlength = ntdevmode->paperlength;
4125 devmode->paperwidth = ntdevmode->paperwidth;
4126 devmode->scale = ntdevmode->scale;
4127 devmode->copies = ntdevmode->copies;
4128 devmode->defaultsource = ntdevmode->defaultsource;
4129 devmode->printquality = ntdevmode->printquality;
4130 devmode->color = ntdevmode->color;
4131 devmode->duplex = ntdevmode->duplex;
4132 devmode->yresolution = ntdevmode->yresolution;
4133 devmode->ttoption = ntdevmode->ttoption;
4134 devmode->collate = ntdevmode->collate;
4135 devmode->icmmethod = ntdevmode->icmmethod;
4136 devmode->icmintent = ntdevmode->icmintent;
4137 devmode->mediatype = ntdevmode->mediatype;
4138 devmode->dithertype = ntdevmode->dithertype;
4140 if (ntdevmode->private != NULL) {
4141 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4148 /****************************************************************************
4149 Create a DEVMODE struct. Returns malloced memory.
4150 ****************************************************************************/
4152 DEVICEMODE *construct_dev_mode(int snum)
4154 NT_PRINTER_INFO_LEVEL *printer = NULL;
4155 DEVICEMODE *devmode = NULL;
4157 DEBUG(7,("construct_dev_mode\n"));
4159 DEBUGADD(8,("getting printer characteristics\n"));
4161 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4164 if ( !printer->info_2->devmode ) {
4165 DEBUG(5, ("BONG! There was no device mode!\n"));
4169 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4170 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4174 ZERO_STRUCTP(devmode);
4176 DEBUGADD(8,("loading DEVICEMODE\n"));
4178 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4179 free_dev_mode( devmode );
4184 free_a_printer(&printer,2);
4189 /********************************************************************
4190 * construct_printer_info_2
4191 * fill a printer_info_2 struct
4192 ********************************************************************/
4194 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4197 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4199 print_status_struct status;
4201 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4204 count = print_queue_length(snum, &status);
4206 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4207 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4208 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4209 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4210 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4212 if (*ntprinter->info_2->comment == '\0')
4213 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4215 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4217 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4218 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4219 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4220 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4221 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4223 printer->attributes = ntprinter->info_2->attributes;
4225 printer->priority = ntprinter->info_2->priority; /* priority */
4226 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4227 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4228 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4229 printer->status = nt_printq_status(status.status); /* status */
4230 printer->cjobs = count; /* jobs */
4231 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4233 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4234 DEBUG(8, ("Returning NULL Devicemode!\n"));
4237 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4238 /* steal the printer info sec_desc structure. [badly done]. */
4239 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4240 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4241 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4242 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4245 printer->secdesc = NULL;
4248 free_a_printer(&ntprinter, 2);
4252 /********************************************************************
4253 * construct_printer_info_3
4254 * fill a printer_info_3 struct
4255 ********************************************************************/
4257 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4259 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4260 PRINTER_INFO_3 *printer = NULL;
4262 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4266 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4267 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4271 ZERO_STRUCTP(printer);
4273 printer->flags = 4; /* These are the components of the SD we are returning. */
4274 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4275 /* steal the printer info sec_desc structure. [badly done]. */
4276 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4280 * Set the flags for the components we are returning.
4283 if (printer->secdesc->owner_sid)
4284 printer->flags |= OWNER_SECURITY_INFORMATION;
4286 if (printer->secdesc->grp_sid)
4287 printer->flags |= GROUP_SECURITY_INFORMATION;
4289 if (printer->secdesc->dacl)
4290 printer->flags |= DACL_SECURITY_INFORMATION;
4292 if (printer->secdesc->sacl)
4293 printer->flags |= SACL_SECURITY_INFORMATION;
4296 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4297 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4298 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4301 free_a_printer(&ntprinter, 2);
4303 *pp_printer = printer;
4307 /********************************************************************
4308 * construct_printer_info_4
4309 * fill a printer_info_4 struct
4310 ********************************************************************/
4312 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4314 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4316 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4319 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4320 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4321 printer->attributes = ntprinter->info_2->attributes;
4323 free_a_printer(&ntprinter, 2);
4327 /********************************************************************
4328 * construct_printer_info_5
4329 * fill a printer_info_5 struct
4330 ********************************************************************/
4332 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4334 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4336 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4339 init_unistr(&printer->printername, ntprinter->info_2->printername);
4340 init_unistr(&printer->portname, ntprinter->info_2->portname);
4341 printer->attributes = ntprinter->info_2->attributes;
4343 /* these two are not used by NT+ according to MSDN */
4345 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4346 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4348 free_a_printer(&ntprinter, 2);
4353 /********************************************************************
4354 * construct_printer_info_7
4355 * fill a printer_info_7 struct
4356 ********************************************************************/
4358 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4360 char *guid_str = NULL;
4363 if (is_printer_published(print_hnd, snum, &guid)) {
4364 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4365 strupper_m(guid_str);
4366 init_unistr(&printer->guid, guid_str);
4367 printer->action = SPOOL_DS_PUBLISH;
4369 init_unistr(&printer->guid, "");
4370 printer->action = SPOOL_DS_UNPUBLISH;
4376 /********************************************************************
4377 Spoolss_enumprinters.
4378 ********************************************************************/
4380 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4384 int n_services=lp_numservices();
4385 PRINTER_INFO_1 *tp, *printers=NULL;
4386 PRINTER_INFO_1 current_prt;
4388 DEBUG(4,("enum_all_printers_info_1\n"));
4390 for (snum=0; snum<n_services; snum++) {
4391 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4392 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4394 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4395 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4396 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4397 SAFE_FREE(printers);
4402 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4404 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4410 /* check the required size. */
4411 for (i=0; i<*returned; i++)
4412 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4414 if (!alloc_buffer_size(buffer, *needed))
4415 return WERR_INSUFFICIENT_BUFFER;
4417 /* fill the buffer with the structures */
4418 for (i=0; i<*returned; i++)
4419 smb_io_printer_info_1("", buffer, &printers[i], 0);
4422 SAFE_FREE(printers);
4424 if (*needed > offered) {
4426 return WERR_INSUFFICIENT_BUFFER;
4432 /********************************************************************
4433 enum_all_printers_info_1_local.
4434 *********************************************************************/
4436 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4438 DEBUG(4,("enum_all_printers_info_1_local\n"));
4440 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4443 /********************************************************************
4444 enum_all_printers_info_1_name.
4445 *********************************************************************/
4447 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4451 DEBUG(4,("enum_all_printers_info_1_name\n"));
4453 if ((name[0] == '\\') && (name[1] == '\\'))
4456 if (is_myname_or_ipaddr(s)) {
4457 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4460 return WERR_INVALID_NAME;
4463 /********************************************************************
4464 enum_all_printers_info_1_remote.
4465 *********************************************************************/
4467 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4469 PRINTER_INFO_1 *printer;
4470 fstring printername;
4473 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4475 /* JFM: currently it's more a place holder than anything else.
4476 * In the spooler world there is a notion of server registration.
4477 * the print servers are registring (sp ?) on the PDC (in the same domain)
4479 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4482 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4487 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4488 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4489 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4491 init_unistr(&printer->description, desc);
4492 init_unistr(&printer->name, printername);
4493 init_unistr(&printer->comment, comment);
4494 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4496 /* check the required size. */
4497 *needed += spoolss_size_printer_info_1(printer);
4499 if (!alloc_buffer_size(buffer, *needed)) {
4501 return WERR_INSUFFICIENT_BUFFER;
4504 /* fill the buffer with the structures */
4505 smb_io_printer_info_1("", buffer, printer, 0);
4510 if (*needed > offered) {
4512 return WERR_INSUFFICIENT_BUFFER;
4518 /********************************************************************
4519 enum_all_printers_info_1_network.
4520 *********************************************************************/
4522 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4526 DEBUG(4,("enum_all_printers_info_1_network\n"));
4528 /* If we respond to a enum_printers level 1 on our name with flags
4529 set to PRINTER_ENUM_REMOTE with a list of printers then these
4530 printers incorrectly appear in the APW browse list.
4531 Specifically the printers for the server appear at the workgroup
4532 level where all the other servers in the domain are
4533 listed. Windows responds to this call with a
4534 WERR_CAN_NOT_COMPLETE so we should do the same. */
4536 if (name[0] == '\\' && name[1] == '\\')
4539 if (is_myname_or_ipaddr(s))
4540 return WERR_CAN_NOT_COMPLETE;
4542 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4545 /********************************************************************
4546 * api_spoolss_enumprinters
4548 * called from api_spoolss_enumprinters (see this to understand)
4549 ********************************************************************/
4551 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4555 int n_services=lp_numservices();
4556 PRINTER_INFO_2 *tp, *printers=NULL;
4557 PRINTER_INFO_2 current_prt;
4559 for (snum=0; snum<n_services; snum++) {
4560 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4561 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4563 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4564 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4565 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4566 SAFE_FREE(printers);
4571 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4572 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4578 /* check the required size. */
4579 for (i=0; i<*returned; i++)
4580 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4582 if (!alloc_buffer_size(buffer, *needed)) {
4583 for (i=0; i<*returned; i++) {
4584 free_devmode(printers[i].devmode);
4586 SAFE_FREE(printers);
4587 return WERR_INSUFFICIENT_BUFFER;
4590 /* fill the buffer with the structures */
4591 for (i=0; i<*returned; i++)
4592 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4595 for (i=0; i<*returned; i++) {
4596 free_devmode(printers[i].devmode);
4598 SAFE_FREE(printers);
4600 if (*needed > offered) {
4602 return WERR_INSUFFICIENT_BUFFER;
4608 /********************************************************************
4609 * handle enumeration of printers at level 1
4610 ********************************************************************/
4612 static WERROR enumprinters_level1( uint32 flags, fstring name,
4613 NEW_BUFFER *buffer, uint32 offered,
4614 uint32 *needed, uint32 *returned)
4616 /* Not all the flags are equals */
4618 if (flags & PRINTER_ENUM_LOCAL)
4619 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4621 if (flags & PRINTER_ENUM_NAME)
4622 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4624 if (flags & PRINTER_ENUM_REMOTE)
4625 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4627 if (flags & PRINTER_ENUM_NETWORK)
4628 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4630 return WERR_OK; /* NT4sp5 does that */
4633 /********************************************************************
4634 * handle enumeration of printers at level 2
4635 ********************************************************************/
4637 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4638 NEW_BUFFER *buffer, uint32 offered,
4639 uint32 *needed, uint32 *returned)
4641 char *s = servername;
4643 if (flags & PRINTER_ENUM_LOCAL) {
4644 return enum_all_printers_info_2(buffer, offered, needed, returned);
4647 if (flags & PRINTER_ENUM_NAME) {
4648 if ((servername[0] == '\\') && (servername[1] == '\\'))
4650 if (is_myname_or_ipaddr(s))
4651 return enum_all_printers_info_2(buffer, offered, needed, returned);
4653 return WERR_INVALID_NAME;
4656 if (flags & PRINTER_ENUM_REMOTE)
4657 return WERR_UNKNOWN_LEVEL;
4662 /********************************************************************
4663 * handle enumeration of printers at level 5
4664 ********************************************************************/
4666 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4667 NEW_BUFFER *buffer, uint32 offered,
4668 uint32 *needed, uint32 *returned)
4670 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4674 /********************************************************************
4675 * api_spoolss_enumprinters
4677 * called from api_spoolss_enumprinters (see this to understand)
4678 ********************************************************************/
4680 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4682 uint32 flags = q_u->flags;
4683 UNISTR2 *servername = &q_u->servername;
4684 uint32 level = q_u->level;
4685 NEW_BUFFER *buffer = NULL;
4686 uint32 offered = q_u->offered;
4687 uint32 *needed = &r_u->needed;
4688 uint32 *returned = &r_u->returned;
4692 /* that's an [in out] buffer */
4693 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4694 buffer = r_u->buffer;
4696 DEBUG(4,("_spoolss_enumprinters\n"));
4703 * flags==PRINTER_ENUM_NAME
4704 * if name=="" then enumerates all printers
4705 * if name!="" then enumerate the printer
4706 * flags==PRINTER_ENUM_REMOTE
4707 * name is NULL, enumerate printers
4708 * Level 2: name!="" enumerates printers, name can't be NULL
4709 * Level 3: doesn't exist
4710 * Level 4: does a local registry lookup
4711 * Level 5: same as Level 2
4714 unistr2_to_ascii(name, servername, sizeof(name)-1);
4719 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4721 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4723 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4728 return WERR_UNKNOWN_LEVEL;
4731 /****************************************************************************
4732 ****************************************************************************/
4734 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4736 PRINTER_INFO_0 *printer=NULL;
4738 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4741 construct_printer_info_0(print_hnd, printer, snum);
4743 /* check the required size. */
4744 *needed += spoolss_size_printer_info_0(printer);
4746 if (!alloc_buffer_size(buffer, *needed)) {
4748 return WERR_INSUFFICIENT_BUFFER;
4751 /* fill the buffer with the structures */
4752 smb_io_printer_info_0("", buffer, printer, 0);
4757 if (*needed > offered) {
4758 return WERR_INSUFFICIENT_BUFFER;
4764 /****************************************************************************
4765 ****************************************************************************/
4767 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4769 PRINTER_INFO_1 *printer=NULL;
4771 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4774 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4776 /* check the required size. */
4777 *needed += spoolss_size_printer_info_1(printer);
4779 if (!alloc_buffer_size(buffer, *needed)) {
4781 return WERR_INSUFFICIENT_BUFFER;
4784 /* fill the buffer with the structures */
4785 smb_io_printer_info_1("", buffer, printer, 0);
4790 if (*needed > offered) {
4791 return WERR_INSUFFICIENT_BUFFER;
4797 /****************************************************************************
4798 ****************************************************************************/
4800 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4802 PRINTER_INFO_2 *printer=NULL;
4804 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4807 construct_printer_info_2(print_hnd, printer, snum);
4809 /* check the required size. */
4810 *needed += spoolss_size_printer_info_2(printer);
4812 if (!alloc_buffer_size(buffer, *needed)) {
4813 free_printer_info_2(printer);
4814 return WERR_INSUFFICIENT_BUFFER;
4817 /* fill the buffer with the structures */
4818 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4819 free_printer_info_2(printer);
4824 free_printer_info_2(printer);
4826 if (*needed > offered) {
4827 return WERR_INSUFFICIENT_BUFFER;
4833 /****************************************************************************
4834 ****************************************************************************/
4836 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4838 PRINTER_INFO_3 *printer=NULL;
4840 if (!construct_printer_info_3(print_hnd, &printer, snum))
4843 /* check the required size. */
4844 *needed += spoolss_size_printer_info_3(printer);
4846 if (!alloc_buffer_size(buffer, *needed)) {
4847 free_printer_info_3(printer);
4848 return WERR_INSUFFICIENT_BUFFER;
4851 /* fill the buffer with the structures */
4852 smb_io_printer_info_3("", buffer, printer, 0);
4855 free_printer_info_3(printer);
4857 if (*needed > offered) {
4858 return WERR_INSUFFICIENT_BUFFER;
4864 /****************************************************************************
4865 ****************************************************************************/
4867 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4869 PRINTER_INFO_4 *printer=NULL;
4871 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4874 if (!construct_printer_info_4(print_hnd, printer, snum))
4877 /* check the required size. */
4878 *needed += spoolss_size_printer_info_4(printer);
4880 if (!alloc_buffer_size(buffer, *needed)) {
4881 free_printer_info_4(printer);
4882 return WERR_INSUFFICIENT_BUFFER;
4885 /* fill the buffer with the structures */
4886 smb_io_printer_info_4("", buffer, printer, 0);
4889 free_printer_info_4(printer);
4891 if (*needed > offered) {
4892 return WERR_INSUFFICIENT_BUFFER;
4898 /****************************************************************************
4899 ****************************************************************************/
4901 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4903 PRINTER_INFO_5 *printer=NULL;
4905 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4908 if (!construct_printer_info_5(print_hnd, printer, snum))
4911 /* check the required size. */
4912 *needed += spoolss_size_printer_info_5(printer);
4914 if (!alloc_buffer_size(buffer, *needed)) {
4915 free_printer_info_5(printer);
4916 return WERR_INSUFFICIENT_BUFFER;
4919 /* fill the buffer with the structures */
4920 smb_io_printer_info_5("", buffer, printer, 0);
4923 free_printer_info_5(printer);
4925 if (*needed > offered) {
4926 return WERR_INSUFFICIENT_BUFFER;
4932 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4934 PRINTER_INFO_7 *printer=NULL;
4936 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4939 if (!construct_printer_info_7(print_hnd, printer, snum))
4942 /* check the required size. */
4943 *needed += spoolss_size_printer_info_7(printer);
4945 if (!alloc_buffer_size(buffer, *needed)) {
4946 free_printer_info_7(printer);
4947 return WERR_INSUFFICIENT_BUFFER;
4950 /* fill the buffer with the structures */
4951 smb_io_printer_info_7("", buffer, printer, 0);
4954 free_printer_info_7(printer);
4956 if (*needed > offered) {
4957 return WERR_INSUFFICIENT_BUFFER;
4963 /****************************************************************************
4964 ****************************************************************************/
4966 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4968 POLICY_HND *handle = &q_u->handle;
4969 uint32 level = q_u->level;
4970 NEW_BUFFER *buffer = NULL;
4971 uint32 offered = q_u->offered;
4972 uint32 *needed = &r_u->needed;
4973 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4977 /* that's an [in out] buffer */
4978 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4979 buffer = r_u->buffer;
4983 if (!get_printer_snum(p, handle, &snum))
4988 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4990 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4992 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4994 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4996 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4998 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5000 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5002 return WERR_UNKNOWN_LEVEL;
5005 /********************************************************************
5006 * fill a DRIVER_INFO_1 struct
5007 ********************************************************************/
5009 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5011 init_unistr( &info->name, driver.info_3->name);
5014 /********************************************************************
5015 * construct_printer_driver_info_1
5016 ********************************************************************/
5018 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5020 NT_PRINTER_INFO_LEVEL *printer = NULL;
5021 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5023 ZERO_STRUCT(driver);
5025 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5026 return WERR_INVALID_PRINTER_NAME;
5028 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5029 return WERR_UNKNOWN_PRINTER_DRIVER;
5031 fill_printer_driver_info_1(info, driver, servername, architecture);
5033 free_a_printer(&printer,2);
5038 /********************************************************************
5039 * construct_printer_driver_info_2
5040 * fill a printer_info_2 struct
5041 ********************************************************************/
5043 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5047 info->version=driver.info_3->cversion;
5049 init_unistr( &info->name, driver.info_3->name );
5050 init_unistr( &info->architecture, driver.info_3->environment );
5053 if (strlen(driver.info_3->driverpath)) {
5054 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5055 init_unistr( &info->driverpath, temp );
5057 init_unistr( &info->driverpath, "" );
5059 if (strlen(driver.info_3->datafile)) {
5060 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5061 init_unistr( &info->datafile, temp );
5063 init_unistr( &info->datafile, "" );
5065 if (strlen(driver.info_3->configfile)) {
5066 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5067 init_unistr( &info->configfile, temp );
5069 init_unistr( &info->configfile, "" );
5072 /********************************************************************
5073 * construct_printer_driver_info_2
5074 * fill a printer_info_2 struct
5075 ********************************************************************/
5077 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5079 NT_PRINTER_INFO_LEVEL *printer = NULL;
5080 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5082 ZERO_STRUCT(printer);
5083 ZERO_STRUCT(driver);
5085 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5086 return WERR_INVALID_PRINTER_NAME;
5088 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5089 return WERR_UNKNOWN_PRINTER_DRIVER;
5091 fill_printer_driver_info_2(info, driver, servername);
5093 free_a_printer(&printer,2);
5098 /********************************************************************
5099 * copy a strings array and convert to UNICODE
5101 * convert an array of ascii string to a UNICODE string
5102 ********************************************************************/
5104 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5112 DEBUG(6,("init_unistr_array\n"));
5123 v = ""; /* hack to handle null lists */
5126 /* hack to allow this to be used in places other than when generating
5127 the list of dependent files */
5130 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5134 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5136 /* add one extra unit16 for the second terminating NULL */
5138 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5139 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5147 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5152 /* special case for ""; we need to add both NULL's here */
5154 (*uni_array)[j++]=0x0000;
5155 (*uni_array)[j]=0x0000;
5158 DEBUGADD(6,("last one:done\n"));
5160 /* return size of array in uint16's */
5165 /********************************************************************
5166 * construct_printer_info_3
5167 * fill a printer_info_3 struct
5168 ********************************************************************/
5170 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5176 info->version=driver.info_3->cversion;
5178 init_unistr( &info->name, driver.info_3->name );
5179 init_unistr( &info->architecture, driver.info_3->environment );
5181 if (strlen(driver.info_3->driverpath)) {
5182 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5183 init_unistr( &info->driverpath, temp );
5185 init_unistr( &info->driverpath, "" );
5187 if (strlen(driver.info_3->datafile)) {
5188 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5189 init_unistr( &info->datafile, temp );
5191 init_unistr( &info->datafile, "" );
5193 if (strlen(driver.info_3->configfile)) {
5194 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5195 init_unistr( &info->configfile, temp );
5197 init_unistr( &info->configfile, "" );
5199 if (strlen(driver.info_3->helpfile)) {
5200 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5201 init_unistr( &info->helpfile, temp );
5203 init_unistr( &info->helpfile, "" );
5205 init_unistr( &info->monitorname, driver.info_3->monitorname );
5206 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5208 info->dependentfiles=NULL;
5209 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5212 /********************************************************************
5213 * construct_printer_info_3
5214 * fill a printer_info_3 struct
5215 ********************************************************************/
5217 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5219 NT_PRINTER_INFO_LEVEL *printer = NULL;
5220 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5222 ZERO_STRUCT(driver);
5224 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5225 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5226 if (!W_ERROR_IS_OK(status))
5227 return WERR_INVALID_PRINTER_NAME;
5229 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5230 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5235 * I put this code in during testing. Helpful when commenting out the
5236 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5237 * as win2k always queries the driver using an infor level of 6.
5238 * I've left it in (but ifdef'd out) because I'll probably
5239 * use it in experimentation again in the future. --jerry 22/01/2002
5242 if (!W_ERROR_IS_OK(status)) {
5244 * Is this a W2k client ?
5247 /* Yes - try again with a WinNT driver. */
5249 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5250 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5254 if (!W_ERROR_IS_OK(status)) {
5255 free_a_printer(&printer,2);
5256 return WERR_UNKNOWN_PRINTER_DRIVER;
5264 fill_printer_driver_info_3(info, driver, servername);
5266 free_a_printer(&printer,2);
5271 /********************************************************************
5272 * construct_printer_info_6
5273 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5274 ********************************************************************/
5276 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5282 memset(&nullstr, '\0', sizeof(fstring));
5284 info->version=driver.info_3->cversion;
5286 init_unistr( &info->name, driver.info_3->name );
5287 init_unistr( &info->architecture, driver.info_3->environment );
5289 if (strlen(driver.info_3->driverpath)) {
5290 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5291 init_unistr( &info->driverpath, temp );
5293 init_unistr( &info->driverpath, "" );
5295 if (strlen(driver.info_3->datafile)) {
5296 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5297 init_unistr( &info->datafile, temp );
5299 init_unistr( &info->datafile, "" );
5301 if (strlen(driver.info_3->configfile)) {
5302 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5303 init_unistr( &info->configfile, temp );
5305 init_unistr( &info->configfile, "" );
5307 if (strlen(driver.info_3->helpfile)) {
5308 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5309 init_unistr( &info->helpfile, temp );
5311 init_unistr( &info->helpfile, "" );
5313 init_unistr( &info->monitorname, driver.info_3->monitorname );
5314 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5316 info->dependentfiles = NULL;
5317 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5319 info->previousdrivernames=NULL;
5320 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5322 info->driver_date.low=0;
5323 info->driver_date.high=0;
5326 info->driver_version_low=0;
5327 info->driver_version_high=0;
5329 init_unistr( &info->mfgname, "");
5330 init_unistr( &info->oem_url, "");
5331 init_unistr( &info->hardware_id, "");
5332 init_unistr( &info->provider, "");
5335 /********************************************************************
5336 * construct_printer_info_6
5337 * fill a printer_info_6 struct
5338 ********************************************************************/
5340 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5341 fstring servername, fstring architecture, uint32 version)
5343 NT_PRINTER_INFO_LEVEL *printer = NULL;
5344 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5347 ZERO_STRUCT(driver);
5349 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5351 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5353 if (!W_ERROR_IS_OK(status))
5354 return WERR_INVALID_PRINTER_NAME;
5356 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5358 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5360 if (!W_ERROR_IS_OK(status))
5363 * Is this a W2k client ?
5367 free_a_printer(&printer,2);
5368 return WERR_UNKNOWN_PRINTER_DRIVER;
5371 /* Yes - try again with a WinNT driver. */
5373 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5374 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5375 if (!W_ERROR_IS_OK(status)) {
5376 free_a_printer(&printer,2);
5377 return WERR_UNKNOWN_PRINTER_DRIVER;
5381 fill_printer_driver_info_6(info, driver, servername);
5383 free_a_printer(&printer,2);
5384 free_a_printer_driver(driver, 3);
5389 /****************************************************************************
5390 ****************************************************************************/
5392 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5394 SAFE_FREE(info->dependentfiles);
5397 /****************************************************************************
5398 ****************************************************************************/
5400 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5402 SAFE_FREE(info->dependentfiles);
5406 /****************************************************************************
5407 ****************************************************************************/
5409 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5411 DRIVER_INFO_1 *info=NULL;
5414 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5417 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5418 if (!W_ERROR_IS_OK(status)) {
5423 /* check the required size. */
5424 *needed += spoolss_size_printer_driver_info_1(info);
5426 if (!alloc_buffer_size(buffer, *needed)) {
5428 return WERR_INSUFFICIENT_BUFFER;
5431 /* fill the buffer with the structures */
5432 smb_io_printer_driver_info_1("", buffer, info, 0);
5437 if (*needed > offered)
5438 return WERR_INSUFFICIENT_BUFFER;
5443 /****************************************************************************
5444 ****************************************************************************/
5446 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5448 DRIVER_INFO_2 *info=NULL;
5451 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5454 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5455 if (!W_ERROR_IS_OK(status)) {
5460 /* check the required size. */
5461 *needed += spoolss_size_printer_driver_info_2(info);
5463 if (!alloc_buffer_size(buffer, *needed)) {
5465 return WERR_INSUFFICIENT_BUFFER;
5468 /* fill the buffer with the structures */
5469 smb_io_printer_driver_info_2("", buffer, info, 0);
5474 if (*needed > offered)
5475 return WERR_INSUFFICIENT_BUFFER;
5480 /****************************************************************************
5481 ****************************************************************************/
5483 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5490 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5491 if (!W_ERROR_IS_OK(status)) {
5495 /* check the required size. */
5496 *needed += spoolss_size_printer_driver_info_3(&info);
5498 if (!alloc_buffer_size(buffer, *needed)) {
5499 free_printer_driver_info_3(&info);
5500 return WERR_INSUFFICIENT_BUFFER;
5503 /* fill the buffer with the structures */
5504 smb_io_printer_driver_info_3("", buffer, &info, 0);
5506 free_printer_driver_info_3(&info);
5508 if (*needed > offered)
5509 return WERR_INSUFFICIENT_BUFFER;
5514 /****************************************************************************
5515 ****************************************************************************/
5517 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5524 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5525 if (!W_ERROR_IS_OK(status)) {
5529 /* check the required size. */
5530 *needed += spoolss_size_printer_driver_info_6(&info);
5532 if (!alloc_buffer_size(buffer, *needed)) {
5533 free_printer_driver_info_6(&info);
5534 return WERR_INSUFFICIENT_BUFFER;
5537 /* fill the buffer with the structures */
5538 smb_io_printer_driver_info_6("", buffer, &info, 0);
5540 free_printer_driver_info_6(&info);
5542 if (*needed > offered)
5543 return WERR_INSUFFICIENT_BUFFER;
5548 /****************************************************************************
5549 ****************************************************************************/
5551 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5553 POLICY_HND *handle = &q_u->handle;
5554 UNISTR2 *uni_arch = &q_u->architecture;
5555 uint32 level = q_u->level;
5556 uint32 clientmajorversion = q_u->clientmajorversion;
5557 NEW_BUFFER *buffer = NULL;
5558 uint32 offered = q_u->offered;
5559 uint32 *needed = &r_u->needed;
5560 uint32 *servermajorversion = &r_u->servermajorversion;
5561 uint32 *serverminorversion = &r_u->serverminorversion;
5564 fstring architecture;
5567 /* that's an [in out] buffer */
5568 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5569 buffer = r_u->buffer;
5571 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5574 *servermajorversion = 0;
5575 *serverminorversion = 0;
5577 fstrcpy(servername, get_called_name());
5578 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5580 if (!get_printer_snum(p, handle, &snum))
5585 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5587 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5589 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5591 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5594 return WERR_UNKNOWN_LEVEL;
5597 /****************************************************************************
5598 ****************************************************************************/
5600 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5602 POLICY_HND *handle = &q_u->handle;
5604 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5607 DEBUG(3,("Error in startpageprinter printer handle\n"));
5611 Printer->page_started=True;
5615 /****************************************************************************
5616 ****************************************************************************/
5618 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5620 POLICY_HND *handle = &q_u->handle;
5623 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5626 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5630 if (!get_printer_snum(p, handle, &snum))
5633 Printer->page_started=False;
5634 print_job_endpage(snum, Printer->jobid);
5639 /********************************************************************
5640 * api_spoolss_getprinter
5641 * called from the spoolss dispatcher
5643 ********************************************************************/
5645 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5647 POLICY_HND *handle = &q_u->handle;
5648 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5649 uint32 *jobid = &r_u->jobid;
5651 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5655 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5656 struct current_user user;
5659 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5663 get_current_user(&user, p);
5666 * a nice thing with NT is it doesn't listen to what you tell it.
5667 * when asked to send _only_ RAW datas, it tries to send datas
5670 * So I add checks like in NT Server ...
5673 if (info_1->p_datatype != 0) {
5674 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5675 if (strcmp(datatype, "RAW") != 0) {
5677 return WERR_INVALID_DATATYPE;
5681 /* get the share number of the printer */
5682 if (!get_printer_snum(p, handle, &snum)) {
5686 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5688 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5690 /* An error occured in print_job_start() so return an appropriate
5693 if (Printer->jobid == -1) {
5694 return map_werror_from_unix(errno);
5697 Printer->document_started=True;
5698 (*jobid) = Printer->jobid;
5703 /********************************************************************
5704 * api_spoolss_getprinter
5705 * called from the spoolss dispatcher
5707 ********************************************************************/
5709 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5711 POLICY_HND *handle = &q_u->handle;
5713 return _spoolss_enddocprinter_internal(p, handle);
5716 /****************************************************************************
5717 ****************************************************************************/
5719 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5721 POLICY_HND *handle = &q_u->handle;
5722 uint32 buffer_size = q_u->buffer_size;
5723 uint8 *buffer = q_u->buffer;
5724 uint32 *buffer_written = &q_u->buffer_size2;
5726 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5729 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5730 r_u->buffer_written = q_u->buffer_size2;
5734 if (!get_printer_snum(p, handle, &snum))
5737 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5738 if (*buffer_written == -1) {
5739 r_u->buffer_written = 0;
5740 if (errno == ENOSPC)
5741 return WERR_NO_SPOOL_SPACE;
5743 return WERR_ACCESS_DENIED;
5746 r_u->buffer_written = q_u->buffer_size2;
5751 /********************************************************************
5752 * api_spoolss_getprinter
5753 * called from the spoolss dispatcher
5755 ********************************************************************/
5757 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5760 struct current_user user;
5762 WERROR errcode = WERR_BADFUNC;
5763 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5765 get_current_user(&user, p);
5768 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5772 if (!get_printer_snum(p, handle, &snum))
5776 case PRINTER_CONTROL_PAUSE:
5777 if (print_queue_pause(&user, snum, &errcode)) {
5781 case PRINTER_CONTROL_RESUME:
5782 case PRINTER_CONTROL_UNPAUSE:
5783 if (print_queue_resume(&user, snum, &errcode)) {
5787 case PRINTER_CONTROL_PURGE:
5788 if (print_queue_purge(&user, snum, &errcode)) {
5793 return WERR_UNKNOWN_LEVEL;
5799 /********************************************************************
5800 * api_spoolss_abortprinter
5801 * From MSDN: "Deletes printer's spool file if printer is configured
5803 ********************************************************************/
5805 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5807 POLICY_HND *handle = &q_u->handle;
5808 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5810 struct current_user user;
5811 WERROR errcode = WERR_OK;
5814 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5818 if (!get_printer_snum(p, handle, &snum))
5821 get_current_user( &user, p );
5823 print_job_delete( &user, snum, Printer->jobid, &errcode );
5828 /********************************************************************
5829 * called by spoolss_api_setprinter
5830 * when updating a printer description
5831 ********************************************************************/
5833 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5834 const SPOOL_PRINTER_INFO_LEVEL *info,
5835 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5837 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5838 struct current_user user;
5842 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5844 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5845 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5846 OUR_HANDLE(handle)));
5848 result = WERR_BADFID;
5852 /* NT seems to like setting the security descriptor even though
5853 nothing may have actually changed. This causes annoying
5854 dialog boxes when the user doesn't have permission to change
5855 the security descriptor. */
5857 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5859 if (DEBUGLEVEL >= 10) {
5863 the_acl = old_secdesc_ctr->sec->dacl;
5864 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5865 PRINTERNAME(snum), the_acl->num_aces));
5867 for (i = 0; i < the_acl->num_aces; i++) {
5870 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5872 DEBUG(10, ("%s 0x%08x\n", sid_str,
5873 the_acl->ace[i].info.mask));
5876 the_acl = secdesc_ctr->sec->dacl;
5879 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5880 PRINTERNAME(snum), the_acl->num_aces));
5882 for (i = 0; i < the_acl->num_aces; i++) {
5885 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5887 DEBUG(10, ("%s 0x%08x\n", sid_str,
5888 the_acl->ace[i].info.mask));
5891 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5895 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5897 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5902 /* Work out which user is performing the operation */
5904 get_current_user(&user, p);
5906 /* Check the user has permissions to change the security
5907 descriptor. By experimentation with two NT machines, the user
5908 requires Full Access to the printer to change security
5911 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5912 result = WERR_ACCESS_DENIED;
5916 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5923 /********************************************************************
5924 Do Samba sanity checks on a printer info struct.
5925 this has changed purpose: it now "canonicalises" printer
5926 info from a client rather than just checking it is correct
5927 ********************************************************************/
5929 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5931 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5932 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5934 /* we force some elements to "correct" values */
5935 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5936 fstrcpy(info->sharename, lp_servicename(snum));
5937 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5938 get_called_name(), info->sharename);
5939 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5945 /****************************************************************************
5946 ****************************************************************************/
5948 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5950 extern userdom_struct current_user_info;
5951 char *cmd = lp_addprinter_cmd();
5957 fstring remote_machine = "%m";
5959 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5961 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5962 cmd, printer->info_2->printername, printer->info_2->sharename,
5963 printer->info_2->portname, printer->info_2->drivername,
5964 printer->info_2->location, printer->info_2->comment, remote_machine);
5966 DEBUG(10,("Running [%s]\n", command));
5967 ret = smbrun(command, &fd);
5968 DEBUGADD(10,("returned [%d]\n", ret));
5977 /* Get lines and convert them back to dos-codepage */
5978 qlines = fd_lines_load(fd, &numlines);
5979 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5983 /* Set the portname to what the script says the portname should be. */
5984 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5985 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5987 /* Send SIGHUP to process group... is there a better way? */
5990 /* reload our services immediately */
5991 reload_services( False );
5994 file_lines_free(qlines);
5998 /********************************************************************
5999 * Called by spoolss_api_setprinter
6000 * when updating a printer description.
6001 ********************************************************************/
6003 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6004 const SPOOL_PRINTER_INFO_LEVEL *info,
6005 DEVICEMODE *devmode)
6008 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6009 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6014 DEBUG(8,("update_printer\n"));
6019 result = WERR_BADFID;
6023 if (!get_printer_snum(p, handle, &snum)) {
6024 result = WERR_BADFID;
6028 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6029 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6030 result = WERR_BADFID;
6034 DEBUGADD(8,("Converting info_2 struct\n"));
6037 * convert_printer_info converts the incoming
6038 * info from the client and overwrites the info
6039 * just read from the tdb in the pointer 'printer'.
6042 if (!convert_printer_info(info, printer, level)) {
6043 result = WERR_NOMEM;
6048 /* we have a valid devmode
6049 convert it and link it*/
6051 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6052 if (!convert_devicemode(printer->info_2->printername, devmode,
6053 &printer->info_2->devmode)) {
6054 result = WERR_NOMEM;
6059 /* Do sanity check on the requested changes for Samba */
6061 if (!check_printer_ok(printer->info_2, snum)) {
6062 result = WERR_INVALID_PARAM;
6066 /* FIXME!!! If the driver has changed we really should verify that
6067 it is installed before doing much else --jerry */
6069 /* Check calling user has permission to update printer description */
6071 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6072 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6073 result = WERR_ACCESS_DENIED;
6077 /* Call addprinter hook */
6078 /* Check changes to see if this is really needed */
6080 if ( *lp_addprinter_cmd()
6081 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6082 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6083 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6084 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6086 if ( !add_printer_hook(printer) ) {
6087 result = WERR_ACCESS_DENIED;
6092 * make sure we actually reload the services after
6093 * this as smb.conf could have a new section in it
6094 * .... shouldn't .... but could
6096 reload_services(False);
6100 * When a *new* driver is bound to a printer, the drivername is used to
6101 * lookup previously saved driver initialization info, which is then
6102 * bound to the printer, simulating what happens in the Windows arch.
6104 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6106 if (!set_driver_init(printer, 2))
6108 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6109 printer->info_2->drivername));
6112 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6113 printer->info_2->drivername));
6115 notify_printer_driver(snum, printer->info_2->drivername);
6119 * flag which changes actually occured. This is a small subset of
6120 * all the possible changes. We also have to update things in the
6124 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6125 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6126 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6127 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6129 notify_printer_comment(snum, printer->info_2->comment);
6132 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6133 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6134 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6135 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6136 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6137 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6139 notify_printer_sharename(snum, printer->info_2->sharename);
6142 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6143 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6144 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6145 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6147 notify_printer_port(snum, printer->info_2->portname);
6150 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6151 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6152 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6153 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6155 notify_printer_location(snum, printer->info_2->location);
6158 /* here we need to update some more DsSpooler keys */
6159 /* uNCName, serverName, shortServerName */
6161 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6162 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6163 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6164 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6165 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6167 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6168 global_myname(), printer->info_2->sharename );
6169 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6170 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6171 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6173 /* Update printer info */
6174 result = mod_a_printer(*printer, 2);
6177 free_a_printer(&printer, 2);
6178 free_a_printer(&old_printer, 2);
6184 /****************************************************************************
6185 ****************************************************************************/
6186 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6187 const SPOOL_PRINTER_INFO_LEVEL *info)
6190 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6192 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6194 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6199 if (!get_printer_snum(p, handle, &snum))
6202 nt_printer_publish(Printer, snum, info7->action);
6206 return WERR_UNKNOWN_LEVEL;
6209 /****************************************************************************
6210 ****************************************************************************/
6212 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6214 POLICY_HND *handle = &q_u->handle;
6215 uint32 level = q_u->level;
6216 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6217 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6218 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6219 uint32 command = q_u->command;
6221 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6224 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6228 /* check the level */
6231 return control_printer(handle, command, p);
6233 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6235 return update_printer_sec(handle, level, info, p,
6238 return publish_or_unpublish_printer(p, handle, info);
6240 return WERR_UNKNOWN_LEVEL;
6244 /****************************************************************************
6245 ****************************************************************************/
6247 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6249 POLICY_HND *handle = &q_u->handle;
6250 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6253 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6257 if (Printer->notify.client_connected==True) {
6260 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6262 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6263 !get_printer_snum(p, handle, &snum) )
6266 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6269 Printer->notify.flags=0;
6270 Printer->notify.options=0;
6271 Printer->notify.localmachine[0]='\0';
6272 Printer->notify.printerlocal=0;
6273 if (Printer->notify.option)
6274 free_spool_notify_option(&Printer->notify.option);
6275 Printer->notify.client_connected=False;
6280 /****************************************************************************
6281 ****************************************************************************/
6283 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6285 /* that's an [in out] buffer (despite appearences to the contrary) */
6286 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6289 return WERR_INVALID_PARAM; /* this is what a NT server
6290 returns for AddJob. AddJob
6291 must fail on non-local
6295 /****************************************************************************
6296 ****************************************************************************/
6298 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6299 int position, int snum)
6305 t=gmtime(&queue->time);
6306 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6308 job_info->jobid=queue->job;
6309 init_unistr(&job_info->printername, lp_servicename(snum));
6310 init_unistr(&job_info->machinename, temp_name);
6311 init_unistr(&job_info->username, queue->fs_user);
6312 init_unistr(&job_info->document, queue->fs_file);
6313 init_unistr(&job_info->datatype, "RAW");
6314 init_unistr(&job_info->text_status, "");
6315 job_info->status=nt_printj_status(queue->status);
6316 job_info->priority=queue->priority;
6317 job_info->position=position;
6318 job_info->totalpages=queue->page_count;
6319 job_info->pagesprinted=0;
6321 make_systemtime(&job_info->submitted, t);
6324 /****************************************************************************
6325 ****************************************************************************/
6327 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6328 int position, int snum,
6329 NT_PRINTER_INFO_LEVEL *ntprinter,
6330 DEVICEMODE *devmode)
6335 t=gmtime(&queue->time);
6336 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6338 job_info->jobid=queue->job;
6340 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6342 init_unistr(&job_info->machinename, temp_name);
6343 init_unistr(&job_info->username, queue->fs_user);
6344 init_unistr(&job_info->document, queue->fs_file);
6345 init_unistr(&job_info->notifyname, queue->fs_user);
6346 init_unistr(&job_info->datatype, "RAW");
6347 init_unistr(&job_info->printprocessor, "winprint");
6348 init_unistr(&job_info->parameters, "");
6349 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6350 init_unistr(&job_info->text_status, "");
6352 /* and here the security descriptor */
6354 job_info->status=nt_printj_status(queue->status);
6355 job_info->priority=queue->priority;
6356 job_info->position=position;
6357 job_info->starttime=0;
6358 job_info->untiltime=0;
6359 job_info->totalpages=queue->page_count;
6360 job_info->size=queue->size;
6361 make_systemtime(&(job_info->submitted), t);
6362 job_info->timeelapsed=0;
6363 job_info->pagesprinted=0;
6365 job_info->devmode = devmode;
6370 /****************************************************************************
6371 Enumjobs at level 1.
6372 ****************************************************************************/
6374 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6375 NEW_BUFFER *buffer, uint32 offered,
6376 uint32 *needed, uint32 *returned)
6381 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6388 for (i=0; i<*returned; i++)
6389 fill_job_info_1(&info[i], &queue[i], i, snum);
6393 /* check the required size. */
6394 for (i=0; i<*returned; i++)
6395 (*needed) += spoolss_size_job_info_1(&info[i]);
6397 if (!alloc_buffer_size(buffer, *needed)) {
6399 return WERR_INSUFFICIENT_BUFFER;
6402 /* fill the buffer with the structures */
6403 for (i=0; i<*returned; i++)
6404 smb_io_job_info_1("", buffer, &info[i], 0);
6409 if (*needed > offered) {
6411 return WERR_INSUFFICIENT_BUFFER;
6417 /****************************************************************************
6418 Enumjobs at level 2.
6419 ****************************************************************************/
6421 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6422 NEW_BUFFER *buffer, uint32 offered,
6423 uint32 *needed, uint32 *returned)
6425 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6426 JOB_INFO_2 *info = NULL;
6429 DEVICEMODE *devmode = NULL;
6431 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6434 result = WERR_NOMEM;
6438 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6439 if (!W_ERROR_IS_OK(result)) {
6444 /* this should not be a failure condition if the devmode is NULL */
6446 devmode = construct_dev_mode(snum);
6448 for (i=0; i<*returned; i++)
6449 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6452 free_a_printer(&ntprinter, 2);
6455 /* check the required size. */
6456 for (i=0; i<*returned; i++)
6457 (*needed) += spoolss_size_job_info_2(&info[i]);
6459 if (*needed > offered) {
6461 result = WERR_INSUFFICIENT_BUFFER;
6465 if (!alloc_buffer_size(buffer, *needed)) {
6467 result = WERR_INSUFFICIENT_BUFFER;
6471 /* fill the buffer with the structures */
6472 for (i=0; i<*returned; i++)
6473 smb_io_job_info_2("", buffer, &info[i], 0);
6478 free_a_printer(&ntprinter, 2);
6479 free_devmode(devmode);
6487 /****************************************************************************
6489 ****************************************************************************/
6491 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6493 POLICY_HND *handle = &q_u->handle;
6494 uint32 level = q_u->level;
6495 NEW_BUFFER *buffer = NULL;
6496 uint32 offered = q_u->offered;
6497 uint32 *needed = &r_u->needed;
6498 uint32 *returned = &r_u->returned;
6502 print_status_struct prt_status;
6503 print_queue_struct *queue=NULL;
6505 /* that's an [in out] buffer */
6506 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6507 buffer = r_u->buffer;
6509 DEBUG(4,("_spoolss_enumjobs\n"));
6514 if (!get_printer_snum(p, handle, &snum))
6517 *returned = print_queue_status(snum, &queue, &prt_status);
6518 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6520 if (*returned == 0) {
6521 set_enumjobs_timestamp(snum);
6528 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6529 set_enumjobs_timestamp(snum);
6532 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6533 set_enumjobs_timestamp(snum);
6538 return WERR_UNKNOWN_LEVEL;
6542 /****************************************************************************
6543 ****************************************************************************/
6545 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6550 /****************************************************************************
6551 ****************************************************************************/
6553 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6555 POLICY_HND *handle = &q_u->handle;
6556 uint32 jobid = q_u->jobid;
6557 uint32 command = q_u->command;
6559 struct current_user user;
6561 WERROR errcode = WERR_BADFUNC;
6563 if (!get_printer_snum(p, handle, &snum)) {
6567 if (!print_job_exists(snum, jobid)) {
6568 return WERR_INVALID_PRINTER_NAME;
6571 get_current_user(&user, p);
6574 case JOB_CONTROL_CANCEL:
6575 case JOB_CONTROL_DELETE:
6576 if (print_job_delete(&user, snum, jobid, &errcode)) {
6580 case JOB_CONTROL_PAUSE:
6581 if (print_job_pause(&user, snum, jobid, &errcode)) {
6585 case JOB_CONTROL_RESTART:
6586 case JOB_CONTROL_RESUME:
6587 if (print_job_resume(&user, snum, jobid, &errcode)) {
6592 return WERR_UNKNOWN_LEVEL;
6598 /****************************************************************************
6599 Enumerates all printer drivers at level 1.
6600 ****************************************************************************/
6602 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6607 fstring *list = NULL;
6609 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6610 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6614 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6616 ndrivers=get_ntdrivers(&list, architecture, version);
6617 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6623 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6624 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6625 SAFE_FREE(driver_info_1);
6629 else driver_info_1 = tdi1;
6632 for (i=0; i<ndrivers; i++) {
6634 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6635 ZERO_STRUCT(driver);
6636 status = get_a_printer_driver(&driver, 3, list[i],
6637 architecture, version);
6638 if (!W_ERROR_IS_OK(status)) {
6642 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6643 free_a_printer_driver(driver, 3);
6646 *returned+=ndrivers;
6650 /* check the required size. */
6651 for (i=0; i<*returned; i++) {
6652 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6653 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6656 if (!alloc_buffer_size(buffer, *needed)) {
6657 SAFE_FREE(driver_info_1);
6658 return WERR_INSUFFICIENT_BUFFER;
6661 /* fill the buffer with the driver structures */
6662 for (i=0; i<*returned; i++) {
6663 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6664 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6667 SAFE_FREE(driver_info_1);
6669 if (*needed > offered) {
6671 return WERR_INSUFFICIENT_BUFFER;
6677 /****************************************************************************
6678 Enumerates all printer drivers at level 2.
6679 ****************************************************************************/
6681 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6686 fstring *list = NULL;
6688 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6689 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6693 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6695 ndrivers=get_ntdrivers(&list, architecture, version);
6696 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6702 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6703 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6704 SAFE_FREE(driver_info_2);
6708 else driver_info_2 = tdi2;
6711 for (i=0; i<ndrivers; i++) {
6714 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6715 ZERO_STRUCT(driver);
6716 status = get_a_printer_driver(&driver, 3, list[i],
6717 architecture, version);
6718 if (!W_ERROR_IS_OK(status)) {
6722 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6723 free_a_printer_driver(driver, 3);
6726 *returned+=ndrivers;
6730 /* check the required size. */
6731 for (i=0; i<*returned; i++) {
6732 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6733 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6736 if (!alloc_buffer_size(buffer, *needed)) {
6737 SAFE_FREE(driver_info_2);
6738 return WERR_INSUFFICIENT_BUFFER;
6741 /* fill the buffer with the form structures */
6742 for (i=0; i<*returned; i++) {
6743 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6744 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6747 SAFE_FREE(driver_info_2);
6749 if (*needed > offered) {
6751 return WERR_INSUFFICIENT_BUFFER;
6757 /****************************************************************************
6758 Enumerates all printer drivers at level 3.
6759 ****************************************************************************/
6761 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6766 fstring *list = NULL;
6768 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6769 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6773 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6775 ndrivers=get_ntdrivers(&list, architecture, version);
6776 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6782 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6783 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6784 SAFE_FREE(driver_info_3);
6788 else driver_info_3 = tdi3;
6791 for (i=0; i<ndrivers; i++) {
6794 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6795 ZERO_STRUCT(driver);
6796 status = get_a_printer_driver(&driver, 3, list[i],
6797 architecture, version);
6798 if (!W_ERROR_IS_OK(status)) {
6802 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6803 free_a_printer_driver(driver, 3);
6806 *returned+=ndrivers;
6810 /* check the required size. */
6811 for (i=0; i<*returned; i++) {
6812 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6813 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6816 if (!alloc_buffer_size(buffer, *needed)) {
6817 SAFE_FREE(driver_info_3);
6818 return WERR_INSUFFICIENT_BUFFER;
6821 /* fill the buffer with the driver structures */
6822 for (i=0; i<*returned; i++) {
6823 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6824 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6827 for (i=0; i<*returned; i++)
6828 SAFE_FREE(driver_info_3[i].dependentfiles);
6830 SAFE_FREE(driver_info_3);
6832 if (*needed > offered) {
6834 return WERR_INSUFFICIENT_BUFFER;
6840 /****************************************************************************
6841 Enumerates all printer drivers.
6842 ****************************************************************************/
6844 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6846 UNISTR2 *environment = &q_u->environment;
6847 uint32 level = q_u->level;
6848 NEW_BUFFER *buffer = NULL;
6849 uint32 offered = q_u->offered;
6850 uint32 *needed = &r_u->needed;
6851 uint32 *returned = &r_u->returned;
6853 fstring *list = NULL;
6855 fstring architecture;
6857 /* that's an [in out] buffer */
6858 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6859 buffer = r_u->buffer;
6861 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6862 fstrcpy(servername, get_called_name());
6866 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6870 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6872 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6874 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6878 return WERR_UNKNOWN_LEVEL;
6882 /****************************************************************************
6883 ****************************************************************************/
6885 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6887 form->flag=list->flag;
6888 init_unistr(&form->name, list->name);
6889 form->width=list->width;
6890 form->length=list->length;
6891 form->left=list->left;
6892 form->top=list->top;
6893 form->right=list->right;
6894 form->bottom=list->bottom;
6897 /****************************************************************************
6898 ****************************************************************************/
6900 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6902 uint32 level = q_u->level;
6903 NEW_BUFFER *buffer = NULL;
6904 uint32 offered = q_u->offered;
6905 uint32 *needed = &r_u->needed;
6906 uint32 *numofforms = &r_u->numofforms;
6907 uint32 numbuiltinforms;
6909 nt_forms_struct *list=NULL;
6910 nt_forms_struct *builtinlist=NULL;
6915 /* that's an [in out] buffer */
6916 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6917 buffer = r_u->buffer;
6919 DEBUG(4,("_spoolss_enumforms\n"));
6920 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6921 DEBUGADD(5,("Info level [%d]\n", level));
6923 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6924 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6925 *numofforms = get_ntforms(&list);
6926 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6927 *numofforms += numbuiltinforms;
6929 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6933 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6938 /* construct the list of form structures */
6939 for (i=0; i<numbuiltinforms; i++) {
6940 DEBUGADD(6,("Filling form number [%d]\n",i));
6941 fill_form_1(&forms_1[i], &builtinlist[i]);
6944 SAFE_FREE(builtinlist);
6946 for (; i<*numofforms; i++) {
6947 DEBUGADD(6,("Filling form number [%d]\n",i));
6948 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6953 /* check the required size. */
6954 for (i=0; i<numbuiltinforms; i++) {
6955 DEBUGADD(6,("adding form [%d]'s size\n",i));
6956 buffer_size += spoolss_size_form_1(&forms_1[i]);
6958 for (; i<*numofforms; i++) {
6959 DEBUGADD(6,("adding form [%d]'s size\n",i));
6960 buffer_size += spoolss_size_form_1(&forms_1[i]);
6963 *needed=buffer_size;
6965 if (!alloc_buffer_size(buffer, buffer_size)){
6967 return WERR_INSUFFICIENT_BUFFER;
6970 /* fill the buffer with the form structures */
6971 for (i=0; i<numbuiltinforms; i++) {
6972 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6973 smb_io_form_1("", buffer, &forms_1[i], 0);
6975 for (; i<*numofforms; i++) {
6976 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6977 smb_io_form_1("", buffer, &forms_1[i], 0);
6982 if (*needed > offered) {
6984 return WERR_INSUFFICIENT_BUFFER;
6991 SAFE_FREE(builtinlist);
6992 return WERR_UNKNOWN_LEVEL;
6997 /****************************************************************************
6998 ****************************************************************************/
7000 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7002 uint32 level = q_u->level;
7003 UNISTR2 *uni_formname = &q_u->formname;
7004 NEW_BUFFER *buffer = NULL;
7005 uint32 offered = q_u->offered;
7006 uint32 *needed = &r_u->needed;
7008 nt_forms_struct *list=NULL;
7009 nt_forms_struct builtin_form;
7014 int numofforms=0, i=0;
7016 /* that's an [in out] buffer */
7017 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7018 buffer = r_u->buffer;
7020 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7022 DEBUG(4,("_spoolss_getform\n"));
7023 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7024 DEBUGADD(5,("Info level [%d]\n", level));
7026 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7027 if (!foundBuiltin) {
7028 numofforms = get_ntforms(&list);
7029 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7031 if (numofforms == 0)
7038 fill_form_1(&form_1, &builtin_form);
7041 /* Check if the requested name is in the list of form structures */
7042 for (i=0; i<numofforms; i++) {
7044 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7046 if (strequal(form_name, list[i].name)) {
7047 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7048 fill_form_1(&form_1, &list[i]);
7054 if (i == numofforms) {
7058 /* check the required size. */
7060 *needed=spoolss_size_form_1(&form_1);
7062 if (!alloc_buffer_size(buffer, buffer_size)){
7063 return WERR_INSUFFICIENT_BUFFER;
7066 if (*needed > offered) {
7067 return WERR_INSUFFICIENT_BUFFER;
7070 /* fill the buffer with the form structures */
7071 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7072 smb_io_form_1("", buffer, &form_1, 0);
7078 return WERR_UNKNOWN_LEVEL;
7082 /****************************************************************************
7083 ****************************************************************************/
7085 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7087 init_unistr(&port->port_name, name);
7090 /****************************************************************************
7091 ****************************************************************************/
7093 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7095 init_unistr(&port->port_name, name);
7096 init_unistr(&port->monitor_name, "Local Monitor");
7097 init_unistr(&port->description, "Local Port");
7098 port->port_type=PORT_TYPE_WRITE;
7102 /****************************************************************************
7104 ****************************************************************************/
7106 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7108 PORT_INFO_1 *ports=NULL;
7111 if (*lp_enumports_cmd()) {
7112 char *cmd = lp_enumports_cmd();
7119 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7121 DEBUG(10,("Running [%s]\n", command));
7122 ret = smbrun(command, &fd);
7123 DEBUG(10,("Returned [%d]\n", ret));
7127 /* Is this the best error to return here? */
7128 return WERR_ACCESS_DENIED;
7132 qlines = fd_lines_load(fd, &numlines);
7133 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7137 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7138 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7139 dos_errstr(WERR_NOMEM)));
7140 file_lines_free(qlines);
7144 for (i=0; i<numlines; i++) {
7145 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7146 fill_port_1(&ports[i], qlines[i]);
7149 file_lines_free(qlines);
7152 *returned = numlines;
7155 *returned = 1; /* Sole Samba port returned. */
7157 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7160 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7162 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7165 /* check the required size. */
7166 for (i=0; i<*returned; i++) {
7167 DEBUGADD(6,("adding port [%d]'s size\n", i));
7168 *needed += spoolss_size_port_info_1(&ports[i]);
7171 if (!alloc_buffer_size(buffer, *needed)) {
7173 return WERR_INSUFFICIENT_BUFFER;
7176 /* fill the buffer with the ports structures */
7177 for (i=0; i<*returned; i++) {
7178 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7179 smb_io_port_1("", buffer, &ports[i], 0);
7184 if (*needed > offered) {
7186 return WERR_INSUFFICIENT_BUFFER;
7192 /****************************************************************************
7194 ****************************************************************************/
7196 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7198 PORT_INFO_2 *ports=NULL;
7201 if (*lp_enumports_cmd()) {
7202 char *cmd = lp_enumports_cmd();
7211 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7212 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7214 path = lp_lockdir();
7216 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7217 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7220 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7221 ret = smbrun(command, &fd);
7222 DEBUGADD(10,("returned [%d]\n", ret));
7226 /* Is this the best error to return here? */
7227 return WERR_ACCESS_DENIED;
7231 qlines = fd_lines_load(fd, &numlines);
7232 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7236 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7237 file_lines_free(qlines);
7241 for (i=0; i<numlines; i++) {
7242 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7243 fill_port_2(&(ports[i]), qlines[i]);
7246 file_lines_free(qlines);
7249 *returned = numlines;
7255 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7258 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7260 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7263 /* check the required size. */
7264 for (i=0; i<*returned; i++) {
7265 DEBUGADD(6,("adding port [%d]'s size\n", i));
7266 *needed += spoolss_size_port_info_2(&ports[i]);
7269 if (!alloc_buffer_size(buffer, *needed)) {
7271 return WERR_INSUFFICIENT_BUFFER;
7274 /* fill the buffer with the ports structures */
7275 for (i=0; i<*returned; i++) {
7276 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7277 smb_io_port_2("", buffer, &ports[i], 0);
7282 if (*needed > offered) {
7284 return WERR_INSUFFICIENT_BUFFER;
7290 /****************************************************************************
7292 ****************************************************************************/
7294 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7296 uint32 level = q_u->level;
7297 NEW_BUFFER *buffer = NULL;
7298 uint32 offered = q_u->offered;
7299 uint32 *needed = &r_u->needed;
7300 uint32 *returned = &r_u->returned;
7302 /* that's an [in out] buffer */
7303 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7304 buffer = r_u->buffer;
7306 DEBUG(4,("_spoolss_enumports\n"));
7313 return enumports_level_1(buffer, offered, needed, returned);
7315 return enumports_level_2(buffer, offered, needed, returned);
7317 return WERR_UNKNOWN_LEVEL;
7321 /****************************************************************************
7322 ****************************************************************************/
7324 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7325 const SPOOL_PRINTER_INFO_LEVEL *info,
7326 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7327 uint32 user_switch, const SPOOL_USER_CTR *user,
7330 NT_PRINTER_INFO_LEVEL *printer = NULL;
7333 WERROR err = WERR_OK;
7335 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7336 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7340 ZERO_STRUCTP(printer);
7342 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7343 if (!convert_printer_info(info, printer, 2)) {
7344 free_a_printer(&printer, 2);
7348 /* check to see if the printer already exists */
7350 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7351 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7352 printer->info_2->sharename));
7353 free_a_printer(&printer, 2);
7354 return WERR_PRINTER_ALREADY_EXISTS;
7357 /* FIXME!!! smbd should check to see if the driver is installed before
7358 trying to add a printer like this --jerry */
7360 if (*lp_addprinter_cmd() ) {
7361 if ( !add_printer_hook(printer) ) {
7362 free_a_printer(&printer,2);
7363 return WERR_ACCESS_DENIED;
7367 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7368 printer->info_2->sharename);
7371 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7372 free_a_printer(&printer,2);
7373 return WERR_ACCESS_DENIED;
7376 /* you must be a printer admin to add a new printer */
7377 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7378 free_a_printer(&printer,2);
7379 return WERR_ACCESS_DENIED;
7383 * Do sanity check on the requested changes for Samba.
7386 if (!check_printer_ok(printer->info_2, snum)) {
7387 free_a_printer(&printer,2);
7388 return WERR_INVALID_PARAM;
7392 * When a printer is created, the drivername bound to the printer is used
7393 * to lookup previously saved driver initialization info, which is then
7394 * bound to the new printer, simulating what happens in the Windows arch.
7399 set_driver_init(printer, 2);
7403 /* A valid devmode was included, convert and link it
7405 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7407 if (!convert_devicemode(printer->info_2->printername, devmode,
7408 &printer->info_2->devmode))
7412 /* write the ASCII on disk */
7413 err = mod_a_printer(*printer, 2);
7414 if (!W_ERROR_IS_OK(err)) {
7415 free_a_printer(&printer,2);
7419 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7420 /* Handle open failed - remove addition. */
7421 del_a_printer(printer->info_2->sharename);
7422 free_a_printer(&printer,2);
7423 return WERR_ACCESS_DENIED;
7426 update_c_setprinter(False);
7427 free_a_printer(&printer,2);
7432 /****************************************************************************
7433 ****************************************************************************/
7435 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7437 UNISTR2 *uni_srv_name = &q_u->server_name;
7438 uint32 level = q_u->level;
7439 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7440 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7441 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7442 uint32 user_switch = q_u->user_switch;
7443 SPOOL_USER_CTR *user = &q_u->user_ctr;
7444 POLICY_HND *handle = &r_u->handle;
7448 /* we don't handle yet */
7449 /* but I know what to do ... */
7450 return WERR_UNKNOWN_LEVEL;
7452 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7454 user_switch, user, handle);
7456 return WERR_UNKNOWN_LEVEL;
7460 /****************************************************************************
7461 ****************************************************************************/
7463 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7465 uint32 level = q_u->level;
7466 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7467 WERROR err = WERR_OK;
7468 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7469 struct current_user user;
7470 fstring driver_name;
7473 ZERO_STRUCT(driver);
7475 get_current_user(&user, p);
7477 if (!convert_printer_driver_info(info, &driver, level)) {
7482 DEBUG(5,("Cleaning driver's information\n"));
7483 err = clean_up_driver_struct(driver, level, &user);
7484 if (!W_ERROR_IS_OK(err))
7487 DEBUG(5,("Moving driver to final destination\n"));
7488 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7489 if (W_ERROR_IS_OK(err))
7490 err = WERR_ACCESS_DENIED;
7494 if (add_a_printer_driver(driver, level)!=0) {
7495 err = WERR_ACCESS_DENIED;
7499 /* BEGIN_ADMIN_LOG */
7502 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7503 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7504 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7507 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7508 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7509 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7515 * I think this is where he DrvUpgradePrinter() hook would be
7516 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7517 * server. Right now, we just need to send ourselves a message
7518 * to update each printer bound to this driver. --jerry
7521 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7522 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7527 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7528 * decide if the driver init data should be deleted. The rules are:
7529 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7530 * 2) delete init data only if there is no 2k/Xp driver
7531 * 3) always delete init data
7532 * The generalized rule is always use init data from the highest order driver.
7533 * It is necessary to follow the driver install by an initialization step to
7534 * finish off this process.
7537 version = driver.info_3->cversion;
7538 else if (level == 6)
7539 version = driver.info_6->version;
7544 * 9x printer driver - never delete init data
7547 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7552 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7553 * there is no 2k/Xp driver init data for this driver name.
7557 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7559 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7561 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7563 if (!del_driver_init(driver_name))
7564 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7567 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7569 free_a_printer_driver(driver1,3);
7570 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7577 * 2k or Xp printer driver - always delete init data
7580 if (!del_driver_init(driver_name))
7581 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7585 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7591 free_a_printer_driver(driver, level);
7595 /********************************************************************
7596 * spoolss_addprinterdriverex
7597 ********************************************************************/
7599 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7601 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7602 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7605 * we only support the semantics of AddPrinterDriver()
7606 * i.e. only copy files that are newer than existing ones
7609 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7610 return WERR_ACCESS_DENIED;
7612 ZERO_STRUCT(q_u_local);
7613 ZERO_STRUCT(r_u_local);
7615 /* just pass the information off to _spoolss_addprinterdriver() */
7616 q_u_local.server_name_ptr = q_u->server_name_ptr;
7617 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7618 q_u_local.level = q_u->level;
7619 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7621 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7624 /****************************************************************************
7625 ****************************************************************************/
7627 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7629 init_unistr(&info->name, name);
7632 /****************************************************************************
7633 ****************************************************************************/
7635 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7639 const char *short_archi;
7640 DRIVER_DIRECTORY_1 *info=NULL;
7642 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7644 if (!(short_archi = get_short_archi(long_archi)))
7645 return WERR_INVALID_ENVIRONMENT;
7647 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7650 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7652 DEBUG(4,("printer driver directory: [%s]\n", path));
7654 fill_driverdir_1(info, path);
7656 *needed += spoolss_size_driverdir_info_1(info);
7658 if (!alloc_buffer_size(buffer, *needed)) {
7660 return WERR_INSUFFICIENT_BUFFER;
7663 smb_io_driverdir_1("", buffer, info, 0);
7667 if (*needed > offered)
7668 return WERR_INSUFFICIENT_BUFFER;
7673 /****************************************************************************
7674 ****************************************************************************/
7676 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7678 UNISTR2 *name = &q_u->name;
7679 UNISTR2 *uni_environment = &q_u->environment;
7680 uint32 level = q_u->level;
7681 NEW_BUFFER *buffer = NULL;
7682 uint32 offered = q_u->offered;
7683 uint32 *needed = &r_u->needed;
7685 /* that's an [in out] buffer */
7686 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7687 buffer = r_u->buffer;
7689 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7695 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7697 return WERR_UNKNOWN_LEVEL;
7701 /****************************************************************************
7702 ****************************************************************************/
7704 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7706 POLICY_HND *handle = &q_u->handle;
7707 uint32 idx = q_u->index;
7708 uint32 in_value_len = q_u->valuesize;
7709 uint32 in_data_len = q_u->datasize;
7710 uint32 *out_max_value_len = &r_u->valuesize;
7711 uint16 **out_value = &r_u->value;
7712 uint32 *out_value_len = &r_u->realvaluesize;
7713 uint32 *out_type = &r_u->type;
7714 uint32 *out_max_data_len = &r_u->datasize;
7715 uint8 **data_out = &r_u->data;
7716 uint32 *out_data_len = &r_u->realdatasize;
7718 NT_PRINTER_INFO_LEVEL *printer = NULL;
7720 uint32 biggest_valuesize;
7721 uint32 biggest_datasize;
7723 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7726 REGISTRY_VALUE *val = NULL;
7727 NT_PRINTER_DATA *p_data;
7728 int i, key_index, num_values;
7731 ZERO_STRUCT( printer );
7735 *out_max_data_len = 0;
7739 DEBUG(5,("spoolss_enumprinterdata\n"));
7742 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7746 if (!get_printer_snum(p,handle, &snum))
7749 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7750 if (!W_ERROR_IS_OK(result))
7753 p_data = &printer->info_2->data;
7754 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7759 * The NT machine wants to know the biggest size of value and data
7761 * cf: MSDN EnumPrinterData remark section
7764 if ( !in_value_len && !in_data_len && (key_index != -1) )
7766 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7768 biggest_valuesize = 0;
7769 biggest_datasize = 0;
7771 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7773 for ( i=0; i<num_values; i++ )
7775 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7777 name_length = strlen(val->valuename);
7778 if ( strlen(val->valuename) > biggest_valuesize )
7779 biggest_valuesize = name_length;
7781 if ( val->size > biggest_datasize )
7782 biggest_datasize = val->size;
7784 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7788 /* the value is an UNICODE string but real_value_size is the length
7789 in bytes including the trailing 0 */
7791 *out_value_len = 2 * (1+biggest_valuesize);
7792 *out_data_len = biggest_datasize;
7794 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7800 * the value len is wrong in NT sp3
7801 * that's the number of bytes not the number of unicode chars
7804 if ( key_index != -1 )
7805 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7810 /* out_value should default to "" or else NT4 has
7811 problems unmarshalling the response */
7813 *out_max_value_len=(in_value_len/sizeof(uint16));
7815 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7817 result = WERR_NOMEM;
7821 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7823 /* the data is counted in bytes */
7825 *out_max_data_len = in_data_len;
7826 *out_data_len = in_data_len;
7828 /* only allocate when given a non-zero data_len */
7830 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7832 result = WERR_NOMEM;
7836 result = WERR_NO_MORE_ITEMS;
7842 * - counted in bytes in the request
7843 * - counted in UNICODE chars in the max reply
7844 * - counted in bytes in the real size
7846 * take a pause *before* coding not *during* coding
7850 *out_max_value_len=(in_value_len/sizeof(uint16));
7851 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7853 result = WERR_NOMEM;
7857 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7861 *out_type = regval_type( val );
7863 /* data - counted in bytes */
7865 *out_max_data_len = in_data_len;
7866 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7868 result = WERR_NOMEM;
7871 data_len = (size_t)regval_size(val);
7872 memcpy( *data_out, regval_data_p(val), data_len );
7873 *out_data_len = data_len;
7877 free_a_printer(&printer, 2);
7881 /****************************************************************************
7882 ****************************************************************************/
7884 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7886 POLICY_HND *handle = &q_u->handle;
7887 UNISTR2 *value = &q_u->value;
7888 uint32 type = q_u->type;
7889 uint8 *data = q_u->data;
7890 uint32 real_len = q_u->real_len;
7892 NT_PRINTER_INFO_LEVEL *printer = NULL;
7894 WERROR status = WERR_OK;
7895 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7898 DEBUG(5,("spoolss_setprinterdata\n"));
7901 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7905 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7906 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7907 return WERR_INVALID_PARAM;
7910 if (!get_printer_snum(p,handle, &snum))
7914 * Access check : NT returns "access denied" if you make a
7915 * SetPrinterData call without the necessary privildge.
7916 * we were originally returning OK if nothing changed
7917 * which made Win2k issue **a lot** of SetPrinterData
7918 * when connecting to a printer --jerry
7921 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7923 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7924 status = WERR_ACCESS_DENIED;
7928 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7929 if (!W_ERROR_IS_OK(status))
7932 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7935 * When client side code sets a magic printer data key, detect it and save
7936 * the current printer data and the magic key's data (its the DEVMODE) for
7937 * future printer/driver initializations.
7939 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7941 /* Set devmode and printer initialization info */
7942 status = save_driver_init( printer, 2, data, real_len );
7944 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7948 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7949 type, data, real_len );
7950 if ( W_ERROR_IS_OK(status) )
7951 status = mod_a_printer(*printer, 2);
7955 free_a_printer(&printer, 2);
7960 /****************************************************************************
7961 ****************************************************************************/
7963 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7965 POLICY_HND *handle = &q_u->handle;
7966 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7969 DEBUG(5,("_spoolss_resetprinter\n"));
7972 * All we do is to check to see if the handle and queue is valid.
7973 * This call really doesn't mean anything to us because we only
7974 * support RAW printing. --jerry
7978 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7982 if (!get_printer_snum(p,handle, &snum))
7986 /* blindly return success */
7991 /****************************************************************************
7992 ****************************************************************************/
7994 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7996 POLICY_HND *handle = &q_u->handle;
7997 UNISTR2 *value = &q_u->valuename;
7999 NT_PRINTER_INFO_LEVEL *printer = NULL;
8001 WERROR status = WERR_OK;
8002 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8005 DEBUG(5,("spoolss_deleteprinterdata\n"));
8008 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8012 if (!get_printer_snum(p, handle, &snum))
8015 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8016 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8017 return WERR_ACCESS_DENIED;
8020 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8021 if (!W_ERROR_IS_OK(status))
8024 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8026 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8028 if ( W_ERROR_IS_OK(status) )
8029 mod_a_printer( *printer, 2 );
8031 free_a_printer(&printer, 2);
8036 /****************************************************************************
8037 ****************************************************************************/
8039 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8041 POLICY_HND *handle = &q_u->handle;
8042 FORM *form = &q_u->form;
8043 nt_forms_struct tmpForm;
8045 WERROR status = WERR_OK;
8046 NT_PRINTER_INFO_LEVEL *printer = NULL;
8049 nt_forms_struct *list=NULL;
8050 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8052 DEBUG(5,("spoolss_addform\n"));
8055 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8060 /* forms can be added on printer of on the print server handle */
8062 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8064 if (!get_printer_snum(p,handle, &snum))
8067 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8068 if (!W_ERROR_IS_OK(status))
8072 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8073 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8074 status = WERR_ACCESS_DENIED;
8078 /* can't add if builtin */
8080 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8081 status = WERR_ALREADY_EXISTS;
8085 count = get_ntforms(&list);
8087 if(!add_a_form(&list, form, &count)) {
8088 status = WERR_NOMEM;
8092 write_ntforms(&list, count);
8095 * ChangeID must always be set if this is a printer
8098 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8099 status = mod_a_printer(*printer, 2);
8103 free_a_printer(&printer, 2);
8109 /****************************************************************************
8110 ****************************************************************************/
8112 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8114 POLICY_HND *handle = &q_u->handle;
8115 UNISTR2 *form_name = &q_u->name;
8116 nt_forms_struct tmpForm;
8118 nt_forms_struct *list=NULL;
8119 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8121 WERROR status = WERR_OK;
8122 NT_PRINTER_INFO_LEVEL *printer = NULL;
8124 DEBUG(5,("spoolss_deleteform\n"));
8127 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8131 /* forms can be deleted on printer of on the print server handle */
8133 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8135 if (!get_printer_snum(p,handle, &snum))
8138 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8139 if (!W_ERROR_IS_OK(status))
8143 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8144 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8145 status = WERR_ACCESS_DENIED;
8149 /* can't delete if builtin */
8151 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8152 status = WERR_INVALID_PARAM;
8156 count = get_ntforms(&list);
8158 if ( !delete_a_form(&list, form_name, &count, &status ))
8162 * ChangeID must always be set if this is a printer
8165 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8166 status = mod_a_printer(*printer, 2);
8170 free_a_printer(&printer, 2);
8176 /****************************************************************************
8177 ****************************************************************************/
8179 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8181 POLICY_HND *handle = &q_u->handle;
8182 FORM *form = &q_u->form;
8183 nt_forms_struct tmpForm;
8185 WERROR status = WERR_OK;
8186 NT_PRINTER_INFO_LEVEL *printer = NULL;
8189 nt_forms_struct *list=NULL;
8190 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8192 DEBUG(5,("spoolss_setform\n"));
8195 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8199 /* forms can be modified on printer of on the print server handle */
8201 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8203 if (!get_printer_snum(p,handle, &snum))
8206 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8207 if (!W_ERROR_IS_OK(status))
8211 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8212 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8213 status = WERR_ACCESS_DENIED;
8217 /* can't set if builtin */
8218 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8219 status = WERR_INVALID_PARAM;
8223 count = get_ntforms(&list);
8224 update_a_form(&list, form, count);
8225 write_ntforms(&list, count);
8228 * ChangeID must always be set if this is a printer
8231 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8232 status = mod_a_printer(*printer, 2);
8237 free_a_printer(&printer, 2);
8243 /****************************************************************************
8244 enumprintprocessors level 1.
8245 ****************************************************************************/
8247 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8249 PRINTPROCESSOR_1 *info_1=NULL;
8251 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8256 init_unistr(&info_1->name, "winprint");
8258 *needed += spoolss_size_printprocessor_info_1(info_1);
8260 if (!alloc_buffer_size(buffer, *needed))
8261 return WERR_INSUFFICIENT_BUFFER;
8263 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8267 if (*needed > offered) {
8269 return WERR_INSUFFICIENT_BUFFER;
8275 /****************************************************************************
8276 ****************************************************************************/
8278 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8280 uint32 level = q_u->level;
8281 NEW_BUFFER *buffer = NULL;
8282 uint32 offered = q_u->offered;
8283 uint32 *needed = &r_u->needed;
8284 uint32 *returned = &r_u->returned;
8286 /* that's an [in out] buffer */
8287 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8288 buffer = r_u->buffer;
8290 DEBUG(5,("spoolss_enumprintprocessors\n"));
8293 * Enumerate the print processors ...
8295 * Just reply with "winprint", to keep NT happy
8296 * and I can use my nice printer checker.
8304 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8306 return WERR_UNKNOWN_LEVEL;
8310 /****************************************************************************
8311 enumprintprocdatatypes level 1.
8312 ****************************************************************************/
8314 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8316 PRINTPROCDATATYPE_1 *info_1=NULL;
8318 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8323 init_unistr(&info_1->name, "RAW");
8325 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8327 if (!alloc_buffer_size(buffer, *needed))
8328 return WERR_INSUFFICIENT_BUFFER;
8330 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8334 if (*needed > offered) {
8336 return WERR_INSUFFICIENT_BUFFER;
8342 /****************************************************************************
8343 ****************************************************************************/
8345 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8347 uint32 level = q_u->level;
8348 NEW_BUFFER *buffer = NULL;
8349 uint32 offered = q_u->offered;
8350 uint32 *needed = &r_u->needed;
8351 uint32 *returned = &r_u->returned;
8353 /* that's an [in out] buffer */
8354 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8355 buffer = r_u->buffer;
8357 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8364 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8366 return WERR_UNKNOWN_LEVEL;
8370 /****************************************************************************
8371 enumprintmonitors level 1.
8372 ****************************************************************************/
8374 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8376 PRINTMONITOR_1 *info_1=NULL;
8378 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8383 init_unistr(&info_1->name, "Local Port");
8385 *needed += spoolss_size_printmonitor_info_1(info_1);
8387 if (!alloc_buffer_size(buffer, *needed))
8388 return WERR_INSUFFICIENT_BUFFER;
8390 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8394 if (*needed > offered) {
8396 return WERR_INSUFFICIENT_BUFFER;
8402 /****************************************************************************
8403 enumprintmonitors level 2.
8404 ****************************************************************************/
8406 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8408 PRINTMONITOR_2 *info_2=NULL;
8410 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8415 init_unistr(&info_2->name, "Local Port");
8416 init_unistr(&info_2->environment, "Windows NT X86");
8417 init_unistr(&info_2->dll_name, "localmon.dll");
8419 *needed += spoolss_size_printmonitor_info_2(info_2);
8421 if (!alloc_buffer_size(buffer, *needed))
8422 return WERR_INSUFFICIENT_BUFFER;
8424 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8428 if (*needed > offered) {
8430 return WERR_INSUFFICIENT_BUFFER;
8436 /****************************************************************************
8437 ****************************************************************************/
8439 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8441 uint32 level = q_u->level;
8442 NEW_BUFFER *buffer = NULL;
8443 uint32 offered = q_u->offered;
8444 uint32 *needed = &r_u->needed;
8445 uint32 *returned = &r_u->returned;
8447 /* that's an [in out] buffer */
8448 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8449 buffer = r_u->buffer;
8451 DEBUG(5,("spoolss_enumprintmonitors\n"));
8454 * Enumerate the print monitors ...
8456 * Just reply with "Local Port", to keep NT happy
8457 * and I can use my nice printer checker.
8465 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8467 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8469 return WERR_UNKNOWN_LEVEL;
8473 /****************************************************************************
8474 ****************************************************************************/
8476 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8480 JOB_INFO_1 *info_1=NULL;
8482 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8484 if (info_1 == NULL) {
8488 for (i=0; i<count && found==False; i++) {
8489 if ((*queue)[i].job==(int)jobid)
8495 /* NT treats not found as bad param... yet another bad choice */
8496 return WERR_INVALID_PARAM;
8499 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8501 *needed += spoolss_size_job_info_1(info_1);
8503 if (!alloc_buffer_size(buffer, *needed)) {
8505 return WERR_INSUFFICIENT_BUFFER;
8508 smb_io_job_info_1("", buffer, info_1, 0);
8512 if (*needed > offered)
8513 return WERR_INSUFFICIENT_BUFFER;
8518 /****************************************************************************
8519 ****************************************************************************/
8521 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8526 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8528 DEVICEMODE *devmode = NULL;
8529 NT_DEVICEMODE *nt_devmode = NULL;
8531 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8533 ZERO_STRUCTP(info_2);
8535 if (info_2 == NULL) {
8540 for ( i=0; i<count && found==False; i++ )
8542 if ((*queue)[i].job == (int)jobid)
8548 /* NT treats not found as bad param... yet another bad
8550 ret = WERR_INVALID_PARAM;
8554 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8555 if (!W_ERROR_IS_OK(ret))
8559 * if the print job does not have a DEVMODE associated with it,
8560 * just use the one for the printer. A NULL devicemode is not
8561 * a failure condition
8564 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8565 devmode = construct_dev_mode(snum);
8567 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8568 ZERO_STRUCTP( devmode );
8569 convert_nt_devicemode( devmode, nt_devmode );
8573 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8575 *needed += spoolss_size_job_info_2(info_2);
8577 if (!alloc_buffer_size(buffer, *needed)) {
8578 ret = WERR_INSUFFICIENT_BUFFER;
8582 smb_io_job_info_2("", buffer, info_2, 0);
8584 if (*needed > offered) {
8585 ret = WERR_INSUFFICIENT_BUFFER;
8592 /* Cleanup allocated memory */
8594 free_job_info_2(info_2); /* Also frees devmode */
8596 free_a_printer(&ntprinter, 2);
8601 /****************************************************************************
8602 ****************************************************************************/
8604 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8606 POLICY_HND *handle = &q_u->handle;
8607 uint32 jobid = q_u->jobid;
8608 uint32 level = q_u->level;
8609 NEW_BUFFER *buffer = NULL;
8610 uint32 offered = q_u->offered;
8611 uint32 *needed = &r_u->needed;
8612 WERROR wstatus = WERR_OK;
8616 print_queue_struct *queue = NULL;
8617 print_status_struct prt_status;
8619 /* that's an [in out] buffer */
8620 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8621 buffer = r_u->buffer;
8623 DEBUG(5,("spoolss_getjob\n"));
8627 if (!get_printer_snum(p, handle, &snum))
8630 count = print_queue_status(snum, &queue, &prt_status);
8632 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8633 count, prt_status.status, prt_status.message));
8637 wstatus = getjob_level_1(&queue, count, snum, jobid,
8638 buffer, offered, needed);
8641 wstatus = getjob_level_2(&queue, count, snum, jobid,
8642 buffer, offered, needed);
8645 wstatus = WERR_UNKNOWN_LEVEL;
8653 /********************************************************************
8654 spoolss_getprinterdataex
8656 From MSDN documentation of GetPrinterDataEx: pass request
8657 to GetPrinterData if key is "PrinterDriverData".
8658 ********************************************************************/
8660 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8662 POLICY_HND *handle = &q_u->handle;
8663 uint32 in_size = q_u->size;
8664 uint32 *type = &r_u->type;
8665 uint32 *out_size = &r_u->size;
8666 uint8 **data = &r_u->data;
8667 uint32 *needed = &r_u->needed;
8668 fstring keyname, valuename;
8670 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8672 NT_PRINTER_INFO_LEVEL *printer = NULL;
8674 WERROR status = WERR_OK;
8676 DEBUG(4,("_spoolss_getprinterdataex\n"));
8678 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8679 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8681 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8682 keyname, valuename));
8684 /* in case of problem, return some default values */
8688 *out_size = in_size;
8691 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8692 status = WERR_BADFID;
8696 /* Is the handle to a printer or to the server? */
8698 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8699 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8700 status = WERR_INVALID_PARAM;
8704 if ( !get_printer_snum(p,handle, &snum) )
8707 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8708 if ( !W_ERROR_IS_OK(status) )
8711 /* check to see if the keyname is valid */
8712 if ( !strlen(keyname) ) {
8713 status = WERR_INVALID_PARAM;
8717 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8718 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8719 free_a_printer( &printer, 2 );
8720 status = WERR_BADFILE;
8724 /* When given a new keyname, we should just create it */
8726 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8728 if (*needed > *out_size)
8729 status = WERR_MORE_DATA;
8732 if ( !W_ERROR_IS_OK(status) )
8734 DEBUG(5, ("error: allocating %d\n", *out_size));
8736 /* reply this param doesn't exist */
8740 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8741 status = WERR_NOMEM;
8751 free_a_printer( &printer, 2 );
8756 /********************************************************************
8757 * spoolss_setprinterdataex
8758 ********************************************************************/
8760 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8762 POLICY_HND *handle = &q_u->handle;
8763 uint32 type = q_u->type;
8764 uint8 *data = q_u->data;
8765 uint32 real_len = q_u->real_len;
8767 NT_PRINTER_INFO_LEVEL *printer = NULL;
8769 WERROR status = WERR_OK;
8770 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8775 DEBUG(4,("_spoolss_setprinterdataex\n"));
8777 /* From MSDN documentation of SetPrinterDataEx: pass request to
8778 SetPrinterData if key is "PrinterDriverData" */
8781 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8785 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8786 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8787 return WERR_INVALID_PARAM;
8790 if ( !get_printer_snum(p,handle, &snum) )
8794 * Access check : NT returns "access denied" if you make a
8795 * SetPrinterData call without the necessary privildge.
8796 * we were originally returning OK if nothing changed
8797 * which made Win2k issue **a lot** of SetPrinterData
8798 * when connecting to a printer --jerry
8801 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8803 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8804 return WERR_ACCESS_DENIED;
8807 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8808 if (!W_ERROR_IS_OK(status))
8811 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8812 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8814 /* check for OID in valuename */
8816 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8822 /* save the registry data */
8824 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8826 if ( W_ERROR_IS_OK(status) )
8828 /* save the OID if one was specified */
8830 fstrcat( keyname, "\\" );
8831 fstrcat( keyname, SPOOL_OID_KEY );
8834 * I'm not checking the status here on purpose. Don't know
8835 * if this is right, but I'm returning the status from the
8836 * previous set_printer_dataex() call. I have no idea if
8837 * this is right. --jerry
8840 set_printer_dataex( printer, keyname, valuename,
8841 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8844 status = mod_a_printer(*printer, 2);
8847 free_a_printer(&printer, 2);
8853 /********************************************************************
8854 * spoolss_deleteprinterdataex
8855 ********************************************************************/
8857 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8859 POLICY_HND *handle = &q_u->handle;
8860 UNISTR2 *value = &q_u->valuename;
8861 UNISTR2 *key = &q_u->keyname;
8863 NT_PRINTER_INFO_LEVEL *printer = NULL;
8865 WERROR status = WERR_OK;
8866 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8867 pstring valuename, keyname;
8869 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8872 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8876 if (!get_printer_snum(p, handle, &snum))
8879 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8880 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8881 return WERR_ACCESS_DENIED;
8884 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8885 if (!W_ERROR_IS_OK(status))
8888 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8889 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8891 status = delete_printer_dataex( printer, keyname, valuename );
8893 if ( W_ERROR_IS_OK(status) )
8894 mod_a_printer( *printer, 2 );
8896 free_a_printer(&printer, 2);
8901 /********************************************************************
8902 * spoolss_enumprinterkey
8903 ********************************************************************/
8906 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8909 fstring *keynames = NULL;
8910 uint16 *enumkeys = NULL;
8913 POLICY_HND *handle = &q_u->handle;
8914 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8915 NT_PRINTER_DATA *data;
8916 NT_PRINTER_INFO_LEVEL *printer = NULL;
8918 WERROR status = WERR_BADFILE;
8921 DEBUG(4,("_spoolss_enumprinterkey\n"));
8924 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8928 if ( !get_printer_snum(p,handle, &snum) )
8931 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8932 if (!W_ERROR_IS_OK(status))
8935 /* get the list of subkey names */
8937 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8938 data = &printer->info_2->data;
8940 num_keys = get_printer_subkeys( data, key, &keynames );
8942 if ( num_keys == -1 ) {
8943 status = WERR_BADFILE;
8947 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8949 r_u->needed = printerkey_len*2;
8951 if ( q_u->size < r_u->needed ) {
8952 status = WERR_MORE_DATA;
8956 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8957 status = WERR_NOMEM;
8963 if ( q_u->size < r_u->needed )
8964 status = WERR_MORE_DATA;
8967 free_a_printer( &printer, 2 );
8968 SAFE_FREE( keynames );
8973 /********************************************************************
8974 * spoolss_deleteprinterkey
8975 ********************************************************************/
8977 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8979 POLICY_HND *handle = &q_u->handle;
8980 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8982 NT_PRINTER_INFO_LEVEL *printer = NULL;
8986 DEBUG(5,("spoolss_deleteprinterkey\n"));
8989 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8993 /* if keyname == NULL, return error */
8995 if ( !q_u->keyname.buffer )
8996 return WERR_INVALID_PARAM;
8998 if (!get_printer_snum(p, handle, &snum))
9001 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9002 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9003 return WERR_ACCESS_DENIED;
9006 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9007 if (!W_ERROR_IS_OK(status))
9010 /* delete the key and all subneys */
9012 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9014 status = delete_all_printer_data( printer->info_2, key );
9016 if ( W_ERROR_IS_OK(status) )
9017 status = mod_a_printer(*printer, 2);
9019 free_a_printer( &printer, 2 );
9025 /********************************************************************
9026 * spoolss_enumprinterdataex
9027 ********************************************************************/
9029 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9031 POLICY_HND *handle = &q_u->handle;
9032 uint32 in_size = q_u->size;
9035 NT_PRINTER_INFO_LEVEL *printer = NULL;
9036 PRINTER_ENUM_VALUES *enum_values = NULL;
9037 NT_PRINTER_DATA *p_data;
9039 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9044 REGISTRY_VALUE *val;
9049 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9052 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9057 * first check for a keyname of NULL or "". Win2k seems to send
9058 * this a lot and we should send back WERR_INVALID_PARAM
9059 * no need to spend time looking up the printer in this case.
9063 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9064 if ( !strlen(key) ) {
9065 result = WERR_INVALID_PARAM;
9069 /* get the printer off of disk */
9071 if (!get_printer_snum(p,handle, &snum))
9074 ZERO_STRUCT(printer);
9075 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9076 if (!W_ERROR_IS_OK(result))
9079 /* now look for a match on the key name */
9081 p_data = &printer->info_2->data;
9083 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9084 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9086 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9087 result = WERR_INVALID_PARAM;
9094 /* allocate the memory for the array of pointers -- if necessary */
9096 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9099 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9101 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9102 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9103 result = WERR_NOMEM;
9107 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9111 * loop through all params and build the array to pass
9112 * back to the client
9115 for ( i=0; i<num_entries; i++ )
9117 /* lookup the registry value */
9119 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9120 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9124 value_name = regval_name( val );
9125 init_unistr( &enum_values[i].valuename, value_name );
9126 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9127 enum_values[i].type = regval_type( val );
9129 data_len = regval_size( val );
9131 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9133 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9135 result = WERR_NOMEM;
9139 enum_values[i].data_len = data_len;
9141 /* keep track of the size of the array in bytes */
9143 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9146 /* housekeeping information in the reply */
9148 r_u->needed = needed;
9149 r_u->returned = num_entries;
9151 if (needed > in_size) {
9152 result = WERR_MORE_DATA;
9156 /* copy data into the reply */
9158 r_u->ctr.size = r_u->needed;
9159 r_u->ctr.size_of_array = r_u->returned;
9160 r_u->ctr.values = enum_values;
9166 free_a_printer(&printer, 2);
9171 /****************************************************************************
9172 ****************************************************************************/
9174 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9176 init_unistr(&info->name, name);
9179 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9180 UNISTR2 *environment,
9187 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9189 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9191 if (!get_short_archi(long_archi))
9192 return WERR_INVALID_ENVIRONMENT;
9194 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9197 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9199 fill_printprocessordirectory_1(info, path);
9201 *needed += spoolss_size_printprocessordirectory_info_1(info);
9203 if (!alloc_buffer_size(buffer, *needed)) {
9205 return WERR_INSUFFICIENT_BUFFER;
9208 smb_io_printprocessordirectory_1("", buffer, info, 0);
9212 if (*needed > offered)
9213 return WERR_INSUFFICIENT_BUFFER;
9218 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9220 uint32 level = q_u->level;
9221 NEW_BUFFER *buffer = NULL;
9222 uint32 offered = q_u->offered;
9223 uint32 *needed = &r_u->needed;
9226 /* that's an [in out] buffer */
9227 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9228 buffer = r_u->buffer;
9230 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9236 result = getprintprocessordirectory_level_1
9237 (&q_u->name, &q_u->environment, buffer, offered, needed);
9240 result = WERR_UNKNOWN_LEVEL;
9248 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9249 SPOOL_R_REPLYOPENPRINTER *r_u)
9251 DEBUG(5,("_spoolss_replyopenprinter\n"));
9253 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9258 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9259 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9261 DEBUG(5,("_spoolss_replycloseprinter\n"));