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 /********************************************************************
1103 Receive a notify2 message list
1104 ********************************************************************/
1106 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1108 size_t msg_count, i;
1109 char *buf = (char *)msg;
1112 SPOOLSS_NOTIFY_MSG notify;
1113 SPOOLSS_NOTIFY_MSG_CTR messages;
1117 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1121 msg_count = IVAL(buf, 0);
1124 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1126 if (msg_count == 0) {
1127 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1131 /* initialize the container */
1133 ZERO_STRUCT( messages );
1134 notify_msg_ctr_init( &messages );
1137 * build message groups for each printer identified
1138 * in a change_notify msg. Remember that a PCN message
1139 * includes the handle returned for the srv_spoolss_replyopenprinter()
1140 * call. Therefore messages are grouped according to printer handle.
1143 for ( i=0; i<msg_count; i++ ) {
1144 struct timeval msg_tv;
1146 if (msg_ptr + 4 - buf > len) {
1147 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1151 msg_len = IVAL(msg_ptr,0);
1154 if (msg_ptr + msg_len - buf > len) {
1155 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1159 /* unpack messages */
1161 ZERO_STRUCT( notify );
1162 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1165 /* add to correct list in container */
1167 notify_msg_ctr_addmsg( &messages, ¬ify );
1169 /* free memory that might have been allocated by notify2_unpack_msg() */
1171 if ( notify.len != 0 )
1172 SAFE_FREE( notify.notify.data );
1175 /* process each group of messages */
1177 num_groups = notify_msg_ctr_numgroups( &messages );
1178 for ( i=0; i<num_groups; i++ )
1179 send_notify2_changes( &messages, i );
1184 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1186 notify_msg_ctr_destroy( &messages );
1191 /********************************************************************
1192 Send a message to ourself about new driver being installed
1193 so we can upgrade the information for each printer bound to this
1195 ********************************************************************/
1197 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1199 int len = strlen(drivername);
1204 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1207 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1212 /**********************************************************************
1213 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1214 over all printers, upgrading ones as necessary
1215 **********************************************************************/
1217 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1221 int n_services = lp_numservices();
1223 len = MIN(len,sizeof(drivername)-1);
1224 strncpy(drivername, buf, len);
1226 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1228 /* Iterate the printer list */
1230 for (snum=0; snum<n_services; snum++)
1232 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1235 NT_PRINTER_INFO_LEVEL *printer = NULL;
1237 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1238 if (!W_ERROR_IS_OK(result))
1241 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1243 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1245 /* all we care about currently is the change_id */
1247 result = mod_a_printer(*printer, 2);
1248 if (!W_ERROR_IS_OK(result)) {
1249 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1250 dos_errstr(result)));
1254 free_a_printer(&printer, 2);
1261 /********************************************************************
1262 Update the cache for all printq's with a registered client
1264 ********************************************************************/
1266 void update_monitored_printq_cache( void )
1268 Printer_entry *printer = printers_list;
1271 /* loop through all printers and update the cache where
1272 client_connected == True */
1275 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1276 && printer->notify.client_connected )
1278 snum = print_queue_snum(printer->dev.handlename);
1279 print_queue_status( snum, NULL, NULL );
1282 printer = printer->next;
1287 /********************************************************************
1288 Send a message to ourself about new driver being installed
1289 so we can upgrade the information for each printer bound to this
1291 ********************************************************************/
1293 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1295 int len = strlen(drivername);
1300 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1303 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1308 /**********************************************************************
1309 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1310 over all printers, resetting printer data as neessary
1311 **********************************************************************/
1313 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1317 int n_services = lp_numservices();
1319 len = MIN( len, sizeof(drivername)-1 );
1320 strncpy( drivername, buf, len );
1322 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1324 /* Iterate the printer list */
1326 for ( snum=0; snum<n_services; snum++ )
1328 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1331 NT_PRINTER_INFO_LEVEL *printer = NULL;
1333 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1334 if ( !W_ERROR_IS_OK(result) )
1338 * if the printer is bound to the driver,
1339 * then reset to the new driver initdata
1342 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1344 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1346 if ( !set_driver_init(printer, 2) ) {
1347 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1348 printer->info_2->printername, printer->info_2->drivername));
1351 result = mod_a_printer( *printer, 2 );
1352 if ( !W_ERROR_IS_OK(result) ) {
1353 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1354 get_dos_error_msg(result)));
1358 free_a_printer( &printer, 2 );
1367 /********************************************************************
1368 Copy routines used by convert_to_openprinterex()
1369 *******************************************************************/
1371 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1379 DEBUG (8,("dup_devmode\n"));
1381 /* bulk copy first */
1383 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1387 /* dup the pointer members separately */
1389 len = unistrlen(devmode->devicename.buffer);
1391 d->devicename.buffer = talloc(ctx, len*2);
1392 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1397 len = unistrlen(devmode->formname.buffer);
1399 d->devicename.buffer = talloc(ctx, len*2);
1400 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1404 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1409 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1411 if (!new_ctr || !ctr)
1414 DEBUG(8,("copy_devmode_ctr\n"));
1416 new_ctr->size = ctr->size;
1417 new_ctr->devmode_ptr = ctr->devmode_ptr;
1419 if(ctr->devmode_ptr)
1420 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1423 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1425 if (!new_def || !def)
1428 DEBUG(8,("copy_printer_defaults\n"));
1430 new_def->datatype_ptr = def->datatype_ptr;
1432 if (def->datatype_ptr)
1433 copy_unistr2(&new_def->datatype, &def->datatype);
1435 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1437 new_def->access_required = def->access_required;
1440 /********************************************************************
1441 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1442 * SPOOL_Q_OPEN_PRINTER_EX structure
1443 ********************************************************************/
1445 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1447 if (!q_u_ex || !q_u)
1450 DEBUG(8,("convert_to_openprinterex\n"));
1452 q_u_ex->printername_ptr = q_u->printername_ptr;
1454 if (q_u->printername_ptr)
1455 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1457 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1460 /********************************************************************
1461 * spoolss_open_printer
1463 * called from the spoolss dispatcher
1464 ********************************************************************/
1466 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1468 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1469 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1474 ZERO_STRUCT(q_u_ex);
1475 ZERO_STRUCT(r_u_ex);
1477 /* convert the OpenPrinter() call to OpenPrinterEx() */
1479 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1481 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1483 /* convert back to OpenPrinter() */
1485 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1490 /********************************************************************
1491 * spoolss_open_printer
1493 * If the openprinterex rpc call contains a devmode,
1494 * it's a per-user one. This per-user devmode is derivated
1495 * from the global devmode. Openprinterex() contains a per-user
1496 * devmode for when you do EMF printing and spooling.
1497 * In the EMF case, the NT workstation is only doing half the job
1498 * of rendering the page. The other half is done by running the printer
1499 * driver on the server.
1500 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1501 * The EMF file only contains what is to be printed on the page.
1502 * So in order for the server to know how to print, the NT client sends
1503 * a devicemode attached to the openprinterex call.
1504 * But this devicemode is short lived, it's only valid for the current print job.
1506 * If Samba would have supported EMF spooling, this devicemode would
1507 * have been attached to the handle, to sent it to the driver to correctly
1508 * rasterize the EMF file.
1510 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1511 * we just act as a pass-thru between windows and the printer.
1513 * In order to know that Samba supports only RAW spooling, NT has to call
1514 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1515 * and until NT sends a RAW job, we refuse it.
1517 * But to call getprinter() or startdoc(), you first need a valid handle,
1518 * and to get an handle you have to call openprintex(). Hence why you have
1519 * a devicemode in the openprinterex() call.
1522 * Differences between NT4 and NT 2000.
1525 * On NT4, you only have a global devicemode. This global devicemode can be changed
1526 * by the administrator (or by a user with enough privs). Everytime a user
1527 * wants to print, the devicemode is resetted to the default. In Word, everytime
1528 * you print, the printer's characteristics are always reset to the global devicemode.
1532 * In W2K, there is the notion of per-user devicemode. The first time you use
1533 * a printer, a per-user devicemode is build from the global devicemode.
1534 * If you change your per-user devicemode, it is saved in the registry, under the
1535 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1536 * printer preferences available.
1538 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1539 * on the General Tab of the printer properties windows.
1541 * To change the global devicemode: it's the "Printing Defaults..." button
1542 * on the Advanced Tab of the printer properties window.
1545 ********************************************************************/
1547 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1549 UNISTR2 *printername = NULL;
1550 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1551 POLICY_HND *handle = &r_u->handle;
1555 struct current_user user;
1556 Printer_entry *Printer=NULL;
1558 if (q_u->printername_ptr != 0)
1559 printername = &q_u->printername;
1561 if (printername == NULL)
1562 return WERR_INVALID_PRINTER_NAME;
1564 /* some sanity check because you can open a printer or a print server */
1565 /* aka: \\server\printer or \\server */
1566 unistr2_to_ascii(name, printername, sizeof(name)-1);
1568 DEBUGADD(3,("checking name: %s\n",name));
1570 if (!open_printer_hnd(p, handle, name, 0))
1571 return WERR_INVALID_PRINTER_NAME;
1573 Printer=find_printer_index_by_hnd(p, handle);
1575 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1576 Can't find printer handle we created for printer %s\n", name ));
1577 close_printer_handle(p,handle);
1578 return WERR_INVALID_PRINTER_NAME;
1581 get_current_user(&user, p);
1584 * First case: the user is opening the print server:
1586 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1587 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1589 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1590 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1591 * or if the user is listed in the smb.conf printer admin parameter.
1593 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1594 * client view printer folder, but does not show the MSAPW.
1596 * Note: this test needs code to check access rights here too. Jeremy
1597 * could you look at this?
1599 * Second case: the user is opening a printer:
1600 * NT doesn't let us connect to a printer if the connecting user
1601 * doesn't have print permission.
1604 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1606 /* Printserver handles use global struct... */
1610 /* Map standard access rights to object specific access rights */
1612 se_map_standard(&printer_default->access_required,
1613 &printserver_std_mapping);
1615 /* Deny any object specific bits that don't apply to print
1616 servers (i.e printer and job specific bits) */
1618 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1620 if (printer_default->access_required &
1621 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1622 DEBUG(3, ("access DENIED for non-printserver bits"));
1623 close_printer_handle(p, handle);
1624 return WERR_ACCESS_DENIED;
1627 /* Allow admin access */
1629 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1631 if (!lp_ms_add_printer_wizard()) {
1632 close_printer_handle(p, handle);
1633 return WERR_ACCESS_DENIED;
1636 /* if the user is not root and not a printer admin, then fail */
1639 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1641 close_printer_handle(p, handle);
1642 return WERR_ACCESS_DENIED;
1645 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1649 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1652 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1653 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1655 /* We fall through to return WERR_OK */
1660 /* NT doesn't let us connect to a printer if the connecting user
1661 doesn't have print permission. */
1663 if (!get_printer_snum(p, handle, &snum)) {
1664 close_printer_handle(p, handle);
1668 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1670 /* map an empty access mask to the minimum access mask */
1671 if (printer_default->access_required == 0x0)
1672 printer_default->access_required = PRINTER_ACCESS_USE;
1675 * If we are not serving the printer driver for this printer,
1676 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1677 * will keep NT clients happy --jerry
1680 if (lp_use_client_driver(snum)
1681 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1683 printer_default->access_required = PRINTER_ACCESS_USE;
1686 /* check smb.conf parameters and the the sec_desc */
1688 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1689 DEBUG(3, ("access DENIED for printer open\n"));
1690 close_printer_handle(p, handle);
1691 return WERR_ACCESS_DENIED;
1694 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1695 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1696 close_printer_handle(p, handle);
1697 return WERR_ACCESS_DENIED;
1700 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1701 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1703 printer_default->access_required = PRINTER_ACCESS_USE;
1705 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1706 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1710 Printer->access_granted = printer_default->access_required;
1713 * If the client sent a devmode in the OpenPrinter() call, then
1714 * save it here in case we get a job submission on this handle
1717 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1718 && q_u->printer_default.devmode_cont.devmode_ptr )
1720 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1721 &Printer->nt_devmode );
1724 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1725 optimization in Windows 2000 clients --jerry */
1727 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1728 && (RA_WIN2K == get_remote_arch()) )
1730 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1731 sys_usleep( 500000 );
1737 /****************************************************************************
1738 ****************************************************************************/
1740 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1741 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1747 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1756 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1757 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1763 printer->info_3=NULL;
1764 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1768 printer->info_6=NULL;
1769 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1779 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1780 NT_DEVICEMODE **pp_nt_devmode)
1782 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1785 * Ensure nt_devmode is a valid pointer
1786 * as we will be overwriting it.
1789 if (nt_devmode == NULL) {
1790 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1791 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1795 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1796 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1798 nt_devmode->specversion=devmode->specversion;
1799 nt_devmode->driverversion=devmode->driverversion;
1800 nt_devmode->size=devmode->size;
1801 nt_devmode->fields=devmode->fields;
1802 nt_devmode->orientation=devmode->orientation;
1803 nt_devmode->papersize=devmode->papersize;
1804 nt_devmode->paperlength=devmode->paperlength;
1805 nt_devmode->paperwidth=devmode->paperwidth;
1806 nt_devmode->scale=devmode->scale;
1807 nt_devmode->copies=devmode->copies;
1808 nt_devmode->defaultsource=devmode->defaultsource;
1809 nt_devmode->printquality=devmode->printquality;
1810 nt_devmode->color=devmode->color;
1811 nt_devmode->duplex=devmode->duplex;
1812 nt_devmode->yresolution=devmode->yresolution;
1813 nt_devmode->ttoption=devmode->ttoption;
1814 nt_devmode->collate=devmode->collate;
1816 nt_devmode->logpixels=devmode->logpixels;
1817 nt_devmode->bitsperpel=devmode->bitsperpel;
1818 nt_devmode->pelswidth=devmode->pelswidth;
1819 nt_devmode->pelsheight=devmode->pelsheight;
1820 nt_devmode->displayflags=devmode->displayflags;
1821 nt_devmode->displayfrequency=devmode->displayfrequency;
1822 nt_devmode->icmmethod=devmode->icmmethod;
1823 nt_devmode->icmintent=devmode->icmintent;
1824 nt_devmode->mediatype=devmode->mediatype;
1825 nt_devmode->dithertype=devmode->dithertype;
1826 nt_devmode->reserved1=devmode->reserved1;
1827 nt_devmode->reserved2=devmode->reserved2;
1828 nt_devmode->panningwidth=devmode->panningwidth;
1829 nt_devmode->panningheight=devmode->panningheight;
1832 * Only change private and driverextra if the incoming devmode
1833 * has a new one. JRA.
1836 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1837 SAFE_FREE(nt_devmode->private);
1838 nt_devmode->driverextra=devmode->driverextra;
1839 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1841 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1844 *pp_nt_devmode = nt_devmode;
1849 /********************************************************************
1850 * _spoolss_enddocprinter_internal.
1851 ********************************************************************/
1853 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1855 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1859 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1863 if (!get_printer_snum(p, handle, &snum))
1866 Printer->document_started=False;
1867 print_job_end(snum, Printer->jobid,True);
1868 /* error codes unhandled so far ... */
1873 /********************************************************************
1874 * api_spoolss_closeprinter
1875 ********************************************************************/
1877 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1879 POLICY_HND *handle = &q_u->handle;
1881 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1883 if (Printer && Printer->document_started)
1884 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1886 if (!close_printer_handle(p, handle))
1889 /* clear the returned printer handle. Observed behavior
1890 from Win2k server. Don't think this really matters.
1891 Previous code just copied the value of the closed
1894 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1899 /********************************************************************
1900 * api_spoolss_deleteprinter
1902 ********************************************************************/
1904 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1906 POLICY_HND *handle = &q_u->handle;
1907 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1910 if (Printer && Printer->document_started)
1911 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1913 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1915 result = delete_printer_handle(p, handle);
1917 update_c_setprinter(False);
1922 /*******************************************************************
1923 * static function to lookup the version id corresponding to an
1924 * long architecture string
1925 ******************************************************************/
1927 static int get_version_id (char * arch)
1930 struct table_node archi_table[]= {
1932 {"Windows 4.0", "WIN40", 0 },
1933 {"Windows NT x86", "W32X86", 2 },
1934 {"Windows NT R4000", "W32MIPS", 2 },
1935 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1936 {"Windows NT PowerPC", "W32PPC", 2 },
1940 for (i=0; archi_table[i].long_archi != NULL; i++)
1942 if (strcmp(arch, archi_table[i].long_archi) == 0)
1943 return (archi_table[i].version);
1949 /********************************************************************
1950 * _spoolss_deleteprinterdriver
1951 ********************************************************************/
1953 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1957 NT_PRINTER_DRIVER_INFO_LEVEL info;
1958 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1960 struct current_user user;
1962 WERROR status_win2k = WERR_ACCESS_DENIED;
1964 get_current_user(&user, p);
1966 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1967 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1969 /* check that we have a valid driver name first */
1971 if ((version=get_version_id(arch)) == -1)
1972 return WERR_INVALID_ENVIRONMENT;
1975 ZERO_STRUCT(info_win2k);
1977 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1979 /* try for Win2k driver if "Windows NT x86" */
1981 if ( version == 2 ) {
1983 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1984 status = WERR_UNKNOWN_PRINTER_DRIVER;
1988 /* otherwise it was a failure */
1990 status = WERR_UNKNOWN_PRINTER_DRIVER;
1996 if (printer_driver_in_use(info.info_3)) {
1997 status = WERR_PRINTER_DRIVER_IN_USE;
2003 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2005 /* if we get to here, we now have 2 driver info structures to remove */
2006 /* remove the Win2k driver first*/
2008 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2009 free_a_printer_driver( info_win2k, 3 );
2011 /* this should not have failed---if it did, report to client */
2012 if ( !W_ERROR_IS_OK(status_win2k) )
2017 status = delete_printer_driver(info.info_3, &user, version, False);
2019 /* if at least one of the deletes succeeded return OK */
2021 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2025 free_a_printer_driver( info, 3 );
2030 /********************************************************************
2031 * spoolss_deleteprinterdriverex
2032 ********************************************************************/
2034 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2038 NT_PRINTER_DRIVER_INFO_LEVEL info;
2039 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2041 uint32 flags = q_u->delete_flags;
2043 struct current_user user;
2045 WERROR status_win2k = WERR_ACCESS_DENIED;
2047 get_current_user(&user, p);
2049 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2050 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2052 /* check that we have a valid driver name first */
2053 if ((version=get_version_id(arch)) == -1) {
2054 /* this is what NT returns */
2055 return WERR_INVALID_ENVIRONMENT;
2058 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2059 version = q_u->version;
2062 ZERO_STRUCT(info_win2k);
2064 status = get_a_printer_driver(&info, 3, driver, arch, version);
2066 if ( !W_ERROR_IS_OK(status) )
2069 * if the client asked for a specific version,
2070 * or this is something other than Windows NT x86,
2074 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2077 /* try for Win2k driver if "Windows NT x86" */
2080 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2081 status = WERR_UNKNOWN_PRINTER_DRIVER;
2086 if ( printer_driver_in_use(info.info_3) ) {
2087 status = WERR_PRINTER_DRIVER_IN_USE;
2092 * we have a couple of cases to consider.
2093 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2094 * then the delete should fail if **any** files overlap with
2096 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2097 * non-overlapping files
2098 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2099 * is set, the do not delete any files
2100 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2103 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2105 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2107 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2108 /* no idea of the correct error here */
2109 status = WERR_ACCESS_DENIED;
2114 /* also check for W32X86/3 if necessary; maybe we already have? */
2116 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2117 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2120 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2121 /* no idea of the correct error here */
2122 free_a_printer_driver( info_win2k, 3 );
2123 status = WERR_ACCESS_DENIED;
2127 /* if we get to here, we now have 2 driver info structures to remove */
2128 /* remove the Win2k driver first*/
2130 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2131 free_a_printer_driver( info_win2k, 3 );
2133 /* this should not have failed---if it did, report to client */
2135 if ( !W_ERROR_IS_OK(status_win2k) )
2140 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2142 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2145 free_a_printer_driver( info, 3 );
2151 /****************************************************************************
2152 Internal routine for retreiving printerdata
2153 ***************************************************************************/
2155 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2156 const char *key, const char *value, uint32 *type, uint8 **data,
2157 uint32 *needed, uint32 in_size )
2159 REGISTRY_VALUE *val;
2162 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2163 return WERR_BADFILE;
2165 *type = regval_type( val );
2167 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2169 size = regval_size( val );
2171 /* copy the min(in_size, len) */
2174 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2176 /* special case for 0 length values */
2178 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2182 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2191 DEBUG(5,("get_printer_dataex: copy done\n"));
2196 /****************************************************************************
2197 Internal routine for removing printerdata
2198 ***************************************************************************/
2200 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2202 return delete_printer_data( printer->info_2, key, value );
2205 /****************************************************************************
2206 Internal routine for storing printerdata
2207 ***************************************************************************/
2209 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2210 uint32 type, uint8 *data, int real_len )
2212 delete_printer_data( printer->info_2, key, value );
2214 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2217 /********************************************************************
2218 GetPrinterData on a printer server Handle.
2219 ********************************************************************/
2221 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2225 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2227 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2229 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2235 if (!StrCaseCmp(value, "BeepEnabled")) {
2237 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2239 SIVAL(*data, 0, 0x00);
2244 if (!StrCaseCmp(value, "EventLog")) {
2246 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2248 /* formally was 0x1b */
2249 SIVAL(*data, 0, 0x0);
2254 if (!StrCaseCmp(value, "NetPopup")) {
2256 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2258 SIVAL(*data, 0, 0x00);
2263 if (!StrCaseCmp(value, "MajorVersion")) {
2265 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2268 /* Windows NT 4.0 seems to not allow uploading of drivers
2269 to a server that reports 0x3 as the MajorVersion.
2270 need to investigate more how Win2k gets around this .
2273 if ( RA_WINNT == get_remote_arch() )
2282 if (!StrCaseCmp(value, "MinorVersion")) {
2284 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2292 * uint32 size = 0x114
2294 * uint32 minor = [0|1]
2295 * uint32 build = [2195|2600]
2296 * extra unicode string = e.g. "Service Pack 3"
2298 if (!StrCaseCmp(value, "OSVersion")) {
2302 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2304 ZERO_STRUCTP( *data );
2306 SIVAL(*data, 0, *needed); /* size */
2307 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2309 SIVAL(*data, 12, 2195); /* build */
2311 /* leave extra string empty */
2317 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2318 const char *string="C:\\PRINTERS";
2320 *needed = 2*(strlen(string)+1);
2321 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2323 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2325 /* it's done by hand ready to go on the wire */
2326 for (i=0; i<strlen(string); i++) {
2327 (*data)[2*i]=string[i];
2328 (*data)[2*i+1]='\0';
2333 if (!StrCaseCmp(value, "Architecture")) {
2334 const char *string="Windows NT x86";
2336 *needed = 2*(strlen(string)+1);
2337 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2339 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2340 for (i=0; i<strlen(string); i++) {
2341 (*data)[2*i]=string[i];
2342 (*data)[2*i+1]='\0';
2347 if (!StrCaseCmp(value, "DsPresent")) {
2349 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2351 SIVAL(*data, 0, 0x01);
2356 if (!StrCaseCmp(value, "DNSMachineName")) {
2359 if (!get_mydnsfullname(hostname))
2360 return WERR_BADFILE;
2362 *needed = 2*(strlen(hostname)+1);
2363 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2365 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2366 for (i=0; i<strlen(hostname); i++) {
2367 (*data)[2*i]=hostname[i];
2368 (*data)[2*i+1]='\0';
2374 return WERR_BADFILE;
2377 /********************************************************************
2378 * spoolss_getprinterdata
2379 ********************************************************************/
2381 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2383 POLICY_HND *handle = &q_u->handle;
2384 UNISTR2 *valuename = &q_u->valuename;
2385 uint32 in_size = q_u->size;
2386 uint32 *type = &r_u->type;
2387 uint32 *out_size = &r_u->size;
2388 uint8 **data = &r_u->data;
2389 uint32 *needed = &r_u->needed;
2392 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2393 NT_PRINTER_INFO_LEVEL *printer = NULL;
2397 * Reminder: when it's a string, the length is in BYTES
2398 * even if UNICODE is negociated.
2403 *out_size = in_size;
2405 /* in case of problem, return some default values */
2410 DEBUG(4,("_spoolss_getprinterdata\n"));
2413 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2414 status = WERR_BADFID;
2418 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2420 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2421 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2424 if ( !get_printer_snum(p,handle, &snum) ) {
2425 status = WERR_BADFID;
2429 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2430 if ( !W_ERROR_IS_OK(status) )
2433 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2435 if ( strequal(value, "ChangeId") ) {
2437 *needed = sizeof(uint32);
2438 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2439 status = WERR_NOMEM;
2442 SIVAL( *data, 0, printer->info_2->changeid );
2446 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2449 if (*needed > *out_size)
2450 status = WERR_MORE_DATA;
2453 if ( !W_ERROR_IS_OK(status) )
2455 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2457 /* reply this param doesn't exist */
2460 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2462 free_a_printer( &printer, 2 );
2471 /* cleanup & exit */
2474 free_a_printer( &printer, 2 );
2479 /*********************************************************
2480 Connect to the client machine.
2481 **********************************************************/
2483 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2484 struct in_addr *client_ip, const char *remote_machine)
2486 ZERO_STRUCTP(the_cli);
2488 if(cli_initialise(the_cli) == NULL) {
2489 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2493 if ( is_zero_ip(*client_ip) ) {
2494 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2495 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2496 cli_shutdown(the_cli);
2500 if (ismyip(the_cli->dest_ip)) {
2501 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2502 cli_shutdown(the_cli);
2507 the_cli->dest_ip.s_addr = client_ip->s_addr;
2508 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2509 inet_ntoa(*client_ip) ));
2512 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2513 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) ));
2514 cli_shutdown(the_cli);
2518 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2519 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2521 cli_shutdown(the_cli);
2525 the_cli->protocol = PROTOCOL_NT1;
2526 cli_setup_signing_state(the_cli, lp_client_signing());
2528 if (!cli_negprot(the_cli)) {
2529 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2530 cli_shutdown(the_cli);
2534 if (the_cli->protocol != PROTOCOL_NT1) {
2535 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2536 cli_shutdown(the_cli);
2541 * Do an anonymous session setup.
2544 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2545 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2546 cli_shutdown(the_cli);
2550 if (!(the_cli->sec_mode & 1)) {
2551 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2552 cli_shutdown(the_cli);
2556 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2557 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) ));
2558 cli_shutdown(the_cli);
2563 * Ok - we have an anonymous connection to the IPC$ share.
2564 * Now start the NT Domain stuff :-).
2567 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2568 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)));
2569 cli_nt_session_close(the_cli);
2570 cli_ulogoff(the_cli);
2571 cli_shutdown(the_cli);
2578 /***************************************************************************
2579 Connect to the client.
2580 ****************************************************************************/
2582 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2583 uint32 localprinter, uint32 type,
2584 POLICY_HND *handle, struct in_addr *client_ip)
2589 * If it's the first connection, contact the client
2590 * and connect to the IPC$ share anonymously
2592 if (smb_connections==0) {
2593 fstring unix_printer;
2595 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2597 ZERO_STRUCT(notify_cli);
2599 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2602 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2603 /* Tell the connections db we're now interested in printer
2604 * notify messages. */
2605 register_message_flags( True, FLAG_MSG_PRINTING );
2609 * Tell the specific printing tdb we want messages for this printer
2610 * by registering our PID.
2613 if (!print_notify_register_pid(snum))
2614 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2618 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2621 if (!W_ERROR_IS_OK(result))
2622 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2623 dos_errstr(result)));
2625 return (W_ERROR_IS_OK(result));
2628 /********************************************************************
2630 * ReplyFindFirstPrinterChangeNotifyEx
2632 * before replying OK: status=0 a rpc call is made to the workstation
2633 * asking ReplyOpenPrinter
2635 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2636 * called from api_spoolss_rffpcnex
2637 ********************************************************************/
2639 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2641 POLICY_HND *handle = &q_u->handle;
2642 uint32 flags = q_u->flags;
2643 uint32 options = q_u->options;
2644 UNISTR2 *localmachine = &q_u->localmachine;
2645 uint32 printerlocal = q_u->printerlocal;
2647 SPOOL_NOTIFY_OPTION *option = q_u->option;
2648 struct in_addr client_ip;
2650 /* store the notify value in the printer struct */
2652 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2655 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2659 Printer->notify.flags=flags;
2660 Printer->notify.options=options;
2661 Printer->notify.printerlocal=printerlocal;
2663 if (Printer->notify.option)
2664 free_spool_notify_option(&Printer->notify.option);
2666 Printer->notify.option=dup_spool_notify_option(option);
2668 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2669 sizeof(Printer->notify.localmachine)-1);
2671 /* Connect to the client machine and send a ReplyOpenPrinter */
2673 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2675 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2676 !get_printer_snum(p, handle, &snum) )
2679 client_ip.s_addr = inet_addr(p->conn->client_address);
2681 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2682 Printer->notify.printerlocal, 1,
2683 &Printer->notify.client_hnd, &client_ip))
2684 return WERR_SERVER_UNAVAILABLE;
2686 Printer->notify.client_connected=True;
2691 /*******************************************************************
2692 * fill a notify_info_data with the servername
2693 ********************************************************************/
2695 void spoolss_notify_server_name(int snum,
2696 SPOOL_NOTIFY_INFO_DATA *data,
2697 print_queue_struct *queue,
2698 NT_PRINTER_INFO_LEVEL *printer,
2699 TALLOC_CTX *mem_ctx)
2701 pstring temp_name, temp;
2704 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2706 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2708 data->notify_data.data.length = len;
2709 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2711 if (!data->notify_data.data.string) {
2712 data->notify_data.data.length = 0;
2716 memcpy(data->notify_data.data.string, temp, len);
2719 /*******************************************************************
2720 * fill a notify_info_data with the printername (not including the servername).
2721 ********************************************************************/
2723 void spoolss_notify_printer_name(int snum,
2724 SPOOL_NOTIFY_INFO_DATA *data,
2725 print_queue_struct *queue,
2726 NT_PRINTER_INFO_LEVEL *printer,
2727 TALLOC_CTX *mem_ctx)
2732 /* the notify name should not contain the \\server\ part */
2733 char *p = strrchr(printer->info_2->printername, '\\');
2736 p = printer->info_2->printername;
2741 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2743 data->notify_data.data.length = len;
2744 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2746 if (!data->notify_data.data.string) {
2747 data->notify_data.data.length = 0;
2751 memcpy(data->notify_data.data.string, temp, len);
2754 /*******************************************************************
2755 * fill a notify_info_data with the servicename
2756 ********************************************************************/
2758 void spoolss_notify_share_name(int snum,
2759 SPOOL_NOTIFY_INFO_DATA *data,
2760 print_queue_struct *queue,
2761 NT_PRINTER_INFO_LEVEL *printer,
2762 TALLOC_CTX *mem_ctx)
2767 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2769 data->notify_data.data.length = len;
2770 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2772 if (!data->notify_data.data.string) {
2773 data->notify_data.data.length = 0;
2777 memcpy(data->notify_data.data.string, temp, len);
2780 /*******************************************************************
2781 * fill a notify_info_data with the port name
2782 ********************************************************************/
2784 void spoolss_notify_port_name(int snum,
2785 SPOOL_NOTIFY_INFO_DATA *data,
2786 print_queue_struct *queue,
2787 NT_PRINTER_INFO_LEVEL *printer,
2788 TALLOC_CTX *mem_ctx)
2793 /* even if it's strange, that's consistant in all the code */
2795 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2797 data->notify_data.data.length = len;
2798 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2800 if (!data->notify_data.data.string) {
2801 data->notify_data.data.length = 0;
2805 memcpy(data->notify_data.data.string, temp, len);
2808 /*******************************************************************
2809 * fill a notify_info_data with the printername
2810 * but it doesn't exist, have to see what to do
2811 ********************************************************************/
2813 void spoolss_notify_driver_name(int snum,
2814 SPOOL_NOTIFY_INFO_DATA *data,
2815 print_queue_struct *queue,
2816 NT_PRINTER_INFO_LEVEL *printer,
2817 TALLOC_CTX *mem_ctx)
2822 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2824 data->notify_data.data.length = len;
2825 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2827 if (!data->notify_data.data.string) {
2828 data->notify_data.data.length = 0;
2832 memcpy(data->notify_data.data.string, temp, len);
2835 /*******************************************************************
2836 * fill a notify_info_data with the comment
2837 ********************************************************************/
2839 void spoolss_notify_comment(int snum,
2840 SPOOL_NOTIFY_INFO_DATA *data,
2841 print_queue_struct *queue,
2842 NT_PRINTER_INFO_LEVEL *printer,
2843 TALLOC_CTX *mem_ctx)
2848 if (*printer->info_2->comment == '\0')
2849 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2851 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2853 data->notify_data.data.length = len;
2854 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2856 if (!data->notify_data.data.string) {
2857 data->notify_data.data.length = 0;
2861 memcpy(data->notify_data.data.string, temp, len);
2864 /*******************************************************************
2865 * fill a notify_info_data with the comment
2866 * location = "Room 1, floor 2, building 3"
2867 ********************************************************************/
2869 void spoolss_notify_location(int snum,
2870 SPOOL_NOTIFY_INFO_DATA *data,
2871 print_queue_struct *queue,
2872 NT_PRINTER_INFO_LEVEL *printer,
2873 TALLOC_CTX *mem_ctx)
2878 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2880 data->notify_data.data.length = len;
2881 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2883 if (!data->notify_data.data.string) {
2884 data->notify_data.data.length = 0;
2888 memcpy(data->notify_data.data.string, temp, len);
2891 /*******************************************************************
2892 * fill a notify_info_data with the device mode
2893 * jfm:xxxx don't to it for know but that's a real problem !!!
2894 ********************************************************************/
2896 static void spoolss_notify_devmode(int snum,
2897 SPOOL_NOTIFY_INFO_DATA *data,
2898 print_queue_struct *queue,
2899 NT_PRINTER_INFO_LEVEL *printer,
2900 TALLOC_CTX *mem_ctx)
2904 /*******************************************************************
2905 * fill a notify_info_data with the separator file name
2906 ********************************************************************/
2908 void spoolss_notify_sepfile(int snum,
2909 SPOOL_NOTIFY_INFO_DATA *data,
2910 print_queue_struct *queue,
2911 NT_PRINTER_INFO_LEVEL *printer,
2912 TALLOC_CTX *mem_ctx)
2917 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2919 data->notify_data.data.length = len;
2920 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2922 if (!data->notify_data.data.string) {
2923 data->notify_data.data.length = 0;
2927 memcpy(data->notify_data.data.string, temp, len);
2930 /*******************************************************************
2931 * fill a notify_info_data with the print processor
2932 * jfm:xxxx return always winprint to indicate we don't do anything to it
2933 ********************************************************************/
2935 void spoolss_notify_print_processor(int snum,
2936 SPOOL_NOTIFY_INFO_DATA *data,
2937 print_queue_struct *queue,
2938 NT_PRINTER_INFO_LEVEL *printer,
2939 TALLOC_CTX *mem_ctx)
2944 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2946 data->notify_data.data.length = len;
2947 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2949 if (!data->notify_data.data.string) {
2950 data->notify_data.data.length = 0;
2954 memcpy(data->notify_data.data.string, temp, len);
2957 /*******************************************************************
2958 * fill a notify_info_data with the print processor options
2959 * jfm:xxxx send an empty string
2960 ********************************************************************/
2962 void spoolss_notify_parameters(int snum,
2963 SPOOL_NOTIFY_INFO_DATA *data,
2964 print_queue_struct *queue,
2965 NT_PRINTER_INFO_LEVEL *printer,
2966 TALLOC_CTX *mem_ctx)
2971 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2973 data->notify_data.data.length = len;
2974 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2976 if (!data->notify_data.data.string) {
2977 data->notify_data.data.length = 0;
2981 memcpy(data->notify_data.data.string, temp, len);
2984 /*******************************************************************
2985 * fill a notify_info_data with the data type
2986 * jfm:xxxx always send RAW as data type
2987 ********************************************************************/
2989 void spoolss_notify_datatype(int snum,
2990 SPOOL_NOTIFY_INFO_DATA *data,
2991 print_queue_struct *queue,
2992 NT_PRINTER_INFO_LEVEL *printer,
2993 TALLOC_CTX *mem_ctx)
2998 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3000 data->notify_data.data.length = len;
3001 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3003 if (!data->notify_data.data.string) {
3004 data->notify_data.data.length = 0;
3008 memcpy(data->notify_data.data.string, temp, len);
3011 /*******************************************************************
3012 * fill a notify_info_data with the security descriptor
3013 * jfm:xxxx send an null pointer to say no security desc
3014 * have to implement security before !
3015 ********************************************************************/
3017 static void spoolss_notify_security_desc(int snum,
3018 SPOOL_NOTIFY_INFO_DATA *data,
3019 print_queue_struct *queue,
3020 NT_PRINTER_INFO_LEVEL *printer,
3021 TALLOC_CTX *mem_ctx)
3023 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3024 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3027 /*******************************************************************
3028 * fill a notify_info_data with the attributes
3029 * jfm:xxxx a samba printer is always shared
3030 ********************************************************************/
3032 void spoolss_notify_attributes(int snum,
3033 SPOOL_NOTIFY_INFO_DATA *data,
3034 print_queue_struct *queue,
3035 NT_PRINTER_INFO_LEVEL *printer,
3036 TALLOC_CTX *mem_ctx)
3038 data->notify_data.value[0] = printer->info_2->attributes;
3039 data->notify_data.value[1] = 0;
3042 /*******************************************************************
3043 * fill a notify_info_data with the priority
3044 ********************************************************************/
3046 static void spoolss_notify_priority(int snum,
3047 SPOOL_NOTIFY_INFO_DATA *data,
3048 print_queue_struct *queue,
3049 NT_PRINTER_INFO_LEVEL *printer,
3050 TALLOC_CTX *mem_ctx)
3052 data->notify_data.value[0] = printer->info_2->priority;
3053 data->notify_data.value[1] = 0;
3056 /*******************************************************************
3057 * fill a notify_info_data with the default priority
3058 ********************************************************************/
3060 static void spoolss_notify_default_priority(int snum,
3061 SPOOL_NOTIFY_INFO_DATA *data,
3062 print_queue_struct *queue,
3063 NT_PRINTER_INFO_LEVEL *printer,
3064 TALLOC_CTX *mem_ctx)
3066 data->notify_data.value[0] = printer->info_2->default_priority;
3067 data->notify_data.value[1] = 0;
3070 /*******************************************************************
3071 * fill a notify_info_data with the start time
3072 ********************************************************************/
3074 static void spoolss_notify_start_time(int snum,
3075 SPOOL_NOTIFY_INFO_DATA *data,
3076 print_queue_struct *queue,
3077 NT_PRINTER_INFO_LEVEL *printer,
3078 TALLOC_CTX *mem_ctx)
3080 data->notify_data.value[0] = printer->info_2->starttime;
3081 data->notify_data.value[1] = 0;
3084 /*******************************************************************
3085 * fill a notify_info_data with the until time
3086 ********************************************************************/
3088 static void spoolss_notify_until_time(int snum,
3089 SPOOL_NOTIFY_INFO_DATA *data,
3090 print_queue_struct *queue,
3091 NT_PRINTER_INFO_LEVEL *printer,
3092 TALLOC_CTX *mem_ctx)
3094 data->notify_data.value[0] = printer->info_2->untiltime;
3095 data->notify_data.value[1] = 0;
3098 /*******************************************************************
3099 * fill a notify_info_data with the status
3100 ********************************************************************/
3102 static void spoolss_notify_status(int snum,
3103 SPOOL_NOTIFY_INFO_DATA *data,
3104 print_queue_struct *queue,
3105 NT_PRINTER_INFO_LEVEL *printer,
3106 TALLOC_CTX *mem_ctx)
3108 print_status_struct status;
3110 print_queue_length(snum, &status);
3111 data->notify_data.value[0]=(uint32) status.status;
3112 data->notify_data.value[1] = 0;
3115 /*******************************************************************
3116 * fill a notify_info_data with the number of jobs queued
3117 ********************************************************************/
3119 void spoolss_notify_cjobs(int snum,
3120 SPOOL_NOTIFY_INFO_DATA *data,
3121 print_queue_struct *queue,
3122 NT_PRINTER_INFO_LEVEL *printer,
3123 TALLOC_CTX *mem_ctx)
3125 data->notify_data.value[0] = print_queue_length(snum, NULL);
3126 data->notify_data.value[1] = 0;
3129 /*******************************************************************
3130 * fill a notify_info_data with the average ppm
3131 ********************************************************************/
3133 static void spoolss_notify_average_ppm(int snum,
3134 SPOOL_NOTIFY_INFO_DATA *data,
3135 print_queue_struct *queue,
3136 NT_PRINTER_INFO_LEVEL *printer,
3137 TALLOC_CTX *mem_ctx)
3139 /* always respond 8 pages per minutes */
3140 /* a little hard ! */
3141 data->notify_data.value[0] = printer->info_2->averageppm;
3142 data->notify_data.value[1] = 0;
3145 /*******************************************************************
3146 * fill a notify_info_data with username
3147 ********************************************************************/
3149 static void spoolss_notify_username(int snum,
3150 SPOOL_NOTIFY_INFO_DATA *data,
3151 print_queue_struct *queue,
3152 NT_PRINTER_INFO_LEVEL *printer,
3153 TALLOC_CTX *mem_ctx)
3158 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3160 data->notify_data.data.length = len;
3161 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3163 if (!data->notify_data.data.string) {
3164 data->notify_data.data.length = 0;
3168 memcpy(data->notify_data.data.string, temp, len);
3171 /*******************************************************************
3172 * fill a notify_info_data with job status
3173 ********************************************************************/
3175 static void spoolss_notify_job_status(int snum,
3176 SPOOL_NOTIFY_INFO_DATA *data,
3177 print_queue_struct *queue,
3178 NT_PRINTER_INFO_LEVEL *printer,
3179 TALLOC_CTX *mem_ctx)
3181 data->notify_data.value[0]=nt_printj_status(queue->status);
3182 data->notify_data.value[1] = 0;
3185 /*******************************************************************
3186 * fill a notify_info_data with job name
3187 ********************************************************************/
3189 static void spoolss_notify_job_name(int snum,
3190 SPOOL_NOTIFY_INFO_DATA *data,
3191 print_queue_struct *queue,
3192 NT_PRINTER_INFO_LEVEL *printer,
3193 TALLOC_CTX *mem_ctx)
3198 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3200 data->notify_data.data.length = len;
3201 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3203 if (!data->notify_data.data.string) {
3204 data->notify_data.data.length = 0;
3208 memcpy(data->notify_data.data.string, temp, len);
3211 /*******************************************************************
3212 * fill a notify_info_data with job status
3213 ********************************************************************/
3215 static void spoolss_notify_job_status_string(int snum,
3216 SPOOL_NOTIFY_INFO_DATA *data,
3217 print_queue_struct *queue,
3218 NT_PRINTER_INFO_LEVEL *printer,
3219 TALLOC_CTX *mem_ctx)
3222 * Now we're returning job status codes we just return a "" here. JRA.
3229 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3232 switch (queue->status) {
3237 p = ""; /* NT provides the paused string */
3246 #endif /* NO LONGER NEEDED. */
3248 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3250 data->notify_data.data.length = len;
3251 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3253 if (!data->notify_data.data.string) {
3254 data->notify_data.data.length = 0;
3258 memcpy(data->notify_data.data.string, temp, len);
3261 /*******************************************************************
3262 * fill a notify_info_data with job time
3263 ********************************************************************/
3265 static void spoolss_notify_job_time(int snum,
3266 SPOOL_NOTIFY_INFO_DATA *data,
3267 print_queue_struct *queue,
3268 NT_PRINTER_INFO_LEVEL *printer,
3269 TALLOC_CTX *mem_ctx)
3271 data->notify_data.value[0]=0x0;
3272 data->notify_data.value[1]=0;
3275 /*******************************************************************
3276 * fill a notify_info_data with job size
3277 ********************************************************************/
3279 static void spoolss_notify_job_size(int snum,
3280 SPOOL_NOTIFY_INFO_DATA *data,
3281 print_queue_struct *queue,
3282 NT_PRINTER_INFO_LEVEL *printer,
3283 TALLOC_CTX *mem_ctx)
3285 data->notify_data.value[0]=queue->size;
3286 data->notify_data.value[1]=0;
3289 /*******************************************************************
3290 * fill a notify_info_data with page info
3291 ********************************************************************/
3292 static void spoolss_notify_total_pages(int snum,
3293 SPOOL_NOTIFY_INFO_DATA *data,
3294 print_queue_struct *queue,
3295 NT_PRINTER_INFO_LEVEL *printer,
3296 TALLOC_CTX *mem_ctx)
3298 data->notify_data.value[0]=queue->page_count;
3299 data->notify_data.value[1]=0;
3302 /*******************************************************************
3303 * fill a notify_info_data with pages printed info.
3304 ********************************************************************/
3305 static void spoolss_notify_pages_printed(int snum,
3306 SPOOL_NOTIFY_INFO_DATA *data,
3307 print_queue_struct *queue,
3308 NT_PRINTER_INFO_LEVEL *printer,
3309 TALLOC_CTX *mem_ctx)
3311 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3312 data->notify_data.value[1]=0;
3315 /*******************************************************************
3316 Fill a notify_info_data with job position.
3317 ********************************************************************/
3319 static void spoolss_notify_job_position(int snum,
3320 SPOOL_NOTIFY_INFO_DATA *data,
3321 print_queue_struct *queue,
3322 NT_PRINTER_INFO_LEVEL *printer,
3323 TALLOC_CTX *mem_ctx)
3325 data->notify_data.value[0]=queue->job;
3326 data->notify_data.value[1]=0;
3329 /*******************************************************************
3330 Fill a notify_info_data with submitted time.
3331 ********************************************************************/
3333 static void spoolss_notify_submitted_time(int snum,
3334 SPOOL_NOTIFY_INFO_DATA *data,
3335 print_queue_struct *queue,
3336 NT_PRINTER_INFO_LEVEL *printer,
3337 TALLOC_CTX *mem_ctx)
3344 t=gmtime(&queue->time);
3346 len = sizeof(SYSTEMTIME);
3348 data->notify_data.data.length = len;
3349 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3351 if (!data->notify_data.data.string) {
3352 data->notify_data.data.length = 0;
3356 make_systemtime(&st, t);
3359 * Systemtime must be linearized as a set of UINT16's.
3360 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3363 p = (char *)data->notify_data.data.string;
3364 SSVAL(p, 0, st.year);
3365 SSVAL(p, 2, st.month);
3366 SSVAL(p, 4, st.dayofweek);
3367 SSVAL(p, 6, st.day);
3368 SSVAL(p, 8, st.hour);
3369 SSVAL(p, 10, st.minute);
3370 SSVAL(p, 12, st.second);
3371 SSVAL(p, 14, st.milliseconds);
3374 struct s_notify_info_data_table
3380 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3381 print_queue_struct *queue,
3382 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3385 /* A table describing the various print notification constants and
3386 whether the notification data is a pointer to a variable sized
3387 buffer, a one value uint32 or a two value uint32. */
3389 static const struct s_notify_info_data_table notify_info_data_table[] =
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3442 /*******************************************************************
3443 Return the size of info_data structure.
3444 ********************************************************************/
3446 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3450 for (i = 0; i < sizeof(notify_info_data_table); i++)
3452 if ( (notify_info_data_table[i].type == type)
3453 && (notify_info_data_table[i].field == field) )
3455 switch(notify_info_data_table[i].size)
3457 case NOTIFY_ONE_VALUE:
3458 case NOTIFY_TWO_VALUE:
3463 /* The only pointer notify data I have seen on
3464 the wire is the submitted time and this has
3465 the notify size set to 4. -tpot */
3467 case NOTIFY_POINTER:
3470 case NOTIFY_SECDESC:
3476 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3481 /*******************************************************************
3482 Return the type of notify_info_data.
3483 ********************************************************************/
3485 static int type_of_notify_info_data(uint16 type, uint16 field)
3489 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3490 if (notify_info_data_table[i].type == type &&
3491 notify_info_data_table[i].field == field)
3492 return notify_info_data_table[i].size;
3498 /****************************************************************************
3499 ****************************************************************************/
3501 static int search_notify(uint16 type, uint16 field, int *value)
3505 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3506 if (notify_info_data_table[i].type == type &&
3507 notify_info_data_table[i].field == field &&
3508 notify_info_data_table[i].fn != NULL) {
3517 /****************************************************************************
3518 ****************************************************************************/
3520 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3522 info_data->type = type;
3523 info_data->field = field;
3524 info_data->reserved = 0;
3526 info_data->size = size_of_notify_info_data(type, field);
3527 info_data->enc_type = type_of_notify_info_data(type, field);
3534 /*******************************************************************
3536 * fill a notify_info struct with info asked
3538 ********************************************************************/
3540 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3541 snum, SPOOL_NOTIFY_OPTION_TYPE
3542 *option_type, uint32 id,
3543 TALLOC_CTX *mem_ctx)
3549 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3550 NT_PRINTER_INFO_LEVEL *printer = NULL;
3551 print_queue_struct *queue=NULL;
3553 type=option_type->type;
3555 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3556 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3557 option_type->count, lp_servicename(snum)));
3559 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3562 for(field_num=0; field_num<option_type->count; field_num++) {
3563 field = option_type->fields[field_num];
3565 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3567 if (!search_notify(type, field, &j) )
3570 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3571 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3576 current_data = &info->data[info->count];
3578 construct_info_data(current_data, type, field, id);
3580 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3581 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3583 notify_info_data_table[j].fn(snum, current_data, queue,
3589 free_a_printer(&printer, 2);
3593 /*******************************************************************
3595 * fill a notify_info struct with info asked
3597 ********************************************************************/
3599 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3600 SPOOL_NOTIFY_INFO *info,
3601 NT_PRINTER_INFO_LEVEL *printer,
3602 int snum, SPOOL_NOTIFY_OPTION_TYPE
3603 *option_type, uint32 id,
3604 TALLOC_CTX *mem_ctx)
3610 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3612 DEBUG(4,("construct_notify_jobs_info\n"));
3614 type = option_type->type;
3616 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3617 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3618 option_type->count));
3620 for(field_num=0; field_num<option_type->count; field_num++) {
3621 field = option_type->fields[field_num];
3623 if (!search_notify(type, field, &j) )
3626 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3627 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3630 else info->data = tid;
3632 current_data=&(info->data[info->count]);
3634 construct_info_data(current_data, type, field, id);
3635 notify_info_data_table[j].fn(snum, current_data, queue,
3644 * JFM: The enumeration is not that simple, it's even non obvious.
3646 * let's take an example: I want to monitor the PRINTER SERVER for
3647 * the printer's name and the number of jobs currently queued.
3648 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3649 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3651 * I have 3 printers on the back of my server.
3653 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3656 * 1 printer 1 name 1
3657 * 2 printer 1 cjob 1
3658 * 3 printer 2 name 2
3659 * 4 printer 2 cjob 2
3660 * 5 printer 3 name 3
3661 * 6 printer 3 name 3
3663 * that's the print server case, the printer case is even worse.
3666 /*******************************************************************
3668 * enumerate all printers on the printserver
3669 * fill a notify_info struct with info asked
3671 ********************************************************************/
3673 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3674 SPOOL_NOTIFY_INFO *info,
3675 TALLOC_CTX *mem_ctx)
3678 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3679 int n_services=lp_numservices();
3681 SPOOL_NOTIFY_OPTION *option;
3682 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3684 DEBUG(4,("printserver_notify_info\n"));
3689 option=Printer->notify.option;
3694 for (i=0; i<option->count; i++) {
3695 option_type=&(option->ctr.type[i]);
3697 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3700 for (snum=0; snum<n_services; snum++)
3702 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3703 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3709 * Debugging information, don't delete.
3712 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3713 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3714 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3716 for (i=0; i<info->count; i++) {
3717 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3718 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3719 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3726 /*******************************************************************
3728 * fill a notify_info struct with info asked
3730 ********************************************************************/
3732 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3733 TALLOC_CTX *mem_ctx)
3736 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3739 SPOOL_NOTIFY_OPTION *option;
3740 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3742 print_queue_struct *queue=NULL;
3743 print_status_struct status;
3745 DEBUG(4,("printer_notify_info\n"));
3750 option=Printer->notify.option;
3756 get_printer_snum(p, hnd, &snum);
3758 for (i=0; i<option->count; i++) {
3759 option_type=&option->ctr.type[i];
3761 switch ( option_type->type ) {
3762 case PRINTER_NOTIFY_TYPE:
3763 if(construct_notify_printer_info(Printer, info, snum,
3769 case JOB_NOTIFY_TYPE: {
3770 NT_PRINTER_INFO_LEVEL *printer = NULL;
3772 count = print_queue_status(snum, &queue, &status);
3774 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3777 for (j=0; j<count; j++) {
3778 construct_notify_jobs_info(&queue[j], info,
3785 free_a_printer(&printer, 2);
3795 * Debugging information, don't delete.
3798 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3799 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3800 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3802 for (i=0; i<info->count; i++) {
3803 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3804 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3805 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3811 /********************************************************************
3813 ********************************************************************/
3815 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3817 POLICY_HND *handle = &q_u->handle;
3818 SPOOL_NOTIFY_INFO *info = &r_u->info;
3820 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3821 WERROR result = WERR_BADFID;
3823 /* we always have a NOTIFY_INFO struct */
3827 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3828 OUR_HANDLE(handle)));
3832 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3835 * We are now using the change value, and
3836 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3837 * I don't have a global notification system, I'm sending back all the
3838 * informations even when _NOTHING_ has changed.
3841 /* We need to keep track of the change value to send back in
3842 RRPCN replies otherwise our updates are ignored. */
3844 Printer->notify.fnpcn = True;
3846 if (Printer->notify.client_connected) {
3847 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3848 Printer->notify.change = q_u->change;
3851 /* just ignore the SPOOL_NOTIFY_OPTION */
3853 switch (Printer->printer_type) {
3854 case PRINTER_HANDLE_IS_PRINTSERVER:
3855 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3858 case PRINTER_HANDLE_IS_PRINTER:
3859 result = printer_notify_info(p, handle, info, p->mem_ctx);
3863 Printer->notify.fnpcn = False;
3869 /********************************************************************
3870 * construct_printer_info_0
3871 * fill a printer_info_0 struct
3872 ********************************************************************/
3874 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3878 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3879 counter_printer_0 *session_counter;
3880 uint32 global_counter;
3883 print_status_struct status;
3885 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3888 count = print_queue_length(snum, &status);
3890 /* check if we already have a counter for this printer */
3891 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3893 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3894 if (session_counter->snum == snum)
3898 /* it's the first time, add it to the list */
3899 if (session_counter==NULL) {
3900 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3901 free_a_printer(&ntprinter, 2);
3904 ZERO_STRUCTP(session_counter);
3905 session_counter->snum=snum;
3906 session_counter->counter=0;
3907 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3911 session_counter->counter++;
3914 * the global_counter should be stored in a TDB as it's common to all the clients
3915 * and should be zeroed on samba startup
3917 global_counter=session_counter->counter;
3919 pstrcpy(chaine,ntprinter->info_2->printername);
3921 init_unistr(&printer->printername, chaine);
3923 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3924 init_unistr(&printer->servername, chaine);
3926 printer->cjobs = count;
3927 printer->total_jobs = 0;
3928 printer->total_bytes = 0;
3930 setuptime = (time_t)ntprinter->info_2->setuptime;
3931 t=gmtime(&setuptime);
3933 printer->year = t->tm_year+1900;
3934 printer->month = t->tm_mon+1;
3935 printer->dayofweek = t->tm_wday;
3936 printer->day = t->tm_mday;
3937 printer->hour = t->tm_hour;
3938 printer->minute = t->tm_min;
3939 printer->second = t->tm_sec;
3940 printer->milliseconds = 0;
3942 printer->global_counter = global_counter;
3943 printer->total_pages = 0;
3945 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3946 printer->major_version = 0x0005; /* NT 5 */
3947 printer->build_version = 0x0893; /* build 2195 */
3949 printer->unknown7 = 0x1;
3950 printer->unknown8 = 0x0;
3951 printer->unknown9 = 0x0;
3952 printer->session_counter = session_counter->counter;
3953 printer->unknown11 = 0x0;
3954 printer->printer_errors = 0x0; /* number of print failure */
3955 printer->unknown13 = 0x0;
3956 printer->unknown14 = 0x1;
3957 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3958 printer->unknown16 = 0x0;
3959 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3960 printer->unknown18 = 0x0;
3961 printer->status = nt_printq_status(status.status);
3962 printer->unknown20 = 0x0;
3963 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3964 printer->unknown22 = 0x0;
3965 printer->unknown23 = 0x6; /* 6 ???*/
3966 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3967 printer->unknown25 = 0;
3968 printer->unknown26 = 0;
3969 printer->unknown27 = 0;
3970 printer->unknown28 = 0;
3971 printer->unknown29 = 0;
3973 free_a_printer(&ntprinter,2);
3977 /********************************************************************
3978 * construct_printer_info_1
3979 * fill a printer_info_1 struct
3980 ********************************************************************/
3981 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3985 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3987 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3990 printer->flags=flags;
3992 if (*ntprinter->info_2->comment == '\0') {
3993 init_unistr(&printer->comment, lp_comment(snum));
3994 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3995 ntprinter->info_2->drivername, lp_comment(snum));
3998 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3999 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4000 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4003 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4005 init_unistr(&printer->description, chaine);
4006 init_unistr(&printer->name, chaine2);
4008 free_a_printer(&ntprinter,2);
4013 /****************************************************************************
4014 Free a DEVMODE struct.
4015 ****************************************************************************/
4017 static void free_dev_mode(DEVICEMODE *dev)
4022 SAFE_FREE(dev->private);
4027 /****************************************************************************
4028 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4029 should be valid upon entry
4030 ****************************************************************************/
4032 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4034 if ( !devmode || !ntdevmode )
4037 init_unistr(&devmode->devicename, ntdevmode->devicename);
4039 init_unistr(&devmode->formname, ntdevmode->formname);
4041 devmode->specversion = ntdevmode->specversion;
4042 devmode->driverversion = ntdevmode->driverversion;
4043 devmode->size = ntdevmode->size;
4044 devmode->driverextra = ntdevmode->driverextra;
4045 devmode->fields = ntdevmode->fields;
4047 devmode->orientation = ntdevmode->orientation;
4048 devmode->papersize = ntdevmode->papersize;
4049 devmode->paperlength = ntdevmode->paperlength;
4050 devmode->paperwidth = ntdevmode->paperwidth;
4051 devmode->scale = ntdevmode->scale;
4052 devmode->copies = ntdevmode->copies;
4053 devmode->defaultsource = ntdevmode->defaultsource;
4054 devmode->printquality = ntdevmode->printquality;
4055 devmode->color = ntdevmode->color;
4056 devmode->duplex = ntdevmode->duplex;
4057 devmode->yresolution = ntdevmode->yresolution;
4058 devmode->ttoption = ntdevmode->ttoption;
4059 devmode->collate = ntdevmode->collate;
4060 devmode->icmmethod = ntdevmode->icmmethod;
4061 devmode->icmintent = ntdevmode->icmintent;
4062 devmode->mediatype = ntdevmode->mediatype;
4063 devmode->dithertype = ntdevmode->dithertype;
4065 if (ntdevmode->private != NULL) {
4066 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4073 /****************************************************************************
4074 Create a DEVMODE struct. Returns malloced memory.
4075 ****************************************************************************/
4077 DEVICEMODE *construct_dev_mode(int snum)
4079 NT_PRINTER_INFO_LEVEL *printer = NULL;
4080 DEVICEMODE *devmode = NULL;
4082 DEBUG(7,("construct_dev_mode\n"));
4084 DEBUGADD(8,("getting printer characteristics\n"));
4086 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4089 if ( !printer->info_2->devmode ) {
4090 DEBUG(5, ("BONG! There was no device mode!\n"));
4094 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4095 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4099 ZERO_STRUCTP(devmode);
4101 DEBUGADD(8,("loading DEVICEMODE\n"));
4103 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4104 free_dev_mode( devmode );
4109 free_a_printer(&printer,2);
4114 /********************************************************************
4115 * construct_printer_info_2
4116 * fill a printer_info_2 struct
4117 ********************************************************************/
4119 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4122 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4124 print_status_struct status;
4126 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4129 count = print_queue_length(snum, &status);
4131 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4132 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4133 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4134 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4135 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4137 if (*ntprinter->info_2->comment == '\0')
4138 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4140 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4142 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4143 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4144 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4145 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4146 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4148 printer->attributes = ntprinter->info_2->attributes;
4150 printer->priority = ntprinter->info_2->priority; /* priority */
4151 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4152 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4153 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4154 printer->status = nt_printq_status(status.status); /* status */
4155 printer->cjobs = count; /* jobs */
4156 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4158 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4159 DEBUG(8, ("Returning NULL Devicemode!\n"));
4162 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4163 /* steal the printer info sec_desc structure. [badly done]. */
4164 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4165 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4166 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4167 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4170 printer->secdesc = NULL;
4173 free_a_printer(&ntprinter, 2);
4177 /********************************************************************
4178 * construct_printer_info_3
4179 * fill a printer_info_3 struct
4180 ********************************************************************/
4182 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4184 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4185 PRINTER_INFO_3 *printer = NULL;
4187 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4191 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4192 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4196 ZERO_STRUCTP(printer);
4198 printer->flags = 4; /* These are the components of the SD we are returning. */
4199 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4200 /* steal the printer info sec_desc structure. [badly done]. */
4201 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4205 * Set the flags for the components we are returning.
4208 if (printer->secdesc->owner_sid)
4209 printer->flags |= OWNER_SECURITY_INFORMATION;
4211 if (printer->secdesc->grp_sid)
4212 printer->flags |= GROUP_SECURITY_INFORMATION;
4214 if (printer->secdesc->dacl)
4215 printer->flags |= DACL_SECURITY_INFORMATION;
4217 if (printer->secdesc->sacl)
4218 printer->flags |= SACL_SECURITY_INFORMATION;
4221 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4222 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4223 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4226 free_a_printer(&ntprinter, 2);
4228 *pp_printer = printer;
4232 /********************************************************************
4233 * construct_printer_info_4
4234 * fill a printer_info_4 struct
4235 ********************************************************************/
4237 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4239 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4241 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4244 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4245 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4246 printer->attributes = ntprinter->info_2->attributes;
4248 free_a_printer(&ntprinter, 2);
4252 /********************************************************************
4253 * construct_printer_info_5
4254 * fill a printer_info_5 struct
4255 ********************************************************************/
4257 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4259 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4261 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4264 init_unistr(&printer->printername, ntprinter->info_2->printername);
4265 init_unistr(&printer->portname, ntprinter->info_2->portname);
4266 printer->attributes = ntprinter->info_2->attributes;
4268 /* these two are not used by NT+ according to MSDN */
4270 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4271 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4273 free_a_printer(&ntprinter, 2);
4278 /********************************************************************
4279 * construct_printer_info_7
4280 * fill a printer_info_7 struct
4281 ********************************************************************/
4283 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4285 char *guid_str = NULL;
4288 if (is_printer_published(print_hnd, snum, &guid)) {
4289 asprintf(&guid_str, "{%s}",
4290 smb_uuid_string_static(smb_uuid_unpack_static(guid)));
4291 strupper_m(guid_str);
4292 init_unistr(&printer->guid, guid_str);
4293 printer->action = SPOOL_DS_PUBLISH;
4295 init_unistr(&printer->guid, "");
4296 printer->action = SPOOL_DS_UNPUBLISH;
4302 /********************************************************************
4303 Spoolss_enumprinters.
4304 ********************************************************************/
4306 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4310 int n_services=lp_numservices();
4311 PRINTER_INFO_1 *tp, *printers=NULL;
4312 PRINTER_INFO_1 current_prt;
4314 DEBUG(4,("enum_all_printers_info_1\n"));
4316 for (snum=0; snum<n_services; snum++) {
4317 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4318 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4320 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4321 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4322 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4323 SAFE_FREE(printers);
4328 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4330 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4336 /* check the required size. */
4337 for (i=0; i<*returned; i++)
4338 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4340 if (!alloc_buffer_size(buffer, *needed))
4341 return WERR_INSUFFICIENT_BUFFER;
4343 /* fill the buffer with the structures */
4344 for (i=0; i<*returned; i++)
4345 smb_io_printer_info_1("", buffer, &printers[i], 0);
4348 SAFE_FREE(printers);
4350 if (*needed > offered) {
4352 return WERR_INSUFFICIENT_BUFFER;
4358 /********************************************************************
4359 enum_all_printers_info_1_local.
4360 *********************************************************************/
4362 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4364 DEBUG(4,("enum_all_printers_info_1_local\n"));
4366 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4369 /********************************************************************
4370 enum_all_printers_info_1_name.
4371 *********************************************************************/
4373 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4377 DEBUG(4,("enum_all_printers_info_1_name\n"));
4379 if ((name[0] == '\\') && (name[1] == '\\'))
4382 if (is_myname_or_ipaddr(s)) {
4383 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4386 return WERR_INVALID_NAME;
4389 /********************************************************************
4390 enum_all_printers_info_1_remote.
4391 *********************************************************************/
4393 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4395 PRINTER_INFO_1 *printer;
4396 fstring printername;
4399 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4401 /* JFM: currently it's more a place holder than anything else.
4402 * In the spooler world there is a notion of server registration.
4403 * the print servers are registring (sp ?) on the PDC (in the same domain)
4405 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4408 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4413 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4414 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4415 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4417 init_unistr(&printer->description, desc);
4418 init_unistr(&printer->name, printername);
4419 init_unistr(&printer->comment, comment);
4420 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4422 /* check the required size. */
4423 *needed += spoolss_size_printer_info_1(printer);
4425 if (!alloc_buffer_size(buffer, *needed)) {
4427 return WERR_INSUFFICIENT_BUFFER;
4430 /* fill the buffer with the structures */
4431 smb_io_printer_info_1("", buffer, printer, 0);
4436 if (*needed > offered) {
4438 return WERR_INSUFFICIENT_BUFFER;
4444 /********************************************************************
4445 enum_all_printers_info_1_network.
4446 *********************************************************************/
4448 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4452 DEBUG(4,("enum_all_printers_info_1_network\n"));
4454 /* If we respond to a enum_printers level 1 on our name with flags
4455 set to PRINTER_ENUM_REMOTE with a list of printers then these
4456 printers incorrectly appear in the APW browse list.
4457 Specifically the printers for the server appear at the workgroup
4458 level where all the other servers in the domain are
4459 listed. Windows responds to this call with a
4460 WERR_CAN_NOT_COMPLETE so we should do the same. */
4462 if (name[0] == '\\' && name[1] == '\\')
4465 if (is_myname_or_ipaddr(s))
4466 return WERR_CAN_NOT_COMPLETE;
4468 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4471 /********************************************************************
4472 * api_spoolss_enumprinters
4474 * called from api_spoolss_enumprinters (see this to understand)
4475 ********************************************************************/
4477 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4481 int n_services=lp_numservices();
4482 PRINTER_INFO_2 *tp, *printers=NULL;
4483 PRINTER_INFO_2 current_prt;
4485 for (snum=0; snum<n_services; snum++) {
4486 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4487 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4489 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4490 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4491 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4492 SAFE_FREE(printers);
4497 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4498 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4504 /* check the required size. */
4505 for (i=0; i<*returned; i++)
4506 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4508 if (!alloc_buffer_size(buffer, *needed)) {
4509 for (i=0; i<*returned; i++) {
4510 free_devmode(printers[i].devmode);
4512 SAFE_FREE(printers);
4513 return WERR_INSUFFICIENT_BUFFER;
4516 /* fill the buffer with the structures */
4517 for (i=0; i<*returned; i++)
4518 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4521 for (i=0; i<*returned; i++) {
4522 free_devmode(printers[i].devmode);
4524 SAFE_FREE(printers);
4526 if (*needed > offered) {
4528 return WERR_INSUFFICIENT_BUFFER;
4534 /********************************************************************
4535 * handle enumeration of printers at level 1
4536 ********************************************************************/
4538 static WERROR enumprinters_level1( uint32 flags, fstring name,
4539 NEW_BUFFER *buffer, uint32 offered,
4540 uint32 *needed, uint32 *returned)
4542 /* Not all the flags are equals */
4544 if (flags & PRINTER_ENUM_LOCAL)
4545 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4547 if (flags & PRINTER_ENUM_NAME)
4548 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4550 if (flags & PRINTER_ENUM_REMOTE)
4551 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4553 if (flags & PRINTER_ENUM_NETWORK)
4554 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4556 return WERR_OK; /* NT4sp5 does that */
4559 /********************************************************************
4560 * handle enumeration of printers at level 2
4561 ********************************************************************/
4563 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4564 NEW_BUFFER *buffer, uint32 offered,
4565 uint32 *needed, uint32 *returned)
4567 char *s = servername;
4569 if (flags & PRINTER_ENUM_LOCAL) {
4570 return enum_all_printers_info_2(buffer, offered, needed, returned);
4573 if (flags & PRINTER_ENUM_NAME) {
4574 if ((servername[0] == '\\') && (servername[1] == '\\'))
4576 if (is_myname_or_ipaddr(s))
4577 return enum_all_printers_info_2(buffer, offered, needed, returned);
4579 return WERR_INVALID_NAME;
4582 if (flags & PRINTER_ENUM_REMOTE)
4583 return WERR_UNKNOWN_LEVEL;
4588 /********************************************************************
4589 * handle enumeration of printers at level 5
4590 ********************************************************************/
4592 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4593 NEW_BUFFER *buffer, uint32 offered,
4594 uint32 *needed, uint32 *returned)
4596 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4600 /********************************************************************
4601 * api_spoolss_enumprinters
4603 * called from api_spoolss_enumprinters (see this to understand)
4604 ********************************************************************/
4606 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4608 uint32 flags = q_u->flags;
4609 UNISTR2 *servername = &q_u->servername;
4610 uint32 level = q_u->level;
4611 NEW_BUFFER *buffer = NULL;
4612 uint32 offered = q_u->offered;
4613 uint32 *needed = &r_u->needed;
4614 uint32 *returned = &r_u->returned;
4618 /* that's an [in out] buffer */
4619 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4620 buffer = r_u->buffer;
4622 DEBUG(4,("_spoolss_enumprinters\n"));
4629 * flags==PRINTER_ENUM_NAME
4630 * if name=="" then enumerates all printers
4631 * if name!="" then enumerate the printer
4632 * flags==PRINTER_ENUM_REMOTE
4633 * name is NULL, enumerate printers
4634 * Level 2: name!="" enumerates printers, name can't be NULL
4635 * Level 3: doesn't exist
4636 * Level 4: does a local registry lookup
4637 * Level 5: same as Level 2
4640 unistr2_to_ascii(name, servername, sizeof(name)-1);
4645 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4647 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4649 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4654 return WERR_UNKNOWN_LEVEL;
4657 /****************************************************************************
4658 ****************************************************************************/
4660 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4662 PRINTER_INFO_0 *printer=NULL;
4664 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4667 construct_printer_info_0(print_hnd, printer, snum);
4669 /* check the required size. */
4670 *needed += spoolss_size_printer_info_0(printer);
4672 if (!alloc_buffer_size(buffer, *needed)) {
4674 return WERR_INSUFFICIENT_BUFFER;
4677 /* fill the buffer with the structures */
4678 smb_io_printer_info_0("", buffer, printer, 0);
4683 if (*needed > offered) {
4684 return WERR_INSUFFICIENT_BUFFER;
4690 /****************************************************************************
4691 ****************************************************************************/
4693 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4695 PRINTER_INFO_1 *printer=NULL;
4697 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4700 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4702 /* check the required size. */
4703 *needed += spoolss_size_printer_info_1(printer);
4705 if (!alloc_buffer_size(buffer, *needed)) {
4707 return WERR_INSUFFICIENT_BUFFER;
4710 /* fill the buffer with the structures */
4711 smb_io_printer_info_1("", buffer, printer, 0);
4716 if (*needed > offered) {
4717 return WERR_INSUFFICIENT_BUFFER;
4723 /****************************************************************************
4724 ****************************************************************************/
4726 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4728 PRINTER_INFO_2 *printer=NULL;
4730 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4733 construct_printer_info_2(print_hnd, printer, snum);
4735 /* check the required size. */
4736 *needed += spoolss_size_printer_info_2(printer);
4738 if (!alloc_buffer_size(buffer, *needed)) {
4739 free_printer_info_2(printer);
4740 return WERR_INSUFFICIENT_BUFFER;
4743 /* fill the buffer with the structures */
4744 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4745 free_printer_info_2(printer);
4750 free_printer_info_2(printer);
4752 if (*needed > offered) {
4753 return WERR_INSUFFICIENT_BUFFER;
4759 /****************************************************************************
4760 ****************************************************************************/
4762 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4764 PRINTER_INFO_3 *printer=NULL;
4766 if (!construct_printer_info_3(print_hnd, &printer, snum))
4769 /* check the required size. */
4770 *needed += spoolss_size_printer_info_3(printer);
4772 if (!alloc_buffer_size(buffer, *needed)) {
4773 free_printer_info_3(printer);
4774 return WERR_INSUFFICIENT_BUFFER;
4777 /* fill the buffer with the structures */
4778 smb_io_printer_info_3("", buffer, printer, 0);
4781 free_printer_info_3(printer);
4783 if (*needed > offered) {
4784 return WERR_INSUFFICIENT_BUFFER;
4790 /****************************************************************************
4791 ****************************************************************************/
4793 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4795 PRINTER_INFO_4 *printer=NULL;
4797 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4800 if (!construct_printer_info_4(print_hnd, printer, snum))
4803 /* check the required size. */
4804 *needed += spoolss_size_printer_info_4(printer);
4806 if (!alloc_buffer_size(buffer, *needed)) {
4807 free_printer_info_4(printer);
4808 return WERR_INSUFFICIENT_BUFFER;
4811 /* fill the buffer with the structures */
4812 smb_io_printer_info_4("", buffer, printer, 0);
4815 free_printer_info_4(printer);
4817 if (*needed > offered) {
4818 return WERR_INSUFFICIENT_BUFFER;
4824 /****************************************************************************
4825 ****************************************************************************/
4827 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4829 PRINTER_INFO_5 *printer=NULL;
4831 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4834 if (!construct_printer_info_5(print_hnd, printer, snum))
4837 /* check the required size. */
4838 *needed += spoolss_size_printer_info_5(printer);
4840 if (!alloc_buffer_size(buffer, *needed)) {
4841 free_printer_info_5(printer);
4842 return WERR_INSUFFICIENT_BUFFER;
4845 /* fill the buffer with the structures */
4846 smb_io_printer_info_5("", buffer, printer, 0);
4849 free_printer_info_5(printer);
4851 if (*needed > offered) {
4852 return WERR_INSUFFICIENT_BUFFER;
4858 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4860 PRINTER_INFO_7 *printer=NULL;
4862 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4865 if (!construct_printer_info_7(print_hnd, printer, snum))
4868 /* check the required size. */
4869 *needed += spoolss_size_printer_info_7(printer);
4871 if (!alloc_buffer_size(buffer, *needed)) {
4872 free_printer_info_7(printer);
4873 return WERR_INSUFFICIENT_BUFFER;
4876 /* fill the buffer with the structures */
4877 smb_io_printer_info_7("", buffer, printer, 0);
4880 free_printer_info_7(printer);
4882 if (*needed > offered) {
4883 return WERR_INSUFFICIENT_BUFFER;
4889 /****************************************************************************
4890 ****************************************************************************/
4892 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4894 POLICY_HND *handle = &q_u->handle;
4895 uint32 level = q_u->level;
4896 NEW_BUFFER *buffer = NULL;
4897 uint32 offered = q_u->offered;
4898 uint32 *needed = &r_u->needed;
4899 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4903 /* that's an [in out] buffer */
4904 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4905 buffer = r_u->buffer;
4909 if (!get_printer_snum(p, handle, &snum))
4914 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4916 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4918 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4920 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4922 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4924 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4926 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4928 return WERR_UNKNOWN_LEVEL;
4931 /********************************************************************
4932 * fill a DRIVER_INFO_1 struct
4933 ********************************************************************/
4935 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4937 init_unistr( &info->name, driver.info_3->name);
4940 /********************************************************************
4941 * construct_printer_driver_info_1
4942 ********************************************************************/
4944 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4946 NT_PRINTER_INFO_LEVEL *printer = NULL;
4947 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4949 ZERO_STRUCT(driver);
4951 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4952 return WERR_INVALID_PRINTER_NAME;
4954 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4955 return WERR_UNKNOWN_PRINTER_DRIVER;
4957 fill_printer_driver_info_1(info, driver, servername, architecture);
4959 free_a_printer(&printer,2);
4964 /********************************************************************
4965 * construct_printer_driver_info_2
4966 * fill a printer_info_2 struct
4967 ********************************************************************/
4969 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4973 info->version=driver.info_3->cversion;
4975 init_unistr( &info->name, driver.info_3->name );
4976 init_unistr( &info->architecture, driver.info_3->environment );
4979 if (strlen(driver.info_3->driverpath)) {
4980 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4981 init_unistr( &info->driverpath, temp );
4983 init_unistr( &info->driverpath, "" );
4985 if (strlen(driver.info_3->datafile)) {
4986 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4987 init_unistr( &info->datafile, temp );
4989 init_unistr( &info->datafile, "" );
4991 if (strlen(driver.info_3->configfile)) {
4992 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4993 init_unistr( &info->configfile, temp );
4995 init_unistr( &info->configfile, "" );
4998 /********************************************************************
4999 * construct_printer_driver_info_2
5000 * fill a printer_info_2 struct
5001 ********************************************************************/
5003 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5005 NT_PRINTER_INFO_LEVEL *printer = NULL;
5006 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5008 ZERO_STRUCT(printer);
5009 ZERO_STRUCT(driver);
5011 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5012 return WERR_INVALID_PRINTER_NAME;
5014 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5015 return WERR_UNKNOWN_PRINTER_DRIVER;
5017 fill_printer_driver_info_2(info, driver, servername);
5019 free_a_printer(&printer,2);
5024 /********************************************************************
5025 * copy a strings array and convert to UNICODE
5027 * convert an array of ascii string to a UNICODE string
5028 ********************************************************************/
5030 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5038 DEBUG(6,("init_unistr_array\n"));
5049 v = ""; /* hack to handle null lists */
5052 /* hack to allow this to be used in places other than when generating
5053 the list of dependent files */
5056 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5060 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5062 /* add one extra unit16 for the second terminating NULL */
5064 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5065 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5073 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5078 /* special case for ""; we need to add both NULL's here */
5080 (*uni_array)[j++]=0x0000;
5081 (*uni_array)[j]=0x0000;
5084 DEBUGADD(6,("last one:done\n"));
5086 /* return size of array in uint16's */
5091 /********************************************************************
5092 * construct_printer_info_3
5093 * fill a printer_info_3 struct
5094 ********************************************************************/
5096 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5102 info->version=driver.info_3->cversion;
5104 init_unistr( &info->name, driver.info_3->name );
5105 init_unistr( &info->architecture, driver.info_3->environment );
5107 if (strlen(driver.info_3->driverpath)) {
5108 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5109 init_unistr( &info->driverpath, temp );
5111 init_unistr( &info->driverpath, "" );
5113 if (strlen(driver.info_3->datafile)) {
5114 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5115 init_unistr( &info->datafile, temp );
5117 init_unistr( &info->datafile, "" );
5119 if (strlen(driver.info_3->configfile)) {
5120 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5121 init_unistr( &info->configfile, temp );
5123 init_unistr( &info->configfile, "" );
5125 if (strlen(driver.info_3->helpfile)) {
5126 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5127 init_unistr( &info->helpfile, temp );
5129 init_unistr( &info->helpfile, "" );
5131 init_unistr( &info->monitorname, driver.info_3->monitorname );
5132 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5134 info->dependentfiles=NULL;
5135 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5138 /********************************************************************
5139 * construct_printer_info_3
5140 * fill a printer_info_3 struct
5141 ********************************************************************/
5143 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5145 NT_PRINTER_INFO_LEVEL *printer = NULL;
5146 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5148 ZERO_STRUCT(driver);
5150 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5151 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5152 if (!W_ERROR_IS_OK(status))
5153 return WERR_INVALID_PRINTER_NAME;
5155 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5156 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5161 * I put this code in during testing. Helpful when commenting out the
5162 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5163 * as win2k always queries the driver using an infor level of 6.
5164 * I've left it in (but ifdef'd out) because I'll probably
5165 * use it in experimentation again in the future. --jerry 22/01/2002
5168 if (!W_ERROR_IS_OK(status)) {
5170 * Is this a W2k client ?
5173 /* Yes - try again with a WinNT driver. */
5175 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5176 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5180 if (!W_ERROR_IS_OK(status)) {
5181 free_a_printer(&printer,2);
5182 return WERR_UNKNOWN_PRINTER_DRIVER;
5190 fill_printer_driver_info_3(info, driver, servername);
5192 free_a_printer(&printer,2);
5197 /********************************************************************
5198 * construct_printer_info_6
5199 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5200 ********************************************************************/
5202 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5208 memset(&nullstr, '\0', sizeof(fstring));
5210 info->version=driver.info_3->cversion;
5212 init_unistr( &info->name, driver.info_3->name );
5213 init_unistr( &info->architecture, driver.info_3->environment );
5215 if (strlen(driver.info_3->driverpath)) {
5216 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5217 init_unistr( &info->driverpath, temp );
5219 init_unistr( &info->driverpath, "" );
5221 if (strlen(driver.info_3->datafile)) {
5222 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5223 init_unistr( &info->datafile, temp );
5225 init_unistr( &info->datafile, "" );
5227 if (strlen(driver.info_3->configfile)) {
5228 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5229 init_unistr( &info->configfile, temp );
5231 init_unistr( &info->configfile, "" );
5233 if (strlen(driver.info_3->helpfile)) {
5234 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5235 init_unistr( &info->helpfile, temp );
5237 init_unistr( &info->helpfile, "" );
5239 init_unistr( &info->monitorname, driver.info_3->monitorname );
5240 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5242 info->dependentfiles = NULL;
5243 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5245 info->previousdrivernames=NULL;
5246 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5248 info->driver_date.low=0;
5249 info->driver_date.high=0;
5252 info->driver_version_low=0;
5253 info->driver_version_high=0;
5255 init_unistr( &info->mfgname, "");
5256 init_unistr( &info->oem_url, "");
5257 init_unistr( &info->hardware_id, "");
5258 init_unistr( &info->provider, "");
5261 /********************************************************************
5262 * construct_printer_info_6
5263 * fill a printer_info_6 struct
5264 ********************************************************************/
5266 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5267 fstring servername, fstring architecture, uint32 version)
5269 NT_PRINTER_INFO_LEVEL *printer = NULL;
5270 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5273 ZERO_STRUCT(driver);
5275 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5277 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5279 if (!W_ERROR_IS_OK(status))
5280 return WERR_INVALID_PRINTER_NAME;
5282 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5284 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5286 if (!W_ERROR_IS_OK(status))
5289 * Is this a W2k client ?
5293 free_a_printer(&printer,2);
5294 return WERR_UNKNOWN_PRINTER_DRIVER;
5297 /* Yes - try again with a WinNT driver. */
5299 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5300 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5301 if (!W_ERROR_IS_OK(status)) {
5302 free_a_printer(&printer,2);
5303 return WERR_UNKNOWN_PRINTER_DRIVER;
5307 fill_printer_driver_info_6(info, driver, servername);
5309 free_a_printer(&printer,2);
5310 free_a_printer_driver(driver, 3);
5315 /****************************************************************************
5316 ****************************************************************************/
5318 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5320 SAFE_FREE(info->dependentfiles);
5323 /****************************************************************************
5324 ****************************************************************************/
5326 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5328 SAFE_FREE(info->dependentfiles);
5332 /****************************************************************************
5333 ****************************************************************************/
5335 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5337 DRIVER_INFO_1 *info=NULL;
5340 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5343 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5344 if (!W_ERROR_IS_OK(status)) {
5349 /* check the required size. */
5350 *needed += spoolss_size_printer_driver_info_1(info);
5352 if (!alloc_buffer_size(buffer, *needed)) {
5354 return WERR_INSUFFICIENT_BUFFER;
5357 /* fill the buffer with the structures */
5358 smb_io_printer_driver_info_1("", buffer, info, 0);
5363 if (*needed > offered)
5364 return WERR_INSUFFICIENT_BUFFER;
5369 /****************************************************************************
5370 ****************************************************************************/
5372 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5374 DRIVER_INFO_2 *info=NULL;
5377 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5380 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5381 if (!W_ERROR_IS_OK(status)) {
5386 /* check the required size. */
5387 *needed += spoolss_size_printer_driver_info_2(info);
5389 if (!alloc_buffer_size(buffer, *needed)) {
5391 return WERR_INSUFFICIENT_BUFFER;
5394 /* fill the buffer with the structures */
5395 smb_io_printer_driver_info_2("", buffer, info, 0);
5400 if (*needed > offered)
5401 return WERR_INSUFFICIENT_BUFFER;
5406 /****************************************************************************
5407 ****************************************************************************/
5409 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5416 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5417 if (!W_ERROR_IS_OK(status)) {
5421 /* check the required size. */
5422 *needed += spoolss_size_printer_driver_info_3(&info);
5424 if (!alloc_buffer_size(buffer, *needed)) {
5425 free_printer_driver_info_3(&info);
5426 return WERR_INSUFFICIENT_BUFFER;
5429 /* fill the buffer with the structures */
5430 smb_io_printer_driver_info_3("", buffer, &info, 0);
5432 free_printer_driver_info_3(&info);
5434 if (*needed > offered)
5435 return WERR_INSUFFICIENT_BUFFER;
5440 /****************************************************************************
5441 ****************************************************************************/
5443 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5450 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5451 if (!W_ERROR_IS_OK(status)) {
5455 /* check the required size. */
5456 *needed += spoolss_size_printer_driver_info_6(&info);
5458 if (!alloc_buffer_size(buffer, *needed)) {
5459 free_printer_driver_info_6(&info);
5460 return WERR_INSUFFICIENT_BUFFER;
5463 /* fill the buffer with the structures */
5464 smb_io_printer_driver_info_6("", buffer, &info, 0);
5466 free_printer_driver_info_6(&info);
5468 if (*needed > offered)
5469 return WERR_INSUFFICIENT_BUFFER;
5474 /****************************************************************************
5475 ****************************************************************************/
5477 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5479 POLICY_HND *handle = &q_u->handle;
5480 UNISTR2 *uni_arch = &q_u->architecture;
5481 uint32 level = q_u->level;
5482 uint32 clientmajorversion = q_u->clientmajorversion;
5483 NEW_BUFFER *buffer = NULL;
5484 uint32 offered = q_u->offered;
5485 uint32 *needed = &r_u->needed;
5486 uint32 *servermajorversion = &r_u->servermajorversion;
5487 uint32 *serverminorversion = &r_u->serverminorversion;
5490 fstring architecture;
5493 /* that's an [in out] buffer */
5494 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5495 buffer = r_u->buffer;
5497 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5500 *servermajorversion = 0;
5501 *serverminorversion = 0;
5503 fstrcpy(servername, get_called_name());
5504 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5506 if (!get_printer_snum(p, handle, &snum))
5511 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5513 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5515 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5517 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5520 return WERR_UNKNOWN_LEVEL;
5523 /****************************************************************************
5524 ****************************************************************************/
5526 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5528 POLICY_HND *handle = &q_u->handle;
5530 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5533 DEBUG(3,("Error in startpageprinter printer handle\n"));
5537 Printer->page_started=True;
5541 /****************************************************************************
5542 ****************************************************************************/
5544 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5546 POLICY_HND *handle = &q_u->handle;
5549 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5552 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5556 if (!get_printer_snum(p, handle, &snum))
5559 Printer->page_started=False;
5560 print_job_endpage(snum, Printer->jobid);
5565 /********************************************************************
5566 * api_spoolss_getprinter
5567 * called from the spoolss dispatcher
5569 ********************************************************************/
5571 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5573 POLICY_HND *handle = &q_u->handle;
5574 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5575 uint32 *jobid = &r_u->jobid;
5577 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5581 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5582 struct current_user user;
5585 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5589 get_current_user(&user, p);
5592 * a nice thing with NT is it doesn't listen to what you tell it.
5593 * when asked to send _only_ RAW datas, it tries to send datas
5596 * So I add checks like in NT Server ...
5599 if (info_1->p_datatype != 0) {
5600 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5601 if (strcmp(datatype, "RAW") != 0) {
5603 return WERR_INVALID_DATATYPE;
5607 /* get the share number of the printer */
5608 if (!get_printer_snum(p, handle, &snum)) {
5612 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5614 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5616 /* An error occured in print_job_start() so return an appropriate
5619 if (Printer->jobid == -1) {
5620 return map_werror_from_unix(errno);
5623 Printer->document_started=True;
5624 (*jobid) = Printer->jobid;
5629 /********************************************************************
5630 * api_spoolss_getprinter
5631 * called from the spoolss dispatcher
5633 ********************************************************************/
5635 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5637 POLICY_HND *handle = &q_u->handle;
5639 return _spoolss_enddocprinter_internal(p, handle);
5642 /****************************************************************************
5643 ****************************************************************************/
5645 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5647 POLICY_HND *handle = &q_u->handle;
5648 uint32 buffer_size = q_u->buffer_size;
5649 uint8 *buffer = q_u->buffer;
5650 uint32 *buffer_written = &q_u->buffer_size2;
5652 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5655 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5656 r_u->buffer_written = q_u->buffer_size2;
5660 if (!get_printer_snum(p, handle, &snum))
5663 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5664 if (*buffer_written == -1) {
5665 r_u->buffer_written = 0;
5666 if (errno == ENOSPC)
5667 return WERR_NO_SPOOL_SPACE;
5669 return WERR_ACCESS_DENIED;
5672 r_u->buffer_written = q_u->buffer_size2;
5677 /********************************************************************
5678 * api_spoolss_getprinter
5679 * called from the spoolss dispatcher
5681 ********************************************************************/
5683 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5686 struct current_user user;
5688 WERROR errcode = WERR_BADFUNC;
5689 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5691 get_current_user(&user, p);
5694 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5698 if (!get_printer_snum(p, handle, &snum))
5702 case PRINTER_CONTROL_PAUSE:
5703 if (print_queue_pause(&user, snum, &errcode)) {
5707 case PRINTER_CONTROL_RESUME:
5708 case PRINTER_CONTROL_UNPAUSE:
5709 if (print_queue_resume(&user, snum, &errcode)) {
5713 case PRINTER_CONTROL_PURGE:
5714 if (print_queue_purge(&user, snum, &errcode)) {
5719 return WERR_UNKNOWN_LEVEL;
5725 /********************************************************************
5726 * api_spoolss_abortprinter
5727 * From MSDN: "Deletes printer's spool file if printer is configured
5729 ********************************************************************/
5731 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5733 POLICY_HND *handle = &q_u->handle;
5734 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5736 struct current_user user;
5737 WERROR errcode = WERR_OK;
5740 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5744 if (!get_printer_snum(p, handle, &snum))
5747 get_current_user( &user, p );
5749 print_job_delete( &user, snum, Printer->jobid, &errcode );
5754 /********************************************************************
5755 * called by spoolss_api_setprinter
5756 * when updating a printer description
5757 ********************************************************************/
5759 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5760 const SPOOL_PRINTER_INFO_LEVEL *info,
5761 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5763 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5764 struct current_user user;
5768 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5770 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5771 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5772 OUR_HANDLE(handle)));
5774 result = WERR_BADFID;
5778 /* NT seems to like setting the security descriptor even though
5779 nothing may have actually changed. This causes annoying
5780 dialog boxes when the user doesn't have permission to change
5781 the security descriptor. */
5783 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5785 if (DEBUGLEVEL >= 10) {
5789 the_acl = old_secdesc_ctr->sec->dacl;
5790 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5791 PRINTERNAME(snum), the_acl->num_aces));
5793 for (i = 0; i < the_acl->num_aces; i++) {
5796 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5798 DEBUG(10, ("%s 0x%08x\n", sid_str,
5799 the_acl->ace[i].info.mask));
5802 the_acl = secdesc_ctr->sec->dacl;
5805 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5806 PRINTERNAME(snum), the_acl->num_aces));
5808 for (i = 0; i < the_acl->num_aces; i++) {
5811 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5813 DEBUG(10, ("%s 0x%08x\n", sid_str,
5814 the_acl->ace[i].info.mask));
5817 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5821 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5823 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5828 /* Work out which user is performing the operation */
5830 get_current_user(&user, p);
5832 /* Check the user has permissions to change the security
5833 descriptor. By experimentation with two NT machines, the user
5834 requires Full Access to the printer to change security
5837 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5838 result = WERR_ACCESS_DENIED;
5842 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5849 /********************************************************************
5850 Do Samba sanity checks on a printer info struct.
5851 this has changed purpose: it now "canonicalises" printer
5852 info from a client rather than just checking it is correct
5853 ********************************************************************/
5855 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5857 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5858 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5860 /* we force some elements to "correct" values */
5861 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5862 fstrcpy(info->sharename, lp_servicename(snum));
5863 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5864 get_called_name(), info->sharename);
5865 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5871 /****************************************************************************
5872 ****************************************************************************/
5874 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5876 extern userdom_struct current_user_info;
5877 char *cmd = lp_addprinter_cmd();
5883 fstring remote_machine = "%m";
5885 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5887 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5888 cmd, printer->info_2->printername, printer->info_2->sharename,
5889 printer->info_2->portname, printer->info_2->drivername,
5890 printer->info_2->location, printer->info_2->comment, remote_machine);
5892 DEBUG(10,("Running [%s]\n", command));
5893 ret = smbrun(command, &fd);
5894 DEBUGADD(10,("returned [%d]\n", ret));
5903 /* Get lines and convert them back to dos-codepage */
5904 qlines = fd_lines_load(fd, &numlines);
5905 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5909 /* Set the portname to what the script says the portname should be. */
5910 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5911 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5913 /* Send SIGHUP to process group... is there a better way? */
5916 /* reload our services immediately */
5917 reload_services( False );
5920 file_lines_free(qlines);
5924 /********************************************************************
5925 * Called by spoolss_api_setprinter
5926 * when updating a printer description.
5927 ********************************************************************/
5929 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5930 const SPOOL_PRINTER_INFO_LEVEL *info,
5931 DEVICEMODE *devmode)
5934 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5935 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5940 DEBUG(8,("update_printer\n"));
5945 result = WERR_BADFID;
5949 if (!get_printer_snum(p, handle, &snum)) {
5950 result = WERR_BADFID;
5954 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5955 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5956 result = WERR_BADFID;
5960 DEBUGADD(8,("Converting info_2 struct\n"));
5963 * convert_printer_info converts the incoming
5964 * info from the client and overwrites the info
5965 * just read from the tdb in the pointer 'printer'.
5968 if (!convert_printer_info(info, printer, level)) {
5969 result = WERR_NOMEM;
5974 /* we have a valid devmode
5975 convert it and link it*/
5977 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5978 if (!convert_devicemode(printer->info_2->printername, devmode,
5979 &printer->info_2->devmode)) {
5980 result = WERR_NOMEM;
5985 /* Do sanity check on the requested changes for Samba */
5987 if (!check_printer_ok(printer->info_2, snum)) {
5988 result = WERR_INVALID_PARAM;
5992 /* FIXME!!! If the driver has changed we really should verify that
5993 it is installed before doing much else --jerry */
5995 /* Check calling user has permission to update printer description */
5997 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5998 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5999 result = WERR_ACCESS_DENIED;
6003 /* Call addprinter hook */
6004 /* Check changes to see if this is really needed */
6006 if ( *lp_addprinter_cmd()
6007 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6008 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6009 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6010 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6012 if ( !add_printer_hook(printer) ) {
6013 result = WERR_ACCESS_DENIED;
6018 * make sure we actually reload the services after
6019 * this as smb.conf could have a new section in it
6020 * .... shouldn't .... but could
6022 reload_services(False);
6026 * When a *new* driver is bound to a printer, the drivername is used to
6027 * lookup previously saved driver initialization info, which is then
6028 * bound to the printer, simulating what happens in the Windows arch.
6030 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6032 if (!set_driver_init(printer, 2))
6034 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6035 printer->info_2->drivername));
6038 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6039 printer->info_2->drivername));
6041 notify_printer_driver(snum, printer->info_2->drivername);
6045 * flag which changes actually occured. This is a small subset of
6046 * all the possible changes. We also have to update things in the
6050 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6051 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6052 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6053 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6055 notify_printer_comment(snum, printer->info_2->comment);
6058 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6059 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6060 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6061 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6062 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6063 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6065 notify_printer_sharename(snum, printer->info_2->sharename);
6068 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6069 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6070 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6071 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6073 notify_printer_port(snum, printer->info_2->portname);
6076 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6077 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6078 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6079 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6081 notify_printer_location(snum, printer->info_2->location);
6084 /* here we need to update some more DsSpooler keys */
6085 /* uNCName, serverName, shortServerName */
6087 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6088 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6089 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6090 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6091 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6093 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6094 global_myname(), printer->info_2->sharename );
6095 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6096 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6097 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6099 /* Update printer info */
6100 result = mod_a_printer(*printer, 2);
6103 free_a_printer(&printer, 2);
6104 free_a_printer(&old_printer, 2);
6110 /****************************************************************************
6111 ****************************************************************************/
6112 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6113 const SPOOL_PRINTER_INFO_LEVEL *info)
6116 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6118 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6120 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6125 if (!get_printer_snum(p, handle, &snum))
6128 nt_printer_publish(Printer, snum, info7->action);
6132 return WERR_UNKNOWN_LEVEL;
6135 /****************************************************************************
6136 ****************************************************************************/
6138 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6140 POLICY_HND *handle = &q_u->handle;
6141 uint32 level = q_u->level;
6142 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6143 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6144 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6145 uint32 command = q_u->command;
6147 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6150 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6154 /* check the level */
6157 return control_printer(handle, command, p);
6159 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6161 return update_printer_sec(handle, level, info, p,
6164 return publish_or_unpublish_printer(p, handle, info);
6166 return WERR_UNKNOWN_LEVEL;
6170 /****************************************************************************
6171 ****************************************************************************/
6173 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6175 POLICY_HND *handle = &q_u->handle;
6176 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6179 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6183 if (Printer->notify.client_connected==True) {
6186 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6188 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6189 !get_printer_snum(p, handle, &snum) )
6192 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6195 Printer->notify.flags=0;
6196 Printer->notify.options=0;
6197 Printer->notify.localmachine[0]='\0';
6198 Printer->notify.printerlocal=0;
6199 if (Printer->notify.option)
6200 free_spool_notify_option(&Printer->notify.option);
6201 Printer->notify.client_connected=False;
6206 /****************************************************************************
6207 ****************************************************************************/
6209 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6211 /* that's an [in out] buffer (despite appearences to the contrary) */
6212 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6215 return WERR_INVALID_PARAM; /* this is what a NT server
6216 returns for AddJob. AddJob
6217 must fail on non-local
6221 /****************************************************************************
6222 ****************************************************************************/
6224 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6225 int position, int snum)
6231 t=gmtime(&queue->time);
6232 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6234 job_info->jobid=queue->job;
6235 init_unistr(&job_info->printername, lp_servicename(snum));
6236 init_unistr(&job_info->machinename, temp_name);
6237 init_unistr(&job_info->username, queue->fs_user);
6238 init_unistr(&job_info->document, queue->fs_file);
6239 init_unistr(&job_info->datatype, "RAW");
6240 init_unistr(&job_info->text_status, "");
6241 job_info->status=nt_printj_status(queue->status);
6242 job_info->priority=queue->priority;
6243 job_info->position=position;
6244 job_info->totalpages=queue->page_count;
6245 job_info->pagesprinted=0;
6247 make_systemtime(&job_info->submitted, t);
6250 /****************************************************************************
6251 ****************************************************************************/
6253 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6254 int position, int snum,
6255 NT_PRINTER_INFO_LEVEL *ntprinter,
6256 DEVICEMODE *devmode)
6261 t=gmtime(&queue->time);
6262 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6264 job_info->jobid=queue->job;
6266 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6268 init_unistr(&job_info->machinename, temp_name);
6269 init_unistr(&job_info->username, queue->fs_user);
6270 init_unistr(&job_info->document, queue->fs_file);
6271 init_unistr(&job_info->notifyname, queue->fs_user);
6272 init_unistr(&job_info->datatype, "RAW");
6273 init_unistr(&job_info->printprocessor, "winprint");
6274 init_unistr(&job_info->parameters, "");
6275 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6276 init_unistr(&job_info->text_status, "");
6278 /* and here the security descriptor */
6280 job_info->status=nt_printj_status(queue->status);
6281 job_info->priority=queue->priority;
6282 job_info->position=position;
6283 job_info->starttime=0;
6284 job_info->untiltime=0;
6285 job_info->totalpages=queue->page_count;
6286 job_info->size=queue->size;
6287 make_systemtime(&(job_info->submitted), t);
6288 job_info->timeelapsed=0;
6289 job_info->pagesprinted=0;
6291 job_info->devmode = devmode;
6296 /****************************************************************************
6297 Enumjobs at level 1.
6298 ****************************************************************************/
6300 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6301 NEW_BUFFER *buffer, uint32 offered,
6302 uint32 *needed, uint32 *returned)
6307 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6314 for (i=0; i<*returned; i++)
6315 fill_job_info_1(&info[i], &queue[i], i, snum);
6319 /* check the required size. */
6320 for (i=0; i<*returned; i++)
6321 (*needed) += spoolss_size_job_info_1(&info[i]);
6323 if (!alloc_buffer_size(buffer, *needed)) {
6325 return WERR_INSUFFICIENT_BUFFER;
6328 /* fill the buffer with the structures */
6329 for (i=0; i<*returned; i++)
6330 smb_io_job_info_1("", buffer, &info[i], 0);
6335 if (*needed > offered) {
6337 return WERR_INSUFFICIENT_BUFFER;
6343 /****************************************************************************
6344 Enumjobs at level 2.
6345 ****************************************************************************/
6347 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6348 NEW_BUFFER *buffer, uint32 offered,
6349 uint32 *needed, uint32 *returned)
6351 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6352 JOB_INFO_2 *info = NULL;
6355 DEVICEMODE *devmode = NULL;
6357 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6360 result = WERR_NOMEM;
6364 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6365 if (!W_ERROR_IS_OK(result)) {
6370 /* this should not be a failure condition if the devmode is NULL */
6372 devmode = construct_dev_mode(snum);
6374 for (i=0; i<*returned; i++)
6375 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6378 free_a_printer(&ntprinter, 2);
6381 /* check the required size. */
6382 for (i=0; i<*returned; i++)
6383 (*needed) += spoolss_size_job_info_2(&info[i]);
6385 if (*needed > offered) {
6387 result = WERR_INSUFFICIENT_BUFFER;
6391 if (!alloc_buffer_size(buffer, *needed)) {
6393 result = WERR_INSUFFICIENT_BUFFER;
6397 /* fill the buffer with the structures */
6398 for (i=0; i<*returned; i++)
6399 smb_io_job_info_2("", buffer, &info[i], 0);
6404 free_a_printer(&ntprinter, 2);
6405 free_devmode(devmode);
6413 /****************************************************************************
6415 ****************************************************************************/
6417 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6419 POLICY_HND *handle = &q_u->handle;
6420 uint32 level = q_u->level;
6421 NEW_BUFFER *buffer = NULL;
6422 uint32 offered = q_u->offered;
6423 uint32 *needed = &r_u->needed;
6424 uint32 *returned = &r_u->returned;
6428 print_status_struct prt_status;
6429 print_queue_struct *queue=NULL;
6431 /* that's an [in out] buffer */
6432 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6433 buffer = r_u->buffer;
6435 DEBUG(4,("_spoolss_enumjobs\n"));
6440 if (!get_printer_snum(p, handle, &snum))
6443 *returned = print_queue_status(snum, &queue, &prt_status);
6444 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6446 if (*returned == 0) {
6453 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6456 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6461 return WERR_UNKNOWN_LEVEL;
6465 /****************************************************************************
6466 ****************************************************************************/
6468 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6473 /****************************************************************************
6474 ****************************************************************************/
6476 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6478 POLICY_HND *handle = &q_u->handle;
6479 uint32 jobid = q_u->jobid;
6480 uint32 command = q_u->command;
6482 struct current_user user;
6484 WERROR errcode = WERR_BADFUNC;
6486 if (!get_printer_snum(p, handle, &snum)) {
6490 if (!print_job_exists(snum, jobid)) {
6491 return WERR_INVALID_PRINTER_NAME;
6494 get_current_user(&user, p);
6497 case JOB_CONTROL_CANCEL:
6498 case JOB_CONTROL_DELETE:
6499 if (print_job_delete(&user, snum, jobid, &errcode)) {
6503 case JOB_CONTROL_PAUSE:
6504 if (print_job_pause(&user, snum, jobid, &errcode)) {
6508 case JOB_CONTROL_RESTART:
6509 case JOB_CONTROL_RESUME:
6510 if (print_job_resume(&user, snum, jobid, &errcode)) {
6515 return WERR_UNKNOWN_LEVEL;
6521 /****************************************************************************
6522 Enumerates all printer drivers at level 1.
6523 ****************************************************************************/
6525 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6530 fstring *list = NULL;
6532 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6533 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6537 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6539 ndrivers=get_ntdrivers(&list, architecture, version);
6540 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6546 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6547 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6548 SAFE_FREE(driver_info_1);
6552 else driver_info_1 = tdi1;
6555 for (i=0; i<ndrivers; i++) {
6557 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6558 ZERO_STRUCT(driver);
6559 status = get_a_printer_driver(&driver, 3, list[i],
6560 architecture, version);
6561 if (!W_ERROR_IS_OK(status)) {
6565 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6566 free_a_printer_driver(driver, 3);
6569 *returned+=ndrivers;
6573 /* check the required size. */
6574 for (i=0; i<*returned; i++) {
6575 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6576 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6579 if (!alloc_buffer_size(buffer, *needed)) {
6580 SAFE_FREE(driver_info_1);
6581 return WERR_INSUFFICIENT_BUFFER;
6584 /* fill the buffer with the driver structures */
6585 for (i=0; i<*returned; i++) {
6586 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6587 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6590 SAFE_FREE(driver_info_1);
6592 if (*needed > offered) {
6594 return WERR_INSUFFICIENT_BUFFER;
6600 /****************************************************************************
6601 Enumerates all printer drivers at level 2.
6602 ****************************************************************************/
6604 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6609 fstring *list = NULL;
6611 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6612 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6616 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6618 ndrivers=get_ntdrivers(&list, architecture, version);
6619 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6625 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6626 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6627 SAFE_FREE(driver_info_2);
6631 else driver_info_2 = tdi2;
6634 for (i=0; i<ndrivers; i++) {
6637 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6638 ZERO_STRUCT(driver);
6639 status = get_a_printer_driver(&driver, 3, list[i],
6640 architecture, version);
6641 if (!W_ERROR_IS_OK(status)) {
6645 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6646 free_a_printer_driver(driver, 3);
6649 *returned+=ndrivers;
6653 /* check the required size. */
6654 for (i=0; i<*returned; i++) {
6655 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6656 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6659 if (!alloc_buffer_size(buffer, *needed)) {
6660 SAFE_FREE(driver_info_2);
6661 return WERR_INSUFFICIENT_BUFFER;
6664 /* fill the buffer with the form structures */
6665 for (i=0; i<*returned; i++) {
6666 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6667 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6670 SAFE_FREE(driver_info_2);
6672 if (*needed > offered) {
6674 return WERR_INSUFFICIENT_BUFFER;
6680 /****************************************************************************
6681 Enumerates all printer drivers at level 3.
6682 ****************************************************************************/
6684 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6689 fstring *list = NULL;
6691 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6692 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6696 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6698 ndrivers=get_ntdrivers(&list, architecture, version);
6699 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6705 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6706 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6707 SAFE_FREE(driver_info_3);
6711 else driver_info_3 = tdi3;
6714 for (i=0; i<ndrivers; i++) {
6717 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6718 ZERO_STRUCT(driver);
6719 status = get_a_printer_driver(&driver, 3, list[i],
6720 architecture, version);
6721 if (!W_ERROR_IS_OK(status)) {
6725 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6726 free_a_printer_driver(driver, 3);
6729 *returned+=ndrivers;
6733 /* check the required size. */
6734 for (i=0; i<*returned; i++) {
6735 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6736 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6739 if (!alloc_buffer_size(buffer, *needed)) {
6740 SAFE_FREE(driver_info_3);
6741 return WERR_INSUFFICIENT_BUFFER;
6744 /* fill the buffer with the driver structures */
6745 for (i=0; i<*returned; i++) {
6746 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6747 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6750 for (i=0; i<*returned; i++)
6751 SAFE_FREE(driver_info_3[i].dependentfiles);
6753 SAFE_FREE(driver_info_3);
6755 if (*needed > offered) {
6757 return WERR_INSUFFICIENT_BUFFER;
6763 /****************************************************************************
6764 Enumerates all printer drivers.
6765 ****************************************************************************/
6767 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6769 UNISTR2 *environment = &q_u->environment;
6770 uint32 level = q_u->level;
6771 NEW_BUFFER *buffer = NULL;
6772 uint32 offered = q_u->offered;
6773 uint32 *needed = &r_u->needed;
6774 uint32 *returned = &r_u->returned;
6776 fstring *list = NULL;
6778 fstring architecture;
6780 /* that's an [in out] buffer */
6781 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6782 buffer = r_u->buffer;
6784 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6785 fstrcpy(servername, get_called_name());
6789 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6793 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6795 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6797 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6801 return WERR_UNKNOWN_LEVEL;
6805 /****************************************************************************
6806 ****************************************************************************/
6808 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6810 form->flag=list->flag;
6811 init_unistr(&form->name, list->name);
6812 form->width=list->width;
6813 form->length=list->length;
6814 form->left=list->left;
6815 form->top=list->top;
6816 form->right=list->right;
6817 form->bottom=list->bottom;
6820 /****************************************************************************
6821 ****************************************************************************/
6823 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6825 uint32 level = q_u->level;
6826 NEW_BUFFER *buffer = NULL;
6827 uint32 offered = q_u->offered;
6828 uint32 *needed = &r_u->needed;
6829 uint32 *numofforms = &r_u->numofforms;
6830 uint32 numbuiltinforms;
6832 nt_forms_struct *list=NULL;
6833 nt_forms_struct *builtinlist=NULL;
6838 /* that's an [in out] buffer */
6839 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6840 buffer = r_u->buffer;
6842 DEBUG(4,("_spoolss_enumforms\n"));
6843 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6844 DEBUGADD(5,("Info level [%d]\n", level));
6846 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6847 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6848 *numofforms = get_ntforms(&list);
6849 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6850 *numofforms += numbuiltinforms;
6852 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6856 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6861 /* construct the list of form structures */
6862 for (i=0; i<numbuiltinforms; i++) {
6863 DEBUGADD(6,("Filling form number [%d]\n",i));
6864 fill_form_1(&forms_1[i], &builtinlist[i]);
6867 SAFE_FREE(builtinlist);
6869 for (; i<*numofforms; i++) {
6870 DEBUGADD(6,("Filling form number [%d]\n",i));
6871 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6876 /* check the required size. */
6877 for (i=0; i<numbuiltinforms; i++) {
6878 DEBUGADD(6,("adding form [%d]'s size\n",i));
6879 buffer_size += spoolss_size_form_1(&forms_1[i]);
6881 for (; i<*numofforms; i++) {
6882 DEBUGADD(6,("adding form [%d]'s size\n",i));
6883 buffer_size += spoolss_size_form_1(&forms_1[i]);
6886 *needed=buffer_size;
6888 if (!alloc_buffer_size(buffer, buffer_size)){
6890 return WERR_INSUFFICIENT_BUFFER;
6893 /* fill the buffer with the form structures */
6894 for (i=0; i<numbuiltinforms; i++) {
6895 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6896 smb_io_form_1("", buffer, &forms_1[i], 0);
6898 for (; i<*numofforms; i++) {
6899 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6900 smb_io_form_1("", buffer, &forms_1[i], 0);
6905 if (*needed > offered) {
6907 return WERR_INSUFFICIENT_BUFFER;
6914 SAFE_FREE(builtinlist);
6915 return WERR_UNKNOWN_LEVEL;
6920 /****************************************************************************
6921 ****************************************************************************/
6923 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6925 uint32 level = q_u->level;
6926 UNISTR2 *uni_formname = &q_u->formname;
6927 NEW_BUFFER *buffer = NULL;
6928 uint32 offered = q_u->offered;
6929 uint32 *needed = &r_u->needed;
6931 nt_forms_struct *list=NULL;
6932 nt_forms_struct builtin_form;
6937 int numofforms=0, i=0;
6939 /* that's an [in out] buffer */
6940 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6941 buffer = r_u->buffer;
6943 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6945 DEBUG(4,("_spoolss_getform\n"));
6946 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6947 DEBUGADD(5,("Info level [%d]\n", level));
6949 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6950 if (!foundBuiltin) {
6951 numofforms = get_ntforms(&list);
6952 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6954 if (numofforms == 0)
6961 fill_form_1(&form_1, &builtin_form);
6964 /* Check if the requested name is in the list of form structures */
6965 for (i=0; i<numofforms; i++) {
6967 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6969 if (strequal(form_name, list[i].name)) {
6970 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6971 fill_form_1(&form_1, &list[i]);
6977 if (i == numofforms) {
6981 /* check the required size. */
6983 *needed=spoolss_size_form_1(&form_1);
6985 if (!alloc_buffer_size(buffer, buffer_size)){
6986 return WERR_INSUFFICIENT_BUFFER;
6989 if (*needed > offered) {
6990 return WERR_INSUFFICIENT_BUFFER;
6993 /* fill the buffer with the form structures */
6994 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6995 smb_io_form_1("", buffer, &form_1, 0);
7001 return WERR_UNKNOWN_LEVEL;
7005 /****************************************************************************
7006 ****************************************************************************/
7008 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7010 init_unistr(&port->port_name, name);
7013 /****************************************************************************
7014 ****************************************************************************/
7016 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7018 init_unistr(&port->port_name, name);
7019 init_unistr(&port->monitor_name, "Local Monitor");
7020 init_unistr(&port->description, "Local Port");
7021 port->port_type=PORT_TYPE_WRITE;
7025 /****************************************************************************
7027 ****************************************************************************/
7029 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7031 PORT_INFO_1 *ports=NULL;
7034 if (*lp_enumports_cmd()) {
7035 char *cmd = lp_enumports_cmd();
7042 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7044 DEBUG(10,("Running [%s]\n", command));
7045 ret = smbrun(command, &fd);
7046 DEBUG(10,("Returned [%d]\n", ret));
7050 /* Is this the best error to return here? */
7051 return WERR_ACCESS_DENIED;
7055 qlines = fd_lines_load(fd, &numlines);
7056 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7060 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7061 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7062 dos_errstr(WERR_NOMEM)));
7063 file_lines_free(qlines);
7067 for (i=0; i<numlines; i++) {
7068 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7069 fill_port_1(&ports[i], qlines[i]);
7072 file_lines_free(qlines);
7075 *returned = numlines;
7078 *returned = 1; /* Sole Samba port returned. */
7080 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7083 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7085 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7088 /* check the required size. */
7089 for (i=0; i<*returned; i++) {
7090 DEBUGADD(6,("adding port [%d]'s size\n", i));
7091 *needed += spoolss_size_port_info_1(&ports[i]);
7094 if (!alloc_buffer_size(buffer, *needed)) {
7096 return WERR_INSUFFICIENT_BUFFER;
7099 /* fill the buffer with the ports structures */
7100 for (i=0; i<*returned; i++) {
7101 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7102 smb_io_port_1("", buffer, &ports[i], 0);
7107 if (*needed > offered) {
7109 return WERR_INSUFFICIENT_BUFFER;
7115 /****************************************************************************
7117 ****************************************************************************/
7119 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7121 PORT_INFO_2 *ports=NULL;
7124 if (*lp_enumports_cmd()) {
7125 char *cmd = lp_enumports_cmd();
7134 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7135 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7137 path = lp_lockdir();
7139 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7140 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7143 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7144 ret = smbrun(command, &fd);
7145 DEBUGADD(10,("returned [%d]\n", ret));
7149 /* Is this the best error to return here? */
7150 return WERR_ACCESS_DENIED;
7154 qlines = fd_lines_load(fd, &numlines);
7155 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7159 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7160 file_lines_free(qlines);
7164 for (i=0; i<numlines; i++) {
7165 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7166 fill_port_2(&(ports[i]), qlines[i]);
7169 file_lines_free(qlines);
7172 *returned = numlines;
7178 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7181 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7183 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7186 /* check the required size. */
7187 for (i=0; i<*returned; i++) {
7188 DEBUGADD(6,("adding port [%d]'s size\n", i));
7189 *needed += spoolss_size_port_info_2(&ports[i]);
7192 if (!alloc_buffer_size(buffer, *needed)) {
7194 return WERR_INSUFFICIENT_BUFFER;
7197 /* fill the buffer with the ports structures */
7198 for (i=0; i<*returned; i++) {
7199 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7200 smb_io_port_2("", buffer, &ports[i], 0);
7205 if (*needed > offered) {
7207 return WERR_INSUFFICIENT_BUFFER;
7213 /****************************************************************************
7215 ****************************************************************************/
7217 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7219 uint32 level = q_u->level;
7220 NEW_BUFFER *buffer = NULL;
7221 uint32 offered = q_u->offered;
7222 uint32 *needed = &r_u->needed;
7223 uint32 *returned = &r_u->returned;
7225 /* that's an [in out] buffer */
7226 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7227 buffer = r_u->buffer;
7229 DEBUG(4,("_spoolss_enumports\n"));
7236 return enumports_level_1(buffer, offered, needed, returned);
7238 return enumports_level_2(buffer, offered, needed, returned);
7240 return WERR_UNKNOWN_LEVEL;
7244 /****************************************************************************
7245 ****************************************************************************/
7247 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7248 const SPOOL_PRINTER_INFO_LEVEL *info,
7249 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7250 uint32 user_switch, const SPOOL_USER_CTR *user,
7253 NT_PRINTER_INFO_LEVEL *printer = NULL;
7256 WERROR err = WERR_OK;
7258 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7259 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7263 ZERO_STRUCTP(printer);
7265 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7266 if (!convert_printer_info(info, printer, 2)) {
7267 free_a_printer(&printer, 2);
7271 /* check to see if the printer already exists */
7273 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7274 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7275 printer->info_2->sharename));
7276 free_a_printer(&printer, 2);
7277 return WERR_PRINTER_ALREADY_EXISTS;
7280 /* FIXME!!! smbd should check to see if the driver is installed before
7281 trying to add a printer like this --jerry */
7283 if (*lp_addprinter_cmd() ) {
7284 if ( !add_printer_hook(printer) ) {
7285 free_a_printer(&printer,2);
7286 return WERR_ACCESS_DENIED;
7290 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7291 printer->info_2->sharename);
7294 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7295 free_a_printer(&printer,2);
7296 return WERR_ACCESS_DENIED;
7299 /* you must be a printer admin to add a new printer */
7300 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7301 free_a_printer(&printer,2);
7302 return WERR_ACCESS_DENIED;
7306 * Do sanity check on the requested changes for Samba.
7309 if (!check_printer_ok(printer->info_2, snum)) {
7310 free_a_printer(&printer,2);
7311 return WERR_INVALID_PARAM;
7315 * When a printer is created, the drivername bound to the printer is used
7316 * to lookup previously saved driver initialization info, which is then
7317 * bound to the new printer, simulating what happens in the Windows arch.
7322 set_driver_init(printer, 2);
7326 /* A valid devmode was included, convert and link it
7328 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7330 if (!convert_devicemode(printer->info_2->printername, devmode,
7331 &printer->info_2->devmode))
7335 /* write the ASCII on disk */
7336 err = mod_a_printer(*printer, 2);
7337 if (!W_ERROR_IS_OK(err)) {
7338 free_a_printer(&printer,2);
7342 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7343 /* Handle open failed - remove addition. */
7344 del_a_printer(printer->info_2->sharename);
7345 free_a_printer(&printer,2);
7346 return WERR_ACCESS_DENIED;
7349 update_c_setprinter(False);
7350 free_a_printer(&printer,2);
7355 /****************************************************************************
7356 ****************************************************************************/
7358 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7360 UNISTR2 *uni_srv_name = &q_u->server_name;
7361 uint32 level = q_u->level;
7362 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7363 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7364 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7365 uint32 user_switch = q_u->user_switch;
7366 SPOOL_USER_CTR *user = &q_u->user_ctr;
7367 POLICY_HND *handle = &r_u->handle;
7371 /* we don't handle yet */
7372 /* but I know what to do ... */
7373 return WERR_UNKNOWN_LEVEL;
7375 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7377 user_switch, user, handle);
7379 return WERR_UNKNOWN_LEVEL;
7383 /****************************************************************************
7384 ****************************************************************************/
7386 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7388 uint32 level = q_u->level;
7389 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7390 WERROR err = WERR_OK;
7391 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7392 struct current_user user;
7393 fstring driver_name;
7396 ZERO_STRUCT(driver);
7398 get_current_user(&user, p);
7400 if (!convert_printer_driver_info(info, &driver, level)) {
7405 DEBUG(5,("Cleaning driver's information\n"));
7406 err = clean_up_driver_struct(driver, level, &user);
7407 if (!W_ERROR_IS_OK(err))
7410 DEBUG(5,("Moving driver to final destination\n"));
7411 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7412 if (W_ERROR_IS_OK(err))
7413 err = WERR_ACCESS_DENIED;
7417 if (add_a_printer_driver(driver, level)!=0) {
7418 err = WERR_ACCESS_DENIED;
7422 /* BEGIN_ADMIN_LOG */
7425 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7426 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7427 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7430 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7431 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7432 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7438 * I think this is where he DrvUpgradePrinter() hook would be
7439 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7440 * server. Right now, we just need to send ourselves a message
7441 * to update each printer bound to this driver. --jerry
7444 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7445 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7450 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7451 * decide if the driver init data should be deleted. The rules are:
7452 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7453 * 2) delete init data only if there is no 2k/Xp driver
7454 * 3) always delete init data
7455 * The generalized rule is always use init data from the highest order driver.
7456 * It is necessary to follow the driver install by an initialization step to
7457 * finish off this process.
7460 version = driver.info_3->cversion;
7461 else if (level == 6)
7462 version = driver.info_6->version;
7467 * 9x printer driver - never delete init data
7470 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7475 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7476 * there is no 2k/Xp driver init data for this driver name.
7480 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7482 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7484 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7486 if (!del_driver_init(driver_name))
7487 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7490 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7492 free_a_printer_driver(driver1,3);
7493 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7500 * 2k or Xp printer driver - always delete init data
7503 if (!del_driver_init(driver_name))
7504 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7508 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7514 free_a_printer_driver(driver, level);
7518 /********************************************************************
7519 * spoolss_addprinterdriverex
7520 ********************************************************************/
7522 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7524 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7525 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7528 * we only support the semantics of AddPrinterDriver()
7529 * i.e. only copy files that are newer than existing ones
7532 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7533 return WERR_ACCESS_DENIED;
7535 ZERO_STRUCT(q_u_local);
7536 ZERO_STRUCT(r_u_local);
7538 /* just pass the information off to _spoolss_addprinterdriver() */
7539 q_u_local.server_name_ptr = q_u->server_name_ptr;
7540 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7541 q_u_local.level = q_u->level;
7542 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7544 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7547 /****************************************************************************
7548 ****************************************************************************/
7550 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7552 init_unistr(&info->name, name);
7555 /****************************************************************************
7556 ****************************************************************************/
7558 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7562 const char *short_archi;
7563 DRIVER_DIRECTORY_1 *info=NULL;
7565 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7567 if (!(short_archi = get_short_archi(long_archi)))
7568 return WERR_INVALID_ENVIRONMENT;
7570 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7573 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7575 DEBUG(4,("printer driver directory: [%s]\n", path));
7577 fill_driverdir_1(info, path);
7579 *needed += spoolss_size_driverdir_info_1(info);
7581 if (!alloc_buffer_size(buffer, *needed)) {
7583 return WERR_INSUFFICIENT_BUFFER;
7586 smb_io_driverdir_1("", buffer, info, 0);
7590 if (*needed > offered)
7591 return WERR_INSUFFICIENT_BUFFER;
7596 /****************************************************************************
7597 ****************************************************************************/
7599 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7601 UNISTR2 *name = &q_u->name;
7602 UNISTR2 *uni_environment = &q_u->environment;
7603 uint32 level = q_u->level;
7604 NEW_BUFFER *buffer = NULL;
7605 uint32 offered = q_u->offered;
7606 uint32 *needed = &r_u->needed;
7608 /* that's an [in out] buffer */
7609 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7610 buffer = r_u->buffer;
7612 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7618 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7620 return WERR_UNKNOWN_LEVEL;
7624 /****************************************************************************
7625 ****************************************************************************/
7627 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7629 POLICY_HND *handle = &q_u->handle;
7630 uint32 idx = q_u->index;
7631 uint32 in_value_len = q_u->valuesize;
7632 uint32 in_data_len = q_u->datasize;
7633 uint32 *out_max_value_len = &r_u->valuesize;
7634 uint16 **out_value = &r_u->value;
7635 uint32 *out_value_len = &r_u->realvaluesize;
7636 uint32 *out_type = &r_u->type;
7637 uint32 *out_max_data_len = &r_u->datasize;
7638 uint8 **data_out = &r_u->data;
7639 uint32 *out_data_len = &r_u->realdatasize;
7641 NT_PRINTER_INFO_LEVEL *printer = NULL;
7643 uint32 biggest_valuesize;
7644 uint32 biggest_datasize;
7646 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7649 REGISTRY_VALUE *val = NULL;
7650 NT_PRINTER_DATA *p_data;
7651 int i, key_index, num_values;
7654 ZERO_STRUCT( printer );
7658 *out_max_data_len = 0;
7662 DEBUG(5,("spoolss_enumprinterdata\n"));
7665 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7669 if (!get_printer_snum(p,handle, &snum))
7672 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7673 if (!W_ERROR_IS_OK(result))
7676 p_data = &printer->info_2->data;
7677 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7682 * The NT machine wants to know the biggest size of value and data
7684 * cf: MSDN EnumPrinterData remark section
7687 if ( !in_value_len && !in_data_len && (key_index != -1) )
7689 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7691 biggest_valuesize = 0;
7692 biggest_datasize = 0;
7694 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7696 for ( i=0; i<num_values; i++ )
7698 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7700 name_length = strlen(val->valuename);
7701 if ( strlen(val->valuename) > biggest_valuesize )
7702 biggest_valuesize = name_length;
7704 if ( val->size > biggest_datasize )
7705 biggest_datasize = val->size;
7707 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7711 /* the value is an UNICODE string but real_value_size is the length
7712 in bytes including the trailing 0 */
7714 *out_value_len = 2 * (1+biggest_valuesize);
7715 *out_data_len = biggest_datasize;
7717 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7723 * the value len is wrong in NT sp3
7724 * that's the number of bytes not the number of unicode chars
7727 if ( key_index != -1 )
7728 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7733 /* out_value should default to "" or else NT4 has
7734 problems unmarshalling the response */
7736 *out_max_value_len=(in_value_len/sizeof(uint16));
7738 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7740 result = WERR_NOMEM;
7744 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7746 /* the data is counted in bytes */
7748 *out_max_data_len = in_data_len;
7749 *out_data_len = in_data_len;
7751 /* only allocate when given a non-zero data_len */
7753 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7755 result = WERR_NOMEM;
7759 result = WERR_NO_MORE_ITEMS;
7765 * - counted in bytes in the request
7766 * - counted in UNICODE chars in the max reply
7767 * - counted in bytes in the real size
7769 * take a pause *before* coding not *during* coding
7773 *out_max_value_len=(in_value_len/sizeof(uint16));
7774 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7776 result = WERR_NOMEM;
7780 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7784 *out_type = regval_type( val );
7786 /* data - counted in bytes */
7788 *out_max_data_len = in_data_len;
7789 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7791 result = WERR_NOMEM;
7794 data_len = (size_t)regval_size(val);
7795 memcpy( *data_out, regval_data_p(val), data_len );
7796 *out_data_len = data_len;
7800 free_a_printer(&printer, 2);
7804 /****************************************************************************
7805 ****************************************************************************/
7807 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7809 POLICY_HND *handle = &q_u->handle;
7810 UNISTR2 *value = &q_u->value;
7811 uint32 type = q_u->type;
7812 uint8 *data = q_u->data;
7813 uint32 real_len = q_u->real_len;
7815 NT_PRINTER_INFO_LEVEL *printer = NULL;
7817 WERROR status = WERR_OK;
7818 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7821 DEBUG(5,("spoolss_setprinterdata\n"));
7824 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7828 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7829 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7830 return WERR_INVALID_PARAM;
7833 if (!get_printer_snum(p,handle, &snum))
7837 * Access check : NT returns "access denied" if you make a
7838 * SetPrinterData call without the necessary privildge.
7839 * we were originally returning OK if nothing changed
7840 * which made Win2k issue **a lot** of SetPrinterData
7841 * when connecting to a printer --jerry
7844 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7846 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7847 status = WERR_ACCESS_DENIED;
7851 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7852 if (!W_ERROR_IS_OK(status))
7855 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7858 * When client side code sets a magic printer data key, detect it and save
7859 * the current printer data and the magic key's data (its the DEVMODE) for
7860 * future printer/driver initializations.
7862 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7864 /* Set devmode and printer initialization info */
7865 status = save_driver_init( printer, 2, data, real_len );
7867 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7871 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7872 type, data, real_len );
7873 if ( W_ERROR_IS_OK(status) )
7874 status = mod_a_printer(*printer, 2);
7878 free_a_printer(&printer, 2);
7883 /****************************************************************************
7884 ****************************************************************************/
7886 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7888 POLICY_HND *handle = &q_u->handle;
7889 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7892 DEBUG(5,("_spoolss_resetprinter\n"));
7895 * All we do is to check to see if the handle and queue is valid.
7896 * This call really doesn't mean anything to us because we only
7897 * support RAW printing. --jerry
7901 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7905 if (!get_printer_snum(p,handle, &snum))
7909 /* blindly return success */
7914 /****************************************************************************
7915 ****************************************************************************/
7917 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7919 POLICY_HND *handle = &q_u->handle;
7920 UNISTR2 *value = &q_u->valuename;
7922 NT_PRINTER_INFO_LEVEL *printer = NULL;
7924 WERROR status = WERR_OK;
7925 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7928 DEBUG(5,("spoolss_deleteprinterdata\n"));
7931 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7935 if (!get_printer_snum(p, handle, &snum))
7938 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7939 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7940 return WERR_ACCESS_DENIED;
7943 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7944 if (!W_ERROR_IS_OK(status))
7947 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7949 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7951 if ( W_ERROR_IS_OK(status) )
7952 mod_a_printer( *printer, 2 );
7954 free_a_printer(&printer, 2);
7959 /****************************************************************************
7960 ****************************************************************************/
7962 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7964 POLICY_HND *handle = &q_u->handle;
7965 FORM *form = &q_u->form;
7966 nt_forms_struct tmpForm;
7968 WERROR status = WERR_OK;
7969 NT_PRINTER_INFO_LEVEL *printer = NULL;
7972 nt_forms_struct *list=NULL;
7973 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7975 DEBUG(5,("spoolss_addform\n"));
7978 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7983 /* forms can be added on printer of on the print server handle */
7985 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7987 if (!get_printer_snum(p,handle, &snum))
7990 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7991 if (!W_ERROR_IS_OK(status))
7995 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7996 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7997 status = WERR_ACCESS_DENIED;
8001 /* can't add if builtin */
8003 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8004 status = WERR_ALREADY_EXISTS;
8008 count = get_ntforms(&list);
8010 if(!add_a_form(&list, form, &count)) {
8011 status = WERR_NOMEM;
8015 write_ntforms(&list, count);
8018 * ChangeID must always be set if this is a printer
8021 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8022 status = mod_a_printer(*printer, 2);
8026 free_a_printer(&printer, 2);
8032 /****************************************************************************
8033 ****************************************************************************/
8035 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8037 POLICY_HND *handle = &q_u->handle;
8038 UNISTR2 *form_name = &q_u->name;
8039 nt_forms_struct tmpForm;
8041 nt_forms_struct *list=NULL;
8042 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8044 WERROR status = WERR_OK;
8045 NT_PRINTER_INFO_LEVEL *printer = NULL;
8047 DEBUG(5,("spoolss_deleteform\n"));
8050 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8054 /* forms can be deleted on printer of on the print server handle */
8056 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8058 if (!get_printer_snum(p,handle, &snum))
8061 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8062 if (!W_ERROR_IS_OK(status))
8066 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8067 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8068 status = WERR_ACCESS_DENIED;
8072 /* can't delete if builtin */
8074 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8075 status = WERR_INVALID_PARAM;
8079 count = get_ntforms(&list);
8081 if ( !delete_a_form(&list, form_name, &count, &status ))
8085 * ChangeID must always be set if this is a printer
8088 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8089 status = mod_a_printer(*printer, 2);
8093 free_a_printer(&printer, 2);
8099 /****************************************************************************
8100 ****************************************************************************/
8102 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8104 POLICY_HND *handle = &q_u->handle;
8105 FORM *form = &q_u->form;
8106 nt_forms_struct tmpForm;
8108 WERROR status = WERR_OK;
8109 NT_PRINTER_INFO_LEVEL *printer = NULL;
8112 nt_forms_struct *list=NULL;
8113 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8115 DEBUG(5,("spoolss_setform\n"));
8118 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8122 /* forms can be modified on printer of on the print server handle */
8124 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8126 if (!get_printer_snum(p,handle, &snum))
8129 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8130 if (!W_ERROR_IS_OK(status))
8134 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8135 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8136 status = WERR_ACCESS_DENIED;
8140 /* can't set if builtin */
8141 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8142 status = WERR_INVALID_PARAM;
8146 count = get_ntforms(&list);
8147 update_a_form(&list, form, count);
8148 write_ntforms(&list, count);
8151 * ChangeID must always be set if this is a printer
8154 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8155 status = mod_a_printer(*printer, 2);
8160 free_a_printer(&printer, 2);
8166 /****************************************************************************
8167 enumprintprocessors level 1.
8168 ****************************************************************************/
8170 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8172 PRINTPROCESSOR_1 *info_1=NULL;
8174 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8179 init_unistr(&info_1->name, "winprint");
8181 *needed += spoolss_size_printprocessor_info_1(info_1);
8183 if (!alloc_buffer_size(buffer, *needed))
8184 return WERR_INSUFFICIENT_BUFFER;
8186 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8190 if (*needed > offered) {
8192 return WERR_INSUFFICIENT_BUFFER;
8198 /****************************************************************************
8199 ****************************************************************************/
8201 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8203 uint32 level = q_u->level;
8204 NEW_BUFFER *buffer = NULL;
8205 uint32 offered = q_u->offered;
8206 uint32 *needed = &r_u->needed;
8207 uint32 *returned = &r_u->returned;
8209 /* that's an [in out] buffer */
8210 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8211 buffer = r_u->buffer;
8213 DEBUG(5,("spoolss_enumprintprocessors\n"));
8216 * Enumerate the print processors ...
8218 * Just reply with "winprint", to keep NT happy
8219 * and I can use my nice printer checker.
8227 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8229 return WERR_UNKNOWN_LEVEL;
8233 /****************************************************************************
8234 enumprintprocdatatypes level 1.
8235 ****************************************************************************/
8237 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8239 PRINTPROCDATATYPE_1 *info_1=NULL;
8241 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8246 init_unistr(&info_1->name, "RAW");
8248 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8250 if (!alloc_buffer_size(buffer, *needed))
8251 return WERR_INSUFFICIENT_BUFFER;
8253 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8257 if (*needed > offered) {
8259 return WERR_INSUFFICIENT_BUFFER;
8265 /****************************************************************************
8266 ****************************************************************************/
8268 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8270 uint32 level = q_u->level;
8271 NEW_BUFFER *buffer = NULL;
8272 uint32 offered = q_u->offered;
8273 uint32 *needed = &r_u->needed;
8274 uint32 *returned = &r_u->returned;
8276 /* that's an [in out] buffer */
8277 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8278 buffer = r_u->buffer;
8280 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8287 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8289 return WERR_UNKNOWN_LEVEL;
8293 /****************************************************************************
8294 enumprintmonitors level 1.
8295 ****************************************************************************/
8297 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8299 PRINTMONITOR_1 *info_1=NULL;
8301 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8306 init_unistr(&info_1->name, "Local Port");
8308 *needed += spoolss_size_printmonitor_info_1(info_1);
8310 if (!alloc_buffer_size(buffer, *needed))
8311 return WERR_INSUFFICIENT_BUFFER;
8313 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8317 if (*needed > offered) {
8319 return WERR_INSUFFICIENT_BUFFER;
8325 /****************************************************************************
8326 enumprintmonitors level 2.
8327 ****************************************************************************/
8329 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8331 PRINTMONITOR_2 *info_2=NULL;
8333 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8338 init_unistr(&info_2->name, "Local Port");
8339 init_unistr(&info_2->environment, "Windows NT X86");
8340 init_unistr(&info_2->dll_name, "localmon.dll");
8342 *needed += spoolss_size_printmonitor_info_2(info_2);
8344 if (!alloc_buffer_size(buffer, *needed))
8345 return WERR_INSUFFICIENT_BUFFER;
8347 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8351 if (*needed > offered) {
8353 return WERR_INSUFFICIENT_BUFFER;
8359 /****************************************************************************
8360 ****************************************************************************/
8362 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8364 uint32 level = q_u->level;
8365 NEW_BUFFER *buffer = NULL;
8366 uint32 offered = q_u->offered;
8367 uint32 *needed = &r_u->needed;
8368 uint32 *returned = &r_u->returned;
8370 /* that's an [in out] buffer */
8371 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8372 buffer = r_u->buffer;
8374 DEBUG(5,("spoolss_enumprintmonitors\n"));
8377 * Enumerate the print monitors ...
8379 * Just reply with "Local Port", to keep NT happy
8380 * and I can use my nice printer checker.
8388 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8390 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8392 return WERR_UNKNOWN_LEVEL;
8396 /****************************************************************************
8397 ****************************************************************************/
8399 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8403 JOB_INFO_1 *info_1=NULL;
8405 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8407 if (info_1 == NULL) {
8411 for (i=0; i<count && found==False; i++) {
8412 if ((*queue)[i].job==(int)jobid)
8418 /* NT treats not found as bad param... yet another bad choice */
8419 return WERR_INVALID_PARAM;
8422 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8424 *needed += spoolss_size_job_info_1(info_1);
8426 if (!alloc_buffer_size(buffer, *needed)) {
8428 return WERR_INSUFFICIENT_BUFFER;
8431 smb_io_job_info_1("", buffer, info_1, 0);
8435 if (*needed > offered)
8436 return WERR_INSUFFICIENT_BUFFER;
8441 /****************************************************************************
8442 ****************************************************************************/
8444 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8449 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8451 DEVICEMODE *devmode = NULL;
8452 NT_DEVICEMODE *nt_devmode = NULL;
8454 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8456 ZERO_STRUCTP(info_2);
8458 if (info_2 == NULL) {
8463 for ( i=0; i<count && found==False; i++ )
8465 if ((*queue)[i].job == (int)jobid)
8471 /* NT treats not found as bad param... yet another bad
8473 ret = WERR_INVALID_PARAM;
8477 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8478 if (!W_ERROR_IS_OK(ret))
8482 * if the print job does not have a DEVMODE associated with it,
8483 * just use the one for the printer. A NULL devicemode is not
8484 * a failure condition
8487 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8488 devmode = construct_dev_mode(snum);
8490 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8491 ZERO_STRUCTP( devmode );
8492 convert_nt_devicemode( devmode, nt_devmode );
8496 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8498 *needed += spoolss_size_job_info_2(info_2);
8500 if (!alloc_buffer_size(buffer, *needed)) {
8501 ret = WERR_INSUFFICIENT_BUFFER;
8505 smb_io_job_info_2("", buffer, info_2, 0);
8507 if (*needed > offered) {
8508 ret = WERR_INSUFFICIENT_BUFFER;
8515 /* Cleanup allocated memory */
8517 free_job_info_2(info_2); /* Also frees devmode */
8519 free_a_printer(&ntprinter, 2);
8524 /****************************************************************************
8525 ****************************************************************************/
8527 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8529 POLICY_HND *handle = &q_u->handle;
8530 uint32 jobid = q_u->jobid;
8531 uint32 level = q_u->level;
8532 NEW_BUFFER *buffer = NULL;
8533 uint32 offered = q_u->offered;
8534 uint32 *needed = &r_u->needed;
8535 WERROR wstatus = WERR_OK;
8539 print_queue_struct *queue = NULL;
8540 print_status_struct prt_status;
8542 /* that's an [in out] buffer */
8543 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8544 buffer = r_u->buffer;
8546 DEBUG(5,("spoolss_getjob\n"));
8550 if (!get_printer_snum(p, handle, &snum))
8553 count = print_queue_status(snum, &queue, &prt_status);
8555 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8556 count, prt_status.status, prt_status.message));
8560 wstatus = getjob_level_1(&queue, count, snum, jobid,
8561 buffer, offered, needed);
8564 wstatus = getjob_level_2(&queue, count, snum, jobid,
8565 buffer, offered, needed);
8568 wstatus = WERR_UNKNOWN_LEVEL;
8576 /********************************************************************
8577 spoolss_getprinterdataex
8579 From MSDN documentation of GetPrinterDataEx: pass request
8580 to GetPrinterData if key is "PrinterDriverData".
8581 ********************************************************************/
8583 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8585 POLICY_HND *handle = &q_u->handle;
8586 uint32 in_size = q_u->size;
8587 uint32 *type = &r_u->type;
8588 uint32 *out_size = &r_u->size;
8589 uint8 **data = &r_u->data;
8590 uint32 *needed = &r_u->needed;
8591 fstring keyname, valuename;
8593 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8595 NT_PRINTER_INFO_LEVEL *printer = NULL;
8597 WERROR status = WERR_OK;
8599 DEBUG(4,("_spoolss_getprinterdataex\n"));
8601 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8602 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8604 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8605 keyname, valuename));
8607 /* in case of problem, return some default values */
8611 *out_size = in_size;
8614 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8615 status = WERR_BADFID;
8619 /* Is the handle to a printer or to the server? */
8621 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8622 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8623 status = WERR_INVALID_PARAM;
8627 if ( !get_printer_snum(p,handle, &snum) )
8630 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8631 if ( !W_ERROR_IS_OK(status) )
8634 /* check to see if the keyname is valid */
8635 if ( !strlen(keyname) ) {
8636 status = WERR_INVALID_PARAM;
8640 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8641 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8642 free_a_printer( &printer, 2 );
8643 status = WERR_BADFILE;
8647 /* When given a new keyname, we should just create it */
8649 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8651 if (*needed > *out_size)
8652 status = WERR_MORE_DATA;
8655 if ( !W_ERROR_IS_OK(status) )
8657 DEBUG(5, ("error: allocating %d\n", *out_size));
8659 /* reply this param doesn't exist */
8663 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8664 status = WERR_NOMEM;
8674 free_a_printer( &printer, 2 );
8679 /********************************************************************
8680 * spoolss_setprinterdataex
8681 ********************************************************************/
8683 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8685 POLICY_HND *handle = &q_u->handle;
8686 uint32 type = q_u->type;
8687 uint8 *data = q_u->data;
8688 uint32 real_len = q_u->real_len;
8690 NT_PRINTER_INFO_LEVEL *printer = NULL;
8692 WERROR status = WERR_OK;
8693 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8698 DEBUG(4,("_spoolss_setprinterdataex\n"));
8700 /* From MSDN documentation of SetPrinterDataEx: pass request to
8701 SetPrinterData if key is "PrinterDriverData" */
8704 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8708 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8709 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8710 return WERR_INVALID_PARAM;
8713 if ( !get_printer_snum(p,handle, &snum) )
8717 * Access check : NT returns "access denied" if you make a
8718 * SetPrinterData call without the necessary privildge.
8719 * we were originally returning OK if nothing changed
8720 * which made Win2k issue **a lot** of SetPrinterData
8721 * when connecting to a printer --jerry
8724 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8726 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8727 return WERR_ACCESS_DENIED;
8730 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8731 if (!W_ERROR_IS_OK(status))
8734 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8735 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8737 /* check for OID in valuename */
8739 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8745 /* save the registry data */
8747 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8749 if ( W_ERROR_IS_OK(status) )
8751 /* save the OID if one was specified */
8753 fstrcat( keyname, "\\" );
8754 fstrcat( keyname, SPOOL_OID_KEY );
8757 * I'm not checking the status here on purpose. Don't know
8758 * if this is right, but I'm returning the status from the
8759 * previous set_printer_dataex() call. I have no idea if
8760 * this is right. --jerry
8763 set_printer_dataex( printer, keyname, valuename,
8764 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8767 status = mod_a_printer(*printer, 2);
8770 free_a_printer(&printer, 2);
8776 /********************************************************************
8777 * spoolss_deleteprinterdataex
8778 ********************************************************************/
8780 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8782 POLICY_HND *handle = &q_u->handle;
8783 UNISTR2 *value = &q_u->valuename;
8784 UNISTR2 *key = &q_u->keyname;
8786 NT_PRINTER_INFO_LEVEL *printer = NULL;
8788 WERROR status = WERR_OK;
8789 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8790 pstring valuename, keyname;
8792 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8795 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8799 if (!get_printer_snum(p, handle, &snum))
8802 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8803 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8804 return WERR_ACCESS_DENIED;
8807 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8808 if (!W_ERROR_IS_OK(status))
8811 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8812 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8814 status = delete_printer_dataex( printer, keyname, valuename );
8816 if ( W_ERROR_IS_OK(status) )
8817 mod_a_printer( *printer, 2 );
8819 free_a_printer(&printer, 2);
8824 /********************************************************************
8825 * spoolss_enumprinterkey
8826 ********************************************************************/
8829 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8832 fstring *keynames = NULL;
8833 uint16 *enumkeys = NULL;
8836 POLICY_HND *handle = &q_u->handle;
8837 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8838 NT_PRINTER_DATA *data;
8839 NT_PRINTER_INFO_LEVEL *printer = NULL;
8841 WERROR status = WERR_BADFILE;
8844 DEBUG(4,("_spoolss_enumprinterkey\n"));
8847 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8851 if ( !get_printer_snum(p,handle, &snum) )
8854 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8855 if (!W_ERROR_IS_OK(status))
8858 /* get the list of subkey names */
8860 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8861 data = &printer->info_2->data;
8863 num_keys = get_printer_subkeys( data, key, &keynames );
8865 if ( num_keys == -1 ) {
8866 status = WERR_BADFILE;
8870 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8872 r_u->needed = printerkey_len*2;
8874 if ( q_u->size < r_u->needed ) {
8875 status = WERR_MORE_DATA;
8879 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8880 status = WERR_NOMEM;
8886 if ( q_u->size < r_u->needed )
8887 status = WERR_MORE_DATA;
8890 free_a_printer( &printer, 2 );
8891 SAFE_FREE( keynames );
8896 /********************************************************************
8897 * spoolss_deleteprinterkey
8898 ********************************************************************/
8900 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8902 POLICY_HND *handle = &q_u->handle;
8903 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8905 NT_PRINTER_INFO_LEVEL *printer = NULL;
8909 DEBUG(5,("spoolss_deleteprinterkey\n"));
8912 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8916 /* if keyname == NULL, return error */
8918 if ( !q_u->keyname.buffer )
8919 return WERR_INVALID_PARAM;
8921 if (!get_printer_snum(p, handle, &snum))
8924 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8925 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8926 return WERR_ACCESS_DENIED;
8929 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8930 if (!W_ERROR_IS_OK(status))
8933 /* delete the key and all subneys */
8935 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8937 status = delete_all_printer_data( printer->info_2, key );
8939 if ( W_ERROR_IS_OK(status) )
8940 status = mod_a_printer(*printer, 2);
8942 free_a_printer( &printer, 2 );
8948 /********************************************************************
8949 * spoolss_enumprinterdataex
8950 ********************************************************************/
8952 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8954 POLICY_HND *handle = &q_u->handle;
8955 uint32 in_size = q_u->size;
8958 NT_PRINTER_INFO_LEVEL *printer = NULL;
8959 PRINTER_ENUM_VALUES *enum_values = NULL;
8960 NT_PRINTER_DATA *p_data;
8962 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8967 REGISTRY_VALUE *val;
8972 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8975 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8980 * first check for a keyname of NULL or "". Win2k seems to send
8981 * this a lot and we should send back WERR_INVALID_PARAM
8982 * no need to spend time looking up the printer in this case.
8986 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8987 if ( !strlen(key) ) {
8988 result = WERR_INVALID_PARAM;
8992 /* get the printer off of disk */
8994 if (!get_printer_snum(p,handle, &snum))
8997 ZERO_STRUCT(printer);
8998 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8999 if (!W_ERROR_IS_OK(result))
9002 /* now look for a match on the key name */
9004 p_data = &printer->info_2->data;
9006 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9007 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9009 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9010 result = WERR_INVALID_PARAM;
9017 /* allocate the memory for the array of pointers -- if necessary */
9019 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9022 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9024 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9025 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9026 result = WERR_NOMEM;
9030 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9034 * loop through all params and build the array to pass
9035 * back to the client
9038 for ( i=0; i<num_entries; i++ )
9040 /* lookup the registry value */
9042 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9043 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9047 value_name = regval_name( val );
9048 init_unistr( &enum_values[i].valuename, value_name );
9049 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9050 enum_values[i].type = regval_type( val );
9052 data_len = regval_size( val );
9054 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9056 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9058 result = WERR_NOMEM;
9062 enum_values[i].data_len = data_len;
9064 /* keep track of the size of the array in bytes */
9066 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9069 /* housekeeping information in the reply */
9071 r_u->needed = needed;
9072 r_u->returned = num_entries;
9074 if (needed > in_size) {
9075 result = WERR_MORE_DATA;
9079 /* copy data into the reply */
9081 r_u->ctr.size = r_u->needed;
9082 r_u->ctr.size_of_array = r_u->returned;
9083 r_u->ctr.values = enum_values;
9089 free_a_printer(&printer, 2);
9094 /****************************************************************************
9095 ****************************************************************************/
9097 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9099 init_unistr(&info->name, name);
9102 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9103 UNISTR2 *environment,
9110 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9112 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9114 if (!get_short_archi(long_archi))
9115 return WERR_INVALID_ENVIRONMENT;
9117 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9120 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9122 fill_printprocessordirectory_1(info, path);
9124 *needed += spoolss_size_printprocessordirectory_info_1(info);
9126 if (!alloc_buffer_size(buffer, *needed)) {
9128 return WERR_INSUFFICIENT_BUFFER;
9131 smb_io_printprocessordirectory_1("", buffer, info, 0);
9135 if (*needed > offered)
9136 return WERR_INSUFFICIENT_BUFFER;
9141 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9143 uint32 level = q_u->level;
9144 NEW_BUFFER *buffer = NULL;
9145 uint32 offered = q_u->offered;
9146 uint32 *needed = &r_u->needed;
9149 /* that's an [in out] buffer */
9150 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9151 buffer = r_u->buffer;
9153 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9159 result = getprintprocessordirectory_level_1
9160 (&q_u->name, &q_u->environment, buffer, offered, needed);
9163 result = WERR_UNKNOWN_LEVEL;
9171 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9172 SPOOL_R_REPLYOPENPRINTER *r_u)
9174 DEBUG(5,("_spoolss_replyopenprinter\n"));
9176 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9181 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9182 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9184 DEBUG(5,("_spoolss_replycloseprinter\n"));