2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 /* Table to map the driver version */
44 static const char * drv_ver_to_os[] = {
45 "WIN9X", /* driver version/cversion 0 */
47 "WINNT", /* driver version/cversion 2 */
48 "WIN2K", /* driver version/cversion 3 */
51 static const char *get_drv_ver_to_os(int ver)
53 if (ver < 0 || ver > 3)
55 return drv_ver_to_os[ver];
59 const char *long_archi;
60 const char *short_archi;
64 static Printer_entry *printers_list;
66 typedef struct _counter_printer_0 {
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
316 && StrCaseCmp(p->dev.handlename, printername)==0)
318 DEBUG(10,("invalidating printer_info cache for handl:\n"));
319 free_a_printer( &p->printer_info, 2 );
320 p->printer_info = NULL;
326 /****************************************************************************
327 Close printer index by handle.
328 ****************************************************************************/
330 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
332 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
335 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
339 close_policy_hnd(p, hnd);
344 /****************************************************************************
345 Delete a printer given a handle.
346 ****************************************************************************/
348 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
350 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
353 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
358 * It turns out that Windows allows delete printer on a handle
359 * opened by an admin user, then used on a pipe handle created
360 * by an anonymous user..... but they're working on security.... riiight !
364 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
365 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
366 return WERR_ACCESS_DENIED;
370 /* Check calling user has permission to delete printer. Note that
371 since we set the snum parameter to -1 only administrators can
372 delete the printer. This stops people with the Full Control
373 permission from deleting the printer. */
375 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
376 DEBUG(3, ("printer delete denied by security descriptor\n"));
377 return WERR_ACCESS_DENIED;
381 if (del_a_printer(Printer->dev.handlename) != 0) {
382 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
386 if (*lp_deleteprinter_cmd()) {
388 char *cmd = lp_deleteprinter_cmd();
392 /* Printer->dev.handlename equals portname equals sharename */
393 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
394 Printer->dev.handlename);
396 DEBUG(10,("Running [%s]\n", command));
397 ret = smbrun(command, NULL);
399 return WERR_BADFID; /* What to return here? */
401 DEBUGADD(10,("returned [%d]\n", ret));
403 /* Send SIGHUP to process group... is there a better way? */
406 /* go ahead and re-read the services immediately */
407 reload_services( False );
409 if ( lp_servicenumber( Printer->dev.handlename ) < 0 )
410 return WERR_ACCESS_DENIED;
416 /****************************************************************************
417 Return the snum of a printer corresponding to an handle.
418 ****************************************************************************/
420 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
422 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
425 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
429 switch (Printer->printer_type) {
430 case PRINTER_HANDLE_IS_PRINTER:
431 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
432 *number = print_queue_snum(Printer->dev.handlename);
433 return (*number != -1);
434 case PRINTER_HANDLE_IS_PRINTSERVER:
441 /****************************************************************************
442 Set printer handle type.
443 Check if it's \\server or \\server\printer
444 ****************************************************************************/
446 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
448 DEBUG(3,("Setting printer type=%s\n", handlename));
450 if ( strlen(handlename) < 3 ) {
451 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
455 /* it's a print server */
456 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
457 DEBUGADD(4,("Printer is a print server\n"));
458 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
462 DEBUGADD(4,("Printer is a printer\n"));
463 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
469 /****************************************************************************
470 Set printer handle name.
471 ****************************************************************************/
473 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
476 int n_services=lp_numservices();
477 char *aprinter, *printername;
480 NT_PRINTER_INFO_LEVEL *printer;
483 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
485 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
486 ZERO_STRUCT(Printer->dev.printerservername);
487 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
491 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
494 if (*handlename=='\\') {
495 aprinter=strchr_m(handlename+2, '\\');
502 DEBUGADD(5, ("searching for [%s] (len=%lu)\n", aprinter, (unsigned long)strlen(aprinter)));
504 /* have to search on sharename and PRINTER_INFO2->printername */
506 for (snum=0; snum<n_services; snum++) {
508 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
511 /* ------ sharename ------ */
513 fstrcpy(sname, lp_servicename(snum));
515 DEBUGADD(10, ("share: %s\n",sname));
517 if ( strequal(sname, aprinter) ) {
522 /* ------ printername ------ */
525 result = get_a_printer( NULL, &printer, 2, sname );
526 if ( !W_ERROR_IS_OK(result) ) {
527 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
528 sname, dos_errstr(result)));
532 /* printername is always returned as \\server\printername */
533 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
534 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
535 printer->info_2->printername));
536 free_a_printer( &printer, 2);
542 if ( strequal(printername, aprinter) ) {
546 DEBUGADD(10, ("printername: %s\n", printername));
548 free_a_printer( &printer, 2);
556 DEBUGADD(4,("Printer not found\n"));
560 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
562 ZERO_STRUCT(Printer->dev.handlename);
563 fstrcpy(Printer->dev.handlename, sname);
568 /****************************************************************************
569 Find first available printer slot. creates a printer handle for you.
570 ****************************************************************************/
572 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
574 Printer_entry *new_printer;
576 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
578 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
581 ZERO_STRUCTP(new_printer);
583 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
584 SAFE_FREE(new_printer);
588 /* Add to the internal list. */
589 DLIST_ADD(printers_list, new_printer);
591 new_printer->notify.option=NULL;
593 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
594 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
595 close_printer_handle(p, hnd);
599 if (!set_printer_hnd_printertype(new_printer, name)) {
600 close_printer_handle(p, hnd);
604 if (!set_printer_hnd_name(new_printer, name)) {
605 close_printer_handle(p, hnd);
609 new_printer->access_granted = access_granted;
611 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
616 /****************************************************************************
617 Allocate more memory for a BUFFER.
618 ****************************************************************************/
620 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
628 /* damn, I'm doing the reverse operation of prs_grow() :) */
629 if (buffer_size < prs_data_size(ps))
632 extra_space = buffer_size - prs_data_size(ps);
635 * save the offset and move to the end of the buffer
636 * prs_grow() checks the extra_space against the offset
638 old_offset=prs_offset(ps);
639 prs_set_offset(ps, prs_data_size(ps));
641 if (!prs_grow(ps, extra_space))
644 prs_set_offset(ps, old_offset);
646 buffer->string_at_end=prs_data_size(ps);
651 /***************************************************************************
652 check to see if the client motify handle is monitoring the notification
653 given by (notify_type, notify_field).
654 **************************************************************************/
656 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
662 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
665 SPOOL_NOTIFY_OPTION *option = p->notify.option;
669 * Flags should always be zero when the change notify
670 * is registered by the client's spooler. A user Win32 app
671 * might use the flags though instead of the NOTIFY_OPTION_INFO
676 return is_monitoring_event_flags(
677 p->notify.flags, notify_type, notify_field);
679 for (i = 0; i < option->count; i++) {
681 /* Check match for notify_type */
683 if (option->ctr.type[i].type != notify_type)
686 /* Check match for field */
688 for (j = 0; j < option->ctr.type[i].count; j++) {
689 if (option->ctr.type[i].fields[j] == notify_field) {
695 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
696 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
697 p->dev.handlename : p->dev.printerservername,
698 notify_type, notify_field));
703 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
705 static void notify_one_value(struct spoolss_notify_msg *msg,
706 SPOOL_NOTIFY_INFO_DATA *data,
709 data->notify_data.value[0] = msg->notify.value[0];
710 data->notify_data.value[1] = 0;
713 static void notify_string(struct spoolss_notify_msg *msg,
714 SPOOL_NOTIFY_INFO_DATA *data,
719 /* The length of the message includes the trailing \0 */
721 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
723 data->notify_data.data.length = msg->len * 2;
724 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
726 if (!data->notify_data.data.string) {
727 data->notify_data.data.length = 0;
731 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
734 static void notify_system_time(struct spoolss_notify_msg *msg,
735 SPOOL_NOTIFY_INFO_DATA *data,
741 if (msg->len != sizeof(time_t)) {
742 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
747 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
748 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
752 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
753 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
757 if (!spoolss_io_system_time("", &ps, 0, &systime))
760 data->notify_data.data.length = prs_offset(&ps);
761 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
763 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
768 struct notify2_message_table {
770 void (*fn)(struct spoolss_notify_msg *msg,
771 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
774 static struct notify2_message_table printer_notify_table[] = {
775 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
776 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
777 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
778 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
779 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
780 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
781 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
782 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
783 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
784 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
785 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
786 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
787 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
788 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
789 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
790 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
791 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
792 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
793 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
796 static struct notify2_message_table job_notify_table[] = {
797 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
798 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
799 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
800 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
801 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
802 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
803 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
804 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
805 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
806 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
807 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
808 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
809 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
810 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
811 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
812 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
813 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
814 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
815 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
816 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
817 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
818 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
819 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
820 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
824 /***********************************************************************
825 Allocate talloc context for container object
826 **********************************************************************/
828 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
833 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
838 /***********************************************************************
839 release all allocated memory and zero out structure
840 **********************************************************************/
842 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
848 talloc_destroy(ctr->ctx);
855 /***********************************************************************
856 **********************************************************************/
858 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
866 /***********************************************************************
867 **********************************************************************/
869 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
871 if ( !ctr || !ctr->msg_groups )
874 if ( idx >= ctr->num_groups )
877 return &ctr->msg_groups[idx];
881 /***********************************************************************
882 How many groups of change messages do we have ?
883 **********************************************************************/
885 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
890 return ctr->num_groups;
893 /***********************************************************************
894 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
895 **********************************************************************/
897 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
899 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
900 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
901 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
907 /* loop over all groups looking for a matching printer name */
909 for ( i=0; i<ctr->num_groups; i++ ) {
910 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
914 /* add a new group? */
916 if ( i == ctr->num_groups ) {
919 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
920 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
923 ctr->msg_groups = groups;
925 /* clear the new entry and set the printer name */
927 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
928 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
931 /* add the change messages; 'i' is the correct index now regardless */
933 msg_grp = &ctr->msg_groups[i];
937 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
938 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
941 msg_grp->msgs = msg_list;
943 new_slot = msg_grp->num_msgs-1;
944 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
946 /* need to allocate own copy of data */
949 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
951 return ctr->num_groups;
954 /***********************************************************************
955 Send a change notication message on all handles which have a call
957 **********************************************************************/
959 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
962 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
963 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
964 SPOOLSS_NOTIFY_MSG *messages;
965 int sending_msg_count;
968 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
972 messages = msg_group->msgs;
975 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
979 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
981 /* loop over all printers */
983 for (p = printers_list; p; p = p->next) {
984 SPOOL_NOTIFY_INFO_DATA *data;
989 /* Is there notification on this handle? */
991 if ( !p->notify.client_connected )
994 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
996 /* For this printer? Print servers always receive
999 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1000 ( !strequal(msg_group->printername, p->dev.handlename) ) )
1003 DEBUG(10,("Our printer\n"));
1005 /* allocate the max entries possible */
1007 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
1010 /* build the array of change notifications */
1012 sending_msg_count = 0;
1014 for ( i=0; i<msg_group->num_msgs; i++ ) {
1015 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1017 /* Are we monitoring this event? */
1019 if (!is_monitoring_event(p, msg->type, msg->field))
1022 sending_msg_count++;
1025 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
1026 msg->type, msg->field, p->dev.handlename));
1029 * if the is a printer notification handle and not a job notification
1030 * type, then set the id to 0. Other wise just use what was specified
1033 * When registering change notification on a print server handle
1034 * we always need to send back the id (snum) matching the printer
1035 * for which the change took place. For change notify registered
1036 * on a printer handle, this does not matter and the id should be 0.
1041 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1047 /* Convert unix jobid to smb jobid */
1049 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1050 id = sysjob_to_jobid(msg->id);
1053 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1058 construct_info_data( &data[data_len], msg->type, msg->field, id );
1061 case PRINTER_NOTIFY_TYPE:
1062 if ( printer_notify_table[msg->field].fn )
1063 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1066 case JOB_NOTIFY_TYPE:
1067 if ( job_notify_table[msg->field].fn )
1068 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1072 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1079 if ( sending_msg_count ) {
1080 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1081 data_len, data, p->notify.change, 0 );
1086 DEBUG(8,("send_notify2_changes: Exit...\n"));
1090 /***********************************************************************
1091 **********************************************************************/
1093 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1096 uint32 tv_sec, tv_usec;
1099 /* Unpack message */
1101 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1104 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1106 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1109 tdb_unpack((char *)buf + offset, len - offset, "dd",
1110 &msg->notify.value[0], &msg->notify.value[1]);
1112 tdb_unpack((char *)buf + offset, len - offset, "B",
1113 &msg->len, &msg->notify.data);
1115 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1116 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1118 tv->tv_sec = tv_sec;
1119 tv->tv_usec = tv_usec;
1122 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1123 msg->notify.value[1]));
1125 dump_data(3, msg->notify.data, msg->len);
1130 /********************************************************************
1131 Receive a notify2 message list
1132 ********************************************************************/
1134 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1136 size_t msg_count, i;
1137 char *buf = (char *)msg;
1140 SPOOLSS_NOTIFY_MSG notify;
1141 SPOOLSS_NOTIFY_MSG_CTR messages;
1145 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1149 msg_count = IVAL(buf, 0);
1152 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1154 if (msg_count == 0) {
1155 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1159 /* initialize the container */
1161 ZERO_STRUCT( messages );
1162 notify_msg_ctr_init( &messages );
1165 * build message groups for each printer identified
1166 * in a change_notify msg. Remember that a PCN message
1167 * includes the handle returned for the srv_spoolss_replyopenprinter()
1168 * call. Therefore messages are grouped according to printer handle.
1171 for ( i=0; i<msg_count; i++ ) {
1172 struct timeval msg_tv;
1174 if (msg_ptr + 4 - buf > len) {
1175 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1179 msg_len = IVAL(msg_ptr,0);
1182 if (msg_ptr + msg_len - buf > len) {
1183 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1187 /* unpack messages */
1189 ZERO_STRUCT( notify );
1190 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1193 /* we don't know if the change was from us or not so kill
1194 any cached printer objects */
1196 if ( notify.type == PRINTER_NOTIFY_TYPE )
1197 invalidate_printer_hnd_cache( notify.printer );
1199 /* add to correct list in container */
1201 notify_msg_ctr_addmsg( &messages, ¬ify );
1203 /* free memory that might have been allocated by notify2_unpack_msg() */
1205 if ( notify.len != 0 )
1206 SAFE_FREE( notify.notify.data );
1209 /* process each group of messages */
1211 num_groups = notify_msg_ctr_numgroups( &messages );
1212 for ( i=0; i<num_groups; i++ )
1213 send_notify2_changes( &messages, i );
1218 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1220 notify_msg_ctr_destroy( &messages );
1225 /********************************************************************
1226 Send a message to ourself about new driver being installed
1227 so we can upgrade the information for each printer bound to this
1229 ********************************************************************/
1231 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1233 int len = strlen(drivername);
1238 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1241 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1246 /**********************************************************************
1247 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1248 over all printers, upgrading ones as necessary
1249 **********************************************************************/
1251 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1255 int n_services = lp_numservices();
1257 len = MIN(len,sizeof(drivername)-1);
1258 strncpy(drivername, buf, len);
1260 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1262 /* Iterate the printer list */
1264 for (snum=0; snum<n_services; snum++)
1266 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1269 NT_PRINTER_INFO_LEVEL *printer = NULL;
1271 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1272 if (!W_ERROR_IS_OK(result))
1275 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1277 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1279 /* all we care about currently is the change_id */
1281 result = mod_a_printer(*printer, 2);
1282 if (!W_ERROR_IS_OK(result)) {
1283 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1284 dos_errstr(result)));
1288 free_a_printer(&printer, 2);
1295 /********************************************************************
1296 Update the cache for all printq's with a registered client
1298 ********************************************************************/
1300 void update_monitored_printq_cache( void )
1302 Printer_entry *printer = printers_list;
1305 /* loop through all printers and update the cache where
1306 client_connected == True */
1309 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1310 && printer->notify.client_connected )
1312 snum = print_queue_snum(printer->dev.handlename);
1313 print_queue_status( snum, NULL, NULL );
1316 printer = printer->next;
1321 /********************************************************************
1322 Send a message to ourself about new driver being installed
1323 so we can upgrade the information for each printer bound to this
1325 ********************************************************************/
1327 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1329 int len = strlen(drivername);
1334 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1337 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1342 /**********************************************************************
1343 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1344 over all printers, resetting printer data as neessary
1345 **********************************************************************/
1347 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1351 int n_services = lp_numservices();
1353 len = MIN( len, sizeof(drivername)-1 );
1354 strncpy( drivername, buf, len );
1356 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1358 /* Iterate the printer list */
1360 for ( snum=0; snum<n_services; snum++ )
1362 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1365 NT_PRINTER_INFO_LEVEL *printer = NULL;
1367 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1368 if ( !W_ERROR_IS_OK(result) )
1372 * if the printer is bound to the driver,
1373 * then reset to the new driver initdata
1376 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1378 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1380 if ( !set_driver_init(printer, 2) ) {
1381 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1382 printer->info_2->printername, printer->info_2->drivername));
1385 result = mod_a_printer( *printer, 2 );
1386 if ( !W_ERROR_IS_OK(result) ) {
1387 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1388 get_dos_error_msg(result)));
1392 free_a_printer( &printer, 2 );
1401 /********************************************************************
1402 Copy routines used by convert_to_openprinterex()
1403 *******************************************************************/
1405 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1413 DEBUG (8,("dup_devmode\n"));
1415 /* bulk copy first */
1417 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1421 /* dup the pointer members separately */
1423 len = unistrlen(devmode->devicename.buffer);
1425 d->devicename.buffer = talloc(ctx, len*2);
1426 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1431 len = unistrlen(devmode->formname.buffer);
1433 d->devicename.buffer = talloc(ctx, len*2);
1434 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1438 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1443 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1445 if (!new_ctr || !ctr)
1448 DEBUG(8,("copy_devmode_ctr\n"));
1450 new_ctr->size = ctr->size;
1451 new_ctr->devmode_ptr = ctr->devmode_ptr;
1453 if(ctr->devmode_ptr)
1454 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1457 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1459 if (!new_def || !def)
1462 DEBUG(8,("copy_printer_defaults\n"));
1464 new_def->datatype_ptr = def->datatype_ptr;
1466 if (def->datatype_ptr)
1467 copy_unistr2(&new_def->datatype, &def->datatype);
1469 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1471 new_def->access_required = def->access_required;
1474 /********************************************************************
1475 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1476 * SPOOL_Q_OPEN_PRINTER_EX structure
1477 ********************************************************************/
1479 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1481 if (!q_u_ex || !q_u)
1484 DEBUG(8,("convert_to_openprinterex\n"));
1486 q_u_ex->printername_ptr = q_u->printername_ptr;
1488 if (q_u->printername_ptr)
1489 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1491 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1494 /********************************************************************
1495 * spoolss_open_printer
1497 * called from the spoolss dispatcher
1498 ********************************************************************/
1500 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1502 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1503 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1508 ZERO_STRUCT(q_u_ex);
1509 ZERO_STRUCT(r_u_ex);
1511 /* convert the OpenPrinter() call to OpenPrinterEx() */
1513 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1515 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1517 /* convert back to OpenPrinter() */
1519 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1524 /********************************************************************
1525 * spoolss_open_printer
1527 * If the openprinterex rpc call contains a devmode,
1528 * it's a per-user one. This per-user devmode is derivated
1529 * from the global devmode. Openprinterex() contains a per-user
1530 * devmode for when you do EMF printing and spooling.
1531 * In the EMF case, the NT workstation is only doing half the job
1532 * of rendering the page. The other half is done by running the printer
1533 * driver on the server.
1534 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1535 * The EMF file only contains what is to be printed on the page.
1536 * So in order for the server to know how to print, the NT client sends
1537 * a devicemode attached to the openprinterex call.
1538 * But this devicemode is short lived, it's only valid for the current print job.
1540 * If Samba would have supported EMF spooling, this devicemode would
1541 * have been attached to the handle, to sent it to the driver to correctly
1542 * rasterize the EMF file.
1544 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1545 * we just act as a pass-thru between windows and the printer.
1547 * In order to know that Samba supports only RAW spooling, NT has to call
1548 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1549 * and until NT sends a RAW job, we refuse it.
1551 * But to call getprinter() or startdoc(), you first need a valid handle,
1552 * and to get an handle you have to call openprintex(). Hence why you have
1553 * a devicemode in the openprinterex() call.
1556 * Differences between NT4 and NT 2000.
1559 * On NT4, you only have a global devicemode. This global devicemode can be changed
1560 * by the administrator (or by a user with enough privs). Everytime a user
1561 * wants to print, the devicemode is resetted to the default. In Word, everytime
1562 * you print, the printer's characteristics are always reset to the global devicemode.
1566 * In W2K, there is the notion of per-user devicemode. The first time you use
1567 * a printer, a per-user devicemode is build from the global devicemode.
1568 * If you change your per-user devicemode, it is saved in the registry, under the
1569 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1570 * printer preferences available.
1572 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1573 * on the General Tab of the printer properties windows.
1575 * To change the global devicemode: it's the "Printing Defaults..." button
1576 * on the Advanced Tab of the printer properties window.
1579 ********************************************************************/
1581 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1583 UNISTR2 *printername = NULL;
1584 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1585 POLICY_HND *handle = &r_u->handle;
1589 struct current_user user;
1590 Printer_entry *Printer=NULL;
1592 if (q_u->printername_ptr != 0)
1593 printername = &q_u->printername;
1595 if (printername == NULL)
1596 return WERR_INVALID_PRINTER_NAME;
1598 /* some sanity check because you can open a printer or a print server */
1599 /* aka: \\server\printer or \\server */
1600 unistr2_to_ascii(name, printername, sizeof(name)-1);
1602 DEBUGADD(3,("checking name: %s\n",name));
1604 if (!open_printer_hnd(p, handle, name, 0))
1605 return WERR_INVALID_PRINTER_NAME;
1607 Printer=find_printer_index_by_hnd(p, handle);
1609 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1610 Can't find printer handle we created for printer %s\n", name ));
1611 close_printer_handle(p,handle);
1612 return WERR_INVALID_PRINTER_NAME;
1615 get_current_user(&user, p);
1618 * First case: the user is opening the print server:
1620 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1621 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1623 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1624 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1625 * or if the user is listed in the smb.conf printer admin parameter.
1627 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1628 * client view printer folder, but does not show the MSAPW.
1630 * Note: this test needs code to check access rights here too. Jeremy
1631 * could you look at this?
1633 * Second case: the user is opening a printer:
1634 * NT doesn't let us connect to a printer if the connecting user
1635 * doesn't have print permission.
1638 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1640 /* Printserver handles use global struct... */
1644 /* Map standard access rights to object specific access rights */
1646 se_map_standard(&printer_default->access_required,
1647 &printserver_std_mapping);
1649 /* Deny any object specific bits that don't apply to print
1650 servers (i.e printer and job specific bits) */
1652 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1654 if (printer_default->access_required &
1655 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1656 DEBUG(3, ("access DENIED for non-printserver bits"));
1657 close_printer_handle(p, handle);
1658 return WERR_ACCESS_DENIED;
1661 /* Allow admin access */
1663 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1665 if (!lp_ms_add_printer_wizard()) {
1666 close_printer_handle(p, handle);
1667 return WERR_ACCESS_DENIED;
1670 /* if the user is not root and not a printer admin, then fail */
1673 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1675 close_printer_handle(p, handle);
1676 return WERR_ACCESS_DENIED;
1679 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1683 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1686 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1687 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1689 /* We fall through to return WERR_OK */
1694 /* NT doesn't let us connect to a printer if the connecting user
1695 doesn't have print permission. */
1697 if (!get_printer_snum(p, handle, &snum)) {
1698 close_printer_handle(p, handle);
1702 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1704 /* map an empty access mask to the minimum access mask */
1705 if (printer_default->access_required == 0x0)
1706 printer_default->access_required = PRINTER_ACCESS_USE;
1709 * If we are not serving the printer driver for this printer,
1710 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1711 * will keep NT clients happy --jerry
1714 if (lp_use_client_driver(snum)
1715 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1717 printer_default->access_required = PRINTER_ACCESS_USE;
1720 /* check smb.conf parameters and the the sec_desc */
1722 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1723 DEBUG(3, ("access DENIED for printer open\n"));
1724 close_printer_handle(p, handle);
1725 return WERR_ACCESS_DENIED;
1728 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1729 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1730 close_printer_handle(p, handle);
1731 return WERR_ACCESS_DENIED;
1734 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1735 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1737 printer_default->access_required = PRINTER_ACCESS_USE;
1739 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1740 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1744 Printer->access_granted = printer_default->access_required;
1747 * If the client sent a devmode in the OpenPrinter() call, then
1748 * save it here in case we get a job submission on this handle
1751 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1752 && q_u->printer_default.devmode_cont.devmode_ptr )
1754 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1755 &Printer->nt_devmode );
1758 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1759 optimization in Windows 2000 clients --jerry */
1761 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1762 && (RA_WIN2K == get_remote_arch()) )
1764 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1765 sys_usleep( 500000 );
1771 /****************************************************************************
1772 ****************************************************************************/
1774 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1775 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1781 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1790 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1791 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1797 printer->info_3=NULL;
1798 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1802 printer->info_6=NULL;
1803 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1813 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1814 NT_DEVICEMODE **pp_nt_devmode)
1816 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1819 * Ensure nt_devmode is a valid pointer
1820 * as we will be overwriting it.
1823 if (nt_devmode == NULL) {
1824 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1825 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1829 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1830 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1832 nt_devmode->specversion=devmode->specversion;
1833 nt_devmode->driverversion=devmode->driverversion;
1834 nt_devmode->size=devmode->size;
1835 nt_devmode->fields=devmode->fields;
1836 nt_devmode->orientation=devmode->orientation;
1837 nt_devmode->papersize=devmode->papersize;
1838 nt_devmode->paperlength=devmode->paperlength;
1839 nt_devmode->paperwidth=devmode->paperwidth;
1840 nt_devmode->scale=devmode->scale;
1841 nt_devmode->copies=devmode->copies;
1842 nt_devmode->defaultsource=devmode->defaultsource;
1843 nt_devmode->printquality=devmode->printquality;
1844 nt_devmode->color=devmode->color;
1845 nt_devmode->duplex=devmode->duplex;
1846 nt_devmode->yresolution=devmode->yresolution;
1847 nt_devmode->ttoption=devmode->ttoption;
1848 nt_devmode->collate=devmode->collate;
1850 nt_devmode->logpixels=devmode->logpixels;
1851 nt_devmode->bitsperpel=devmode->bitsperpel;
1852 nt_devmode->pelswidth=devmode->pelswidth;
1853 nt_devmode->pelsheight=devmode->pelsheight;
1854 nt_devmode->displayflags=devmode->displayflags;
1855 nt_devmode->displayfrequency=devmode->displayfrequency;
1856 nt_devmode->icmmethod=devmode->icmmethod;
1857 nt_devmode->icmintent=devmode->icmintent;
1858 nt_devmode->mediatype=devmode->mediatype;
1859 nt_devmode->dithertype=devmode->dithertype;
1860 nt_devmode->reserved1=devmode->reserved1;
1861 nt_devmode->reserved2=devmode->reserved2;
1862 nt_devmode->panningwidth=devmode->panningwidth;
1863 nt_devmode->panningheight=devmode->panningheight;
1866 * Only change private and driverextra if the incoming devmode
1867 * has a new one. JRA.
1870 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1871 SAFE_FREE(nt_devmode->private);
1872 nt_devmode->driverextra=devmode->driverextra;
1873 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1875 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1878 *pp_nt_devmode = nt_devmode;
1883 /********************************************************************
1884 * _spoolss_enddocprinter_internal.
1885 ********************************************************************/
1887 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1889 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1893 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1897 if (!get_printer_snum(p, handle, &snum))
1900 Printer->document_started=False;
1901 print_job_end(snum, Printer->jobid,True);
1902 /* error codes unhandled so far ... */
1907 /********************************************************************
1908 * api_spoolss_closeprinter
1909 ********************************************************************/
1911 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1913 POLICY_HND *handle = &q_u->handle;
1915 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1917 if (Printer && Printer->document_started)
1918 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1920 if (!close_printer_handle(p, handle))
1923 /* clear the returned printer handle. Observed behavior
1924 from Win2k server. Don't think this really matters.
1925 Previous code just copied the value of the closed
1928 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1933 /********************************************************************
1934 * api_spoolss_deleteprinter
1936 ********************************************************************/
1938 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1940 POLICY_HND *handle = &q_u->handle;
1941 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1944 if (Printer && Printer->document_started)
1945 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1947 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1949 result = delete_printer_handle(p, handle);
1951 update_c_setprinter(False);
1956 /*******************************************************************
1957 * static function to lookup the version id corresponding to an
1958 * long architecture string
1959 ******************************************************************/
1961 static int get_version_id (char * arch)
1964 struct table_node archi_table[]= {
1966 {"Windows 4.0", "WIN40", 0 },
1967 {"Windows NT x86", "W32X86", 2 },
1968 {"Windows NT R4000", "W32MIPS", 2 },
1969 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1970 {"Windows NT PowerPC", "W32PPC", 2 },
1974 for (i=0; archi_table[i].long_archi != NULL; i++)
1976 if (strcmp(arch, archi_table[i].long_archi) == 0)
1977 return (archi_table[i].version);
1983 /********************************************************************
1984 * _spoolss_deleteprinterdriver
1985 ********************************************************************/
1987 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1991 NT_PRINTER_DRIVER_INFO_LEVEL info;
1992 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1994 struct current_user user;
1996 WERROR status_win2k = WERR_ACCESS_DENIED;
1998 get_current_user(&user, p);
2000 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2001 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2003 /* check that we have a valid driver name first */
2005 if ((version=get_version_id(arch)) == -1)
2006 return WERR_INVALID_ENVIRONMENT;
2009 ZERO_STRUCT(info_win2k);
2011 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2013 /* try for Win2k driver if "Windows NT x86" */
2015 if ( version == 2 ) {
2017 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2018 status = WERR_UNKNOWN_PRINTER_DRIVER;
2022 /* otherwise it was a failure */
2024 status = WERR_UNKNOWN_PRINTER_DRIVER;
2030 if (printer_driver_in_use(info.info_3)) {
2031 status = WERR_PRINTER_DRIVER_IN_USE;
2037 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2039 /* if we get to here, we now have 2 driver info structures to remove */
2040 /* remove the Win2k driver first*/
2042 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2043 free_a_printer_driver( info_win2k, 3 );
2045 /* this should not have failed---if it did, report to client */
2046 if ( !W_ERROR_IS_OK(status_win2k) )
2051 status = delete_printer_driver(info.info_3, &user, version, False);
2053 /* if at least one of the deletes succeeded return OK */
2055 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2059 free_a_printer_driver( info, 3 );
2064 /********************************************************************
2065 * spoolss_deleteprinterdriverex
2066 ********************************************************************/
2068 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2072 NT_PRINTER_DRIVER_INFO_LEVEL info;
2073 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2075 uint32 flags = q_u->delete_flags;
2077 struct current_user user;
2079 WERROR status_win2k = WERR_ACCESS_DENIED;
2081 get_current_user(&user, p);
2083 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2084 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2086 /* check that we have a valid driver name first */
2087 if ((version=get_version_id(arch)) == -1) {
2088 /* this is what NT returns */
2089 return WERR_INVALID_ENVIRONMENT;
2092 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2093 version = q_u->version;
2096 ZERO_STRUCT(info_win2k);
2098 status = get_a_printer_driver(&info, 3, driver, arch, version);
2100 if ( !W_ERROR_IS_OK(status) )
2103 * if the client asked for a specific version,
2104 * or this is something other than Windows NT x86,
2108 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2111 /* try for Win2k driver if "Windows NT x86" */
2114 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2115 status = WERR_UNKNOWN_PRINTER_DRIVER;
2120 if ( printer_driver_in_use(info.info_3) ) {
2121 status = WERR_PRINTER_DRIVER_IN_USE;
2126 * we have a couple of cases to consider.
2127 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2128 * then the delete should fail if **any** files overlap with
2130 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2131 * non-overlapping files
2132 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2133 * is set, the do not delete any files
2134 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2137 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2139 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2141 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2142 /* no idea of the correct error here */
2143 status = WERR_ACCESS_DENIED;
2148 /* also check for W32X86/3 if necessary; maybe we already have? */
2150 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2151 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2154 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2155 /* no idea of the correct error here */
2156 free_a_printer_driver( info_win2k, 3 );
2157 status = WERR_ACCESS_DENIED;
2161 /* if we get to here, we now have 2 driver info structures to remove */
2162 /* remove the Win2k driver first*/
2164 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2165 free_a_printer_driver( info_win2k, 3 );
2167 /* this should not have failed---if it did, report to client */
2169 if ( !W_ERROR_IS_OK(status_win2k) )
2174 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2176 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2179 free_a_printer_driver( info, 3 );
2185 /****************************************************************************
2186 Internal routine for retreiving printerdata
2187 ***************************************************************************/
2189 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2190 const char *key, const char *value, uint32 *type, uint8 **data,
2191 uint32 *needed, uint32 in_size )
2193 REGISTRY_VALUE *val;
2196 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2197 return WERR_BADFILE;
2199 *type = regval_type( val );
2201 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2203 size = regval_size( val );
2205 /* copy the min(in_size, len) */
2208 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2210 /* special case for 0 length values */
2212 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2216 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2225 DEBUG(5,("get_printer_dataex: copy done\n"));
2230 /****************************************************************************
2231 Internal routine for removing printerdata
2232 ***************************************************************************/
2234 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2236 return delete_printer_data( printer->info_2, key, value );
2239 /****************************************************************************
2240 Internal routine for storing printerdata
2241 ***************************************************************************/
2243 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2244 uint32 type, uint8 *data, int real_len )
2246 delete_printer_data( printer->info_2, key, value );
2248 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2251 /********************************************************************
2252 GetPrinterData on a printer server Handle.
2253 ********************************************************************/
2255 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2259 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2261 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2263 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2269 if (!StrCaseCmp(value, "BeepEnabled")) {
2271 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2273 SIVAL(*data, 0, 0x00);
2278 if (!StrCaseCmp(value, "EventLog")) {
2280 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2282 /* formally was 0x1b */
2283 SIVAL(*data, 0, 0x0);
2288 if (!StrCaseCmp(value, "NetPopup")) {
2290 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2292 SIVAL(*data, 0, 0x00);
2297 if (!StrCaseCmp(value, "MajorVersion")) {
2299 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2302 /* Windows NT 4.0 seems to not allow uploading of drivers
2303 to a server that reports 0x3 as the MajorVersion.
2304 need to investigate more how Win2k gets around this .
2307 if ( RA_WINNT == get_remote_arch() )
2316 if (!StrCaseCmp(value, "MinorVersion")) {
2318 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2326 * uint32 size = 0x114
2328 * uint32 minor = [0|1]
2329 * uint32 build = [2195|2600]
2330 * extra unicode string = e.g. "Service Pack 3"
2332 if (!StrCaseCmp(value, "OSVersion")) {
2336 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2338 ZERO_STRUCTP( *data );
2340 SIVAL(*data, 0, *needed); /* size */
2341 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2343 SIVAL(*data, 12, 2195); /* build */
2345 /* leave extra string empty */
2351 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2352 const char *string="C:\\PRINTERS";
2354 *needed = 2*(strlen(string)+1);
2355 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2357 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2359 /* it's done by hand ready to go on the wire */
2360 for (i=0; i<strlen(string); i++) {
2361 (*data)[2*i]=string[i];
2362 (*data)[2*i+1]='\0';
2367 if (!StrCaseCmp(value, "Architecture")) {
2368 const char *string="Windows NT x86";
2370 *needed = 2*(strlen(string)+1);
2371 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2373 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2374 for (i=0; i<strlen(string); i++) {
2375 (*data)[2*i]=string[i];
2376 (*data)[2*i+1]='\0';
2381 if (!StrCaseCmp(value, "DsPresent")) {
2383 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2385 SIVAL(*data, 0, 0x01);
2390 if (!StrCaseCmp(value, "DNSMachineName")) {
2393 if (!get_mydnsfullname(hostname))
2394 return WERR_BADFILE;
2396 *needed = 2*(strlen(hostname)+1);
2397 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2399 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2400 for (i=0; i<strlen(hostname); i++) {
2401 (*data)[2*i]=hostname[i];
2402 (*data)[2*i+1]='\0';
2408 return WERR_BADFILE;
2411 /********************************************************************
2412 * spoolss_getprinterdata
2413 ********************************************************************/
2415 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2417 POLICY_HND *handle = &q_u->handle;
2418 UNISTR2 *valuename = &q_u->valuename;
2419 uint32 in_size = q_u->size;
2420 uint32 *type = &r_u->type;
2421 uint32 *out_size = &r_u->size;
2422 uint8 **data = &r_u->data;
2423 uint32 *needed = &r_u->needed;
2426 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2427 NT_PRINTER_INFO_LEVEL *printer = NULL;
2431 * Reminder: when it's a string, the length is in BYTES
2432 * even if UNICODE is negociated.
2437 *out_size = in_size;
2439 /* in case of problem, return some default values */
2444 DEBUG(4,("_spoolss_getprinterdata\n"));
2447 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2448 status = WERR_BADFID;
2452 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2454 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2455 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2458 if ( !get_printer_snum(p,handle, &snum) ) {
2459 status = WERR_BADFID;
2463 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2464 if ( !W_ERROR_IS_OK(status) )
2467 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2469 if ( strequal(value, "ChangeId") ) {
2471 *needed = sizeof(uint32);
2472 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2473 status = WERR_NOMEM;
2476 SIVAL( *data, 0, printer->info_2->changeid );
2480 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2483 if (*needed > *out_size)
2484 status = WERR_MORE_DATA;
2487 if ( !W_ERROR_IS_OK(status) )
2489 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2491 /* reply this param doesn't exist */
2494 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2496 free_a_printer( &printer, 2 );
2505 /* cleanup & exit */
2508 free_a_printer( &printer, 2 );
2513 /*********************************************************
2514 Connect to the client machine.
2515 **********************************************************/
2517 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2518 struct in_addr *client_ip, const char *remote_machine)
2520 ZERO_STRUCTP(the_cli);
2522 if(cli_initialise(the_cli) == NULL) {
2523 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2527 if ( is_zero_ip(*client_ip) ) {
2528 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2529 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2530 cli_shutdown(the_cli);
2534 if (ismyip(the_cli->dest_ip)) {
2535 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2536 cli_shutdown(the_cli);
2541 the_cli->dest_ip.s_addr = client_ip->s_addr;
2542 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2543 inet_ntoa(*client_ip) ));
2546 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2547 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) ));
2548 cli_shutdown(the_cli);
2552 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2553 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2555 cli_shutdown(the_cli);
2559 the_cli->protocol = PROTOCOL_NT1;
2560 cli_setup_signing_state(the_cli, lp_client_signing());
2562 if (!cli_negprot(the_cli)) {
2563 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2564 cli_shutdown(the_cli);
2568 if (the_cli->protocol != PROTOCOL_NT1) {
2569 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2570 cli_shutdown(the_cli);
2575 * Do an anonymous session setup.
2578 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2579 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2580 cli_shutdown(the_cli);
2584 if (!(the_cli->sec_mode & 1)) {
2585 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2586 cli_shutdown(the_cli);
2590 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2591 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) ));
2592 cli_shutdown(the_cli);
2597 * Ok - we have an anonymous connection to the IPC$ share.
2598 * Now start the NT Domain stuff :-).
2601 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2602 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)));
2603 cli_nt_session_close(the_cli);
2604 cli_ulogoff(the_cli);
2605 cli_shutdown(the_cli);
2612 /***************************************************************************
2613 Connect to the client.
2614 ****************************************************************************/
2616 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2617 uint32 localprinter, uint32 type,
2618 POLICY_HND *handle, struct in_addr *client_ip)
2623 * If it's the first connection, contact the client
2624 * and connect to the IPC$ share anonymously
2626 if (smb_connections==0) {
2627 fstring unix_printer;
2629 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2631 ZERO_STRUCT(notify_cli);
2633 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2636 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2637 /* Tell the connections db we're now interested in printer
2638 * notify messages. */
2639 register_message_flags( True, FLAG_MSG_PRINTING );
2643 * Tell the specific printing tdb we want messages for this printer
2644 * by registering our PID.
2647 if (!print_notify_register_pid(snum))
2648 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2652 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2655 if (!W_ERROR_IS_OK(result))
2656 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2657 dos_errstr(result)));
2659 return (W_ERROR_IS_OK(result));
2662 /********************************************************************
2664 * ReplyFindFirstPrinterChangeNotifyEx
2666 * before replying OK: status=0 a rpc call is made to the workstation
2667 * asking ReplyOpenPrinter
2669 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2670 * called from api_spoolss_rffpcnex
2671 ********************************************************************/
2673 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2675 POLICY_HND *handle = &q_u->handle;
2676 uint32 flags = q_u->flags;
2677 uint32 options = q_u->options;
2678 UNISTR2 *localmachine = &q_u->localmachine;
2679 uint32 printerlocal = q_u->printerlocal;
2681 SPOOL_NOTIFY_OPTION *option = q_u->option;
2682 struct in_addr client_ip;
2684 /* store the notify value in the printer struct */
2686 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2689 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2693 Printer->notify.flags=flags;
2694 Printer->notify.options=options;
2695 Printer->notify.printerlocal=printerlocal;
2697 if (Printer->notify.option)
2698 free_spool_notify_option(&Printer->notify.option);
2700 Printer->notify.option=dup_spool_notify_option(option);
2702 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2703 sizeof(Printer->notify.localmachine)-1);
2705 /* Connect to the client machine and send a ReplyOpenPrinter */
2707 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2709 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2710 !get_printer_snum(p, handle, &snum) )
2713 client_ip.s_addr = inet_addr(p->conn->client_address);
2715 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2716 Printer->notify.printerlocal, 1,
2717 &Printer->notify.client_hnd, &client_ip))
2718 return WERR_SERVER_UNAVAILABLE;
2720 Printer->notify.client_connected=True;
2725 /*******************************************************************
2726 * fill a notify_info_data with the servername
2727 ********************************************************************/
2729 void spoolss_notify_server_name(int snum,
2730 SPOOL_NOTIFY_INFO_DATA *data,
2731 print_queue_struct *queue,
2732 NT_PRINTER_INFO_LEVEL *printer,
2733 TALLOC_CTX *mem_ctx)
2735 pstring temp_name, temp;
2738 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2740 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2742 data->notify_data.data.length = len;
2743 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2745 if (!data->notify_data.data.string) {
2746 data->notify_data.data.length = 0;
2750 memcpy(data->notify_data.data.string, temp, len);
2753 /*******************************************************************
2754 * fill a notify_info_data with the printername (not including the servername).
2755 ********************************************************************/
2757 void spoolss_notify_printer_name(int snum,
2758 SPOOL_NOTIFY_INFO_DATA *data,
2759 print_queue_struct *queue,
2760 NT_PRINTER_INFO_LEVEL *printer,
2761 TALLOC_CTX *mem_ctx)
2766 /* the notify name should not contain the \\server\ part */
2767 char *p = strrchr(printer->info_2->printername, '\\');
2770 p = printer->info_2->printername;
2775 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2777 data->notify_data.data.length = len;
2778 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2780 if (!data->notify_data.data.string) {
2781 data->notify_data.data.length = 0;
2785 memcpy(data->notify_data.data.string, temp, len);
2788 /*******************************************************************
2789 * fill a notify_info_data with the servicename
2790 ********************************************************************/
2792 void spoolss_notify_share_name(int snum,
2793 SPOOL_NOTIFY_INFO_DATA *data,
2794 print_queue_struct *queue,
2795 NT_PRINTER_INFO_LEVEL *printer,
2796 TALLOC_CTX *mem_ctx)
2801 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2803 data->notify_data.data.length = len;
2804 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2806 if (!data->notify_data.data.string) {
2807 data->notify_data.data.length = 0;
2811 memcpy(data->notify_data.data.string, temp, len);
2814 /*******************************************************************
2815 * fill a notify_info_data with the port name
2816 ********************************************************************/
2818 void spoolss_notify_port_name(int snum,
2819 SPOOL_NOTIFY_INFO_DATA *data,
2820 print_queue_struct *queue,
2821 NT_PRINTER_INFO_LEVEL *printer,
2822 TALLOC_CTX *mem_ctx)
2827 /* even if it's strange, that's consistant in all the code */
2829 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2831 data->notify_data.data.length = len;
2832 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2834 if (!data->notify_data.data.string) {
2835 data->notify_data.data.length = 0;
2839 memcpy(data->notify_data.data.string, temp, len);
2842 /*******************************************************************
2843 * fill a notify_info_data with the printername
2844 * but it doesn't exist, have to see what to do
2845 ********************************************************************/
2847 void spoolss_notify_driver_name(int snum,
2848 SPOOL_NOTIFY_INFO_DATA *data,
2849 print_queue_struct *queue,
2850 NT_PRINTER_INFO_LEVEL *printer,
2851 TALLOC_CTX *mem_ctx)
2856 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2858 data->notify_data.data.length = len;
2859 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2861 if (!data->notify_data.data.string) {
2862 data->notify_data.data.length = 0;
2866 memcpy(data->notify_data.data.string, temp, len);
2869 /*******************************************************************
2870 * fill a notify_info_data with the comment
2871 ********************************************************************/
2873 void spoolss_notify_comment(int snum,
2874 SPOOL_NOTIFY_INFO_DATA *data,
2875 print_queue_struct *queue,
2876 NT_PRINTER_INFO_LEVEL *printer,
2877 TALLOC_CTX *mem_ctx)
2882 if (*printer->info_2->comment == '\0')
2883 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2885 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2887 data->notify_data.data.length = len;
2888 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2890 if (!data->notify_data.data.string) {
2891 data->notify_data.data.length = 0;
2895 memcpy(data->notify_data.data.string, temp, len);
2898 /*******************************************************************
2899 * fill a notify_info_data with the comment
2900 * location = "Room 1, floor 2, building 3"
2901 ********************************************************************/
2903 void spoolss_notify_location(int snum,
2904 SPOOL_NOTIFY_INFO_DATA *data,
2905 print_queue_struct *queue,
2906 NT_PRINTER_INFO_LEVEL *printer,
2907 TALLOC_CTX *mem_ctx)
2912 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2914 data->notify_data.data.length = len;
2915 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2917 if (!data->notify_data.data.string) {
2918 data->notify_data.data.length = 0;
2922 memcpy(data->notify_data.data.string, temp, len);
2925 /*******************************************************************
2926 * fill a notify_info_data with the device mode
2927 * jfm:xxxx don't to it for know but that's a real problem !!!
2928 ********************************************************************/
2930 static void spoolss_notify_devmode(int snum,
2931 SPOOL_NOTIFY_INFO_DATA *data,
2932 print_queue_struct *queue,
2933 NT_PRINTER_INFO_LEVEL *printer,
2934 TALLOC_CTX *mem_ctx)
2938 /*******************************************************************
2939 * fill a notify_info_data with the separator file name
2940 ********************************************************************/
2942 void spoolss_notify_sepfile(int snum,
2943 SPOOL_NOTIFY_INFO_DATA *data,
2944 print_queue_struct *queue,
2945 NT_PRINTER_INFO_LEVEL *printer,
2946 TALLOC_CTX *mem_ctx)
2951 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2953 data->notify_data.data.length = len;
2954 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2956 if (!data->notify_data.data.string) {
2957 data->notify_data.data.length = 0;
2961 memcpy(data->notify_data.data.string, temp, len);
2964 /*******************************************************************
2965 * fill a notify_info_data with the print processor
2966 * jfm:xxxx return always winprint to indicate we don't do anything to it
2967 ********************************************************************/
2969 void spoolss_notify_print_processor(int snum,
2970 SPOOL_NOTIFY_INFO_DATA *data,
2971 print_queue_struct *queue,
2972 NT_PRINTER_INFO_LEVEL *printer,
2973 TALLOC_CTX *mem_ctx)
2978 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2980 data->notify_data.data.length = len;
2981 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2983 if (!data->notify_data.data.string) {
2984 data->notify_data.data.length = 0;
2988 memcpy(data->notify_data.data.string, temp, len);
2991 /*******************************************************************
2992 * fill a notify_info_data with the print processor options
2993 * jfm:xxxx send an empty string
2994 ********************************************************************/
2996 void spoolss_notify_parameters(int snum,
2997 SPOOL_NOTIFY_INFO_DATA *data,
2998 print_queue_struct *queue,
2999 NT_PRINTER_INFO_LEVEL *printer,
3000 TALLOC_CTX *mem_ctx)
3005 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3007 data->notify_data.data.length = len;
3008 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3010 if (!data->notify_data.data.string) {
3011 data->notify_data.data.length = 0;
3015 memcpy(data->notify_data.data.string, temp, len);
3018 /*******************************************************************
3019 * fill a notify_info_data with the data type
3020 * jfm:xxxx always send RAW as data type
3021 ********************************************************************/
3023 void spoolss_notify_datatype(int snum,
3024 SPOOL_NOTIFY_INFO_DATA *data,
3025 print_queue_struct *queue,
3026 NT_PRINTER_INFO_LEVEL *printer,
3027 TALLOC_CTX *mem_ctx)
3032 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3034 data->notify_data.data.length = len;
3035 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3037 if (!data->notify_data.data.string) {
3038 data->notify_data.data.length = 0;
3042 memcpy(data->notify_data.data.string, temp, len);
3045 /*******************************************************************
3046 * fill a notify_info_data with the security descriptor
3047 * jfm:xxxx send an null pointer to say no security desc
3048 * have to implement security before !
3049 ********************************************************************/
3051 static void spoolss_notify_security_desc(int snum,
3052 SPOOL_NOTIFY_INFO_DATA *data,
3053 print_queue_struct *queue,
3054 NT_PRINTER_INFO_LEVEL *printer,
3055 TALLOC_CTX *mem_ctx)
3057 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3058 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3061 /*******************************************************************
3062 * fill a notify_info_data with the attributes
3063 * jfm:xxxx a samba printer is always shared
3064 ********************************************************************/
3066 void spoolss_notify_attributes(int snum,
3067 SPOOL_NOTIFY_INFO_DATA *data,
3068 print_queue_struct *queue,
3069 NT_PRINTER_INFO_LEVEL *printer,
3070 TALLOC_CTX *mem_ctx)
3072 data->notify_data.value[0] = printer->info_2->attributes;
3073 data->notify_data.value[1] = 0;
3076 /*******************************************************************
3077 * fill a notify_info_data with the priority
3078 ********************************************************************/
3080 static void spoolss_notify_priority(int snum,
3081 SPOOL_NOTIFY_INFO_DATA *data,
3082 print_queue_struct *queue,
3083 NT_PRINTER_INFO_LEVEL *printer,
3084 TALLOC_CTX *mem_ctx)
3086 data->notify_data.value[0] = printer->info_2->priority;
3087 data->notify_data.value[1] = 0;
3090 /*******************************************************************
3091 * fill a notify_info_data with the default priority
3092 ********************************************************************/
3094 static void spoolss_notify_default_priority(int snum,
3095 SPOOL_NOTIFY_INFO_DATA *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 data->notify_data.value[0] = printer->info_2->default_priority;
3101 data->notify_data.value[1] = 0;
3104 /*******************************************************************
3105 * fill a notify_info_data with the start time
3106 ********************************************************************/
3108 static void spoolss_notify_start_time(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 data->notify_data.value[0] = printer->info_2->starttime;
3115 data->notify_data.value[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the until time
3120 ********************************************************************/
3122 static void spoolss_notify_until_time(int snum,
3123 SPOOL_NOTIFY_INFO_DATA *data,
3124 print_queue_struct *queue,
3125 NT_PRINTER_INFO_LEVEL *printer,
3126 TALLOC_CTX *mem_ctx)
3128 data->notify_data.value[0] = printer->info_2->untiltime;
3129 data->notify_data.value[1] = 0;
3132 /*******************************************************************
3133 * fill a notify_info_data with the status
3134 ********************************************************************/
3136 static void spoolss_notify_status(int snum,
3137 SPOOL_NOTIFY_INFO_DATA *data,
3138 print_queue_struct *queue,
3139 NT_PRINTER_INFO_LEVEL *printer,
3140 TALLOC_CTX *mem_ctx)
3142 print_status_struct status;
3144 print_queue_length(snum, &status);
3145 data->notify_data.value[0]=(uint32) status.status;
3146 data->notify_data.value[1] = 0;
3149 /*******************************************************************
3150 * fill a notify_info_data with the number of jobs queued
3151 ********************************************************************/
3153 void spoolss_notify_cjobs(int snum,
3154 SPOOL_NOTIFY_INFO_DATA *data,
3155 print_queue_struct *queue,
3156 NT_PRINTER_INFO_LEVEL *printer,
3157 TALLOC_CTX *mem_ctx)
3159 data->notify_data.value[0] = print_queue_length(snum, NULL);
3160 data->notify_data.value[1] = 0;
3163 /*******************************************************************
3164 * fill a notify_info_data with the average ppm
3165 ********************************************************************/
3167 static void spoolss_notify_average_ppm(int snum,
3168 SPOOL_NOTIFY_INFO_DATA *data,
3169 print_queue_struct *queue,
3170 NT_PRINTER_INFO_LEVEL *printer,
3171 TALLOC_CTX *mem_ctx)
3173 /* always respond 8 pages per minutes */
3174 /* a little hard ! */
3175 data->notify_data.value[0] = printer->info_2->averageppm;
3176 data->notify_data.value[1] = 0;
3179 /*******************************************************************
3180 * fill a notify_info_data with username
3181 ********************************************************************/
3183 static void spoolss_notify_username(int snum,
3184 SPOOL_NOTIFY_INFO_DATA *data,
3185 print_queue_struct *queue,
3186 NT_PRINTER_INFO_LEVEL *printer,
3187 TALLOC_CTX *mem_ctx)
3192 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3194 data->notify_data.data.length = len;
3195 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3197 if (!data->notify_data.data.string) {
3198 data->notify_data.data.length = 0;
3202 memcpy(data->notify_data.data.string, temp, len);
3205 /*******************************************************************
3206 * fill a notify_info_data with job status
3207 ********************************************************************/
3209 static void spoolss_notify_job_status(int snum,
3210 SPOOL_NOTIFY_INFO_DATA *data,
3211 print_queue_struct *queue,
3212 NT_PRINTER_INFO_LEVEL *printer,
3213 TALLOC_CTX *mem_ctx)
3215 data->notify_data.value[0]=nt_printj_status(queue->status);
3216 data->notify_data.value[1] = 0;
3219 /*******************************************************************
3220 * fill a notify_info_data with job name
3221 ********************************************************************/
3223 static void spoolss_notify_job_name(int snum,
3224 SPOOL_NOTIFY_INFO_DATA *data,
3225 print_queue_struct *queue,
3226 NT_PRINTER_INFO_LEVEL *printer,
3227 TALLOC_CTX *mem_ctx)
3232 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3234 data->notify_data.data.length = len;
3235 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3237 if (!data->notify_data.data.string) {
3238 data->notify_data.data.length = 0;
3242 memcpy(data->notify_data.data.string, temp, len);
3245 /*******************************************************************
3246 * fill a notify_info_data with job status
3247 ********************************************************************/
3249 static void spoolss_notify_job_status_string(int snum,
3250 SPOOL_NOTIFY_INFO_DATA *data,
3251 print_queue_struct *queue,
3252 NT_PRINTER_INFO_LEVEL *printer,
3253 TALLOC_CTX *mem_ctx)
3256 * Now we're returning job status codes we just return a "" here. JRA.
3263 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3266 switch (queue->status) {
3271 p = ""; /* NT provides the paused string */
3280 #endif /* NO LONGER NEEDED. */
3282 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3284 data->notify_data.data.length = len;
3285 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3287 if (!data->notify_data.data.string) {
3288 data->notify_data.data.length = 0;
3292 memcpy(data->notify_data.data.string, temp, len);
3295 /*******************************************************************
3296 * fill a notify_info_data with job time
3297 ********************************************************************/
3299 static void spoolss_notify_job_time(int snum,
3300 SPOOL_NOTIFY_INFO_DATA *data,
3301 print_queue_struct *queue,
3302 NT_PRINTER_INFO_LEVEL *printer,
3303 TALLOC_CTX *mem_ctx)
3305 data->notify_data.value[0]=0x0;
3306 data->notify_data.value[1]=0;
3309 /*******************************************************************
3310 * fill a notify_info_data with job size
3311 ********************************************************************/
3313 static void spoolss_notify_job_size(int snum,
3314 SPOOL_NOTIFY_INFO_DATA *data,
3315 print_queue_struct *queue,
3316 NT_PRINTER_INFO_LEVEL *printer,
3317 TALLOC_CTX *mem_ctx)
3319 data->notify_data.value[0]=queue->size;
3320 data->notify_data.value[1]=0;
3323 /*******************************************************************
3324 * fill a notify_info_data with page info
3325 ********************************************************************/
3326 static void spoolss_notify_total_pages(int snum,
3327 SPOOL_NOTIFY_INFO_DATA *data,
3328 print_queue_struct *queue,
3329 NT_PRINTER_INFO_LEVEL *printer,
3330 TALLOC_CTX *mem_ctx)
3332 data->notify_data.value[0]=queue->page_count;
3333 data->notify_data.value[1]=0;
3336 /*******************************************************************
3337 * fill a notify_info_data with pages printed info.
3338 ********************************************************************/
3339 static void spoolss_notify_pages_printed(int snum,
3340 SPOOL_NOTIFY_INFO_DATA *data,
3341 print_queue_struct *queue,
3342 NT_PRINTER_INFO_LEVEL *printer,
3343 TALLOC_CTX *mem_ctx)
3345 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3346 data->notify_data.value[1]=0;
3349 /*******************************************************************
3350 Fill a notify_info_data with job position.
3351 ********************************************************************/
3353 static void spoolss_notify_job_position(int snum,
3354 SPOOL_NOTIFY_INFO_DATA *data,
3355 print_queue_struct *queue,
3356 NT_PRINTER_INFO_LEVEL *printer,
3357 TALLOC_CTX *mem_ctx)
3359 data->notify_data.value[0]=queue->job;
3360 data->notify_data.value[1]=0;
3363 /*******************************************************************
3364 Fill a notify_info_data with submitted time.
3365 ********************************************************************/
3367 static void spoolss_notify_submitted_time(int snum,
3368 SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer,
3371 TALLOC_CTX *mem_ctx)
3378 t=gmtime(&queue->time);
3380 len = sizeof(SYSTEMTIME);
3382 data->notify_data.data.length = len;
3383 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3385 if (!data->notify_data.data.string) {
3386 data->notify_data.data.length = 0;
3390 make_systemtime(&st, t);
3393 * Systemtime must be linearized as a set of UINT16's.
3394 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3397 p = (char *)data->notify_data.data.string;
3398 SSVAL(p, 0, st.year);
3399 SSVAL(p, 2, st.month);
3400 SSVAL(p, 4, st.dayofweek);
3401 SSVAL(p, 6, st.day);
3402 SSVAL(p, 8, st.hour);
3403 SSVAL(p, 10, st.minute);
3404 SSVAL(p, 12, st.second);
3405 SSVAL(p, 14, st.milliseconds);
3408 struct s_notify_info_data_table
3414 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3415 print_queue_struct *queue,
3416 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3419 /* A table describing the various print notification constants and
3420 whether the notification data is a pointer to a variable sized
3421 buffer, a one value uint32 or a two value uint32. */
3423 static const struct s_notify_info_data_table notify_info_data_table[] =
3425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3452 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3453 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3454 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3455 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3456 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3457 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3458 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3463 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3476 /*******************************************************************
3477 Return the size of info_data structure.
3478 ********************************************************************/
3480 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3484 for (i = 0; i < sizeof(notify_info_data_table); i++)
3486 if ( (notify_info_data_table[i].type == type)
3487 && (notify_info_data_table[i].field == field) )
3489 switch(notify_info_data_table[i].size)
3491 case NOTIFY_ONE_VALUE:
3492 case NOTIFY_TWO_VALUE:
3497 /* The only pointer notify data I have seen on
3498 the wire is the submitted time and this has
3499 the notify size set to 4. -tpot */
3501 case NOTIFY_POINTER:
3504 case NOTIFY_SECDESC:
3510 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3515 /*******************************************************************
3516 Return the type of notify_info_data.
3517 ********************************************************************/
3519 static int type_of_notify_info_data(uint16 type, uint16 field)
3523 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3524 if (notify_info_data_table[i].type == type &&
3525 notify_info_data_table[i].field == field)
3526 return notify_info_data_table[i].size;
3532 /****************************************************************************
3533 ****************************************************************************/
3535 static int search_notify(uint16 type, uint16 field, int *value)
3539 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3540 if (notify_info_data_table[i].type == type &&
3541 notify_info_data_table[i].field == field &&
3542 notify_info_data_table[i].fn != NULL) {
3551 /****************************************************************************
3552 ****************************************************************************/
3554 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3556 info_data->type = type;
3557 info_data->field = field;
3558 info_data->reserved = 0;
3560 info_data->size = size_of_notify_info_data(type, field);
3561 info_data->enc_type = type_of_notify_info_data(type, field);
3568 /*******************************************************************
3570 * fill a notify_info struct with info asked
3572 ********************************************************************/
3574 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3575 snum, SPOOL_NOTIFY_OPTION_TYPE
3576 *option_type, uint32 id,
3577 TALLOC_CTX *mem_ctx)
3583 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3584 NT_PRINTER_INFO_LEVEL *printer = NULL;
3585 print_queue_struct *queue=NULL;
3587 type=option_type->type;
3589 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3590 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3591 option_type->count, lp_servicename(snum)));
3593 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3596 for(field_num=0; field_num<option_type->count; field_num++) {
3597 field = option_type->fields[field_num];
3599 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3601 if (!search_notify(type, field, &j) )
3604 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3605 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3610 current_data = &info->data[info->count];
3612 construct_info_data(current_data, type, field, id);
3614 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3615 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3617 notify_info_data_table[j].fn(snum, current_data, queue,
3623 free_a_printer(&printer, 2);
3627 /*******************************************************************
3629 * fill a notify_info struct with info asked
3631 ********************************************************************/
3633 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3634 SPOOL_NOTIFY_INFO *info,
3635 NT_PRINTER_INFO_LEVEL *printer,
3636 int snum, SPOOL_NOTIFY_OPTION_TYPE
3637 *option_type, uint32 id,
3638 TALLOC_CTX *mem_ctx)
3644 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3646 DEBUG(4,("construct_notify_jobs_info\n"));
3648 type = option_type->type;
3650 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3651 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3652 option_type->count));
3654 for(field_num=0; field_num<option_type->count; field_num++) {
3655 field = option_type->fields[field_num];
3657 if (!search_notify(type, field, &j) )
3660 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3661 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3664 else info->data = tid;
3666 current_data=&(info->data[info->count]);
3668 construct_info_data(current_data, type, field, id);
3669 notify_info_data_table[j].fn(snum, current_data, queue,
3678 * JFM: The enumeration is not that simple, it's even non obvious.
3680 * let's take an example: I want to monitor the PRINTER SERVER for
3681 * the printer's name and the number of jobs currently queued.
3682 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3683 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3685 * I have 3 printers on the back of my server.
3687 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3690 * 1 printer 1 name 1
3691 * 2 printer 1 cjob 1
3692 * 3 printer 2 name 2
3693 * 4 printer 2 cjob 2
3694 * 5 printer 3 name 3
3695 * 6 printer 3 name 3
3697 * that's the print server case, the printer case is even worse.
3700 /*******************************************************************
3702 * enumerate all printers on the printserver
3703 * fill a notify_info struct with info asked
3705 ********************************************************************/
3707 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3708 SPOOL_NOTIFY_INFO *info,
3709 TALLOC_CTX *mem_ctx)
3712 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3713 int n_services=lp_numservices();
3715 SPOOL_NOTIFY_OPTION *option;
3716 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3718 DEBUG(4,("printserver_notify_info\n"));
3723 option=Printer->notify.option;
3728 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3729 sending a ffpcn() request first */
3734 for (i=0; i<option->count; i++) {
3735 option_type=&(option->ctr.type[i]);
3737 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3740 for (snum=0; snum<n_services; snum++)
3742 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3743 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3749 * Debugging information, don't delete.
3752 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3753 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3754 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3756 for (i=0; i<info->count; i++) {
3757 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3758 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3759 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3766 /*******************************************************************
3768 * fill a notify_info struct with info asked
3770 ********************************************************************/
3772 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3773 TALLOC_CTX *mem_ctx)
3776 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3779 SPOOL_NOTIFY_OPTION *option;
3780 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3782 print_queue_struct *queue=NULL;
3783 print_status_struct status;
3785 DEBUG(4,("printer_notify_info\n"));
3790 option=Printer->notify.option;
3796 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3797 sending a ffpcn() request first */
3802 get_printer_snum(p, hnd, &snum);
3804 for (i=0; i<option->count; i++) {
3805 option_type=&option->ctr.type[i];
3807 switch ( option_type->type ) {
3808 case PRINTER_NOTIFY_TYPE:
3809 if(construct_notify_printer_info(Printer, info, snum,
3815 case JOB_NOTIFY_TYPE: {
3816 NT_PRINTER_INFO_LEVEL *printer = NULL;
3818 count = print_queue_status(snum, &queue, &status);
3820 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3823 for (j=0; j<count; j++) {
3824 construct_notify_jobs_info(&queue[j], info,
3831 free_a_printer(&printer, 2);
3841 * Debugging information, don't delete.
3844 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3845 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3846 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3848 for (i=0; i<info->count; i++) {
3849 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3850 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3851 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3857 /********************************************************************
3859 ********************************************************************/
3861 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3863 POLICY_HND *handle = &q_u->handle;
3864 SPOOL_NOTIFY_INFO *info = &r_u->info;
3866 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3867 WERROR result = WERR_BADFID;
3869 /* we always have a NOTIFY_INFO struct */
3873 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3874 OUR_HANDLE(handle)));
3878 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3881 * We are now using the change value, and
3882 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3883 * I don't have a global notification system, I'm sending back all the
3884 * informations even when _NOTHING_ has changed.
3887 /* We need to keep track of the change value to send back in
3888 RRPCN replies otherwise our updates are ignored. */
3890 Printer->notify.fnpcn = True;
3892 if (Printer->notify.client_connected) {
3893 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3894 Printer->notify.change = q_u->change;
3897 /* just ignore the SPOOL_NOTIFY_OPTION */
3899 switch (Printer->printer_type) {
3900 case PRINTER_HANDLE_IS_PRINTSERVER:
3901 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3904 case PRINTER_HANDLE_IS_PRINTER:
3905 result = printer_notify_info(p, handle, info, p->mem_ctx);
3909 Printer->notify.fnpcn = False;
3915 /********************************************************************
3916 * construct_printer_info_0
3917 * fill a printer_info_0 struct
3918 ********************************************************************/
3920 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3924 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3925 counter_printer_0 *session_counter;
3926 uint32 global_counter;
3929 print_status_struct status;
3931 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3934 count = print_queue_length(snum, &status);
3936 /* check if we already have a counter for this printer */
3937 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3939 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3940 if (session_counter->snum == snum)
3944 /* it's the first time, add it to the list */
3945 if (session_counter==NULL) {
3946 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3947 free_a_printer(&ntprinter, 2);
3950 ZERO_STRUCTP(session_counter);
3951 session_counter->snum=snum;
3952 session_counter->counter=0;
3953 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3957 session_counter->counter++;
3960 * the global_counter should be stored in a TDB as it's common to all the clients
3961 * and should be zeroed on samba startup
3963 global_counter=session_counter->counter;
3965 pstrcpy(chaine,ntprinter->info_2->printername);
3967 init_unistr(&printer->printername, chaine);
3969 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3970 init_unistr(&printer->servername, chaine);
3972 printer->cjobs = count;
3973 printer->total_jobs = 0;
3974 printer->total_bytes = 0;
3976 setuptime = (time_t)ntprinter->info_2->setuptime;
3977 t=gmtime(&setuptime);
3979 printer->year = t->tm_year+1900;
3980 printer->month = t->tm_mon+1;
3981 printer->dayofweek = t->tm_wday;
3982 printer->day = t->tm_mday;
3983 printer->hour = t->tm_hour;
3984 printer->minute = t->tm_min;
3985 printer->second = t->tm_sec;
3986 printer->milliseconds = 0;
3988 printer->global_counter = global_counter;
3989 printer->total_pages = 0;
3991 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3992 printer->major_version = 0x0005; /* NT 5 */
3993 printer->build_version = 0x0893; /* build 2195 */
3995 printer->unknown7 = 0x1;
3996 printer->unknown8 = 0x0;
3997 printer->unknown9 = 0x0;
3998 printer->session_counter = session_counter->counter;
3999 printer->unknown11 = 0x0;
4000 printer->printer_errors = 0x0; /* number of print failure */
4001 printer->unknown13 = 0x0;
4002 printer->unknown14 = 0x1;
4003 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4004 printer->unknown16 = 0x0;
4005 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4006 printer->unknown18 = 0x0;
4007 printer->status = nt_printq_status(status.status);
4008 printer->unknown20 = 0x0;
4009 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4010 printer->unknown22 = 0x0;
4011 printer->unknown23 = 0x6; /* 6 ???*/
4012 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4013 printer->unknown25 = 0;
4014 printer->unknown26 = 0;
4015 printer->unknown27 = 0;
4016 printer->unknown28 = 0;
4017 printer->unknown29 = 0;
4019 free_a_printer(&ntprinter,2);
4023 /********************************************************************
4024 * construct_printer_info_1
4025 * fill a printer_info_1 struct
4026 ********************************************************************/
4027 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4031 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4033 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4036 printer->flags=flags;
4038 if (*ntprinter->info_2->comment == '\0') {
4039 init_unistr(&printer->comment, lp_comment(snum));
4040 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4041 ntprinter->info_2->drivername, lp_comment(snum));
4044 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4045 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4046 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4049 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4051 init_unistr(&printer->description, chaine);
4052 init_unistr(&printer->name, chaine2);
4054 free_a_printer(&ntprinter,2);
4059 /****************************************************************************
4060 Free a DEVMODE struct.
4061 ****************************************************************************/
4063 static void free_dev_mode(DEVICEMODE *dev)
4068 SAFE_FREE(dev->private);
4073 /****************************************************************************
4074 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4075 should be valid upon entry
4076 ****************************************************************************/
4078 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4080 if ( !devmode || !ntdevmode )
4083 init_unistr(&devmode->devicename, ntdevmode->devicename);
4085 init_unistr(&devmode->formname, ntdevmode->formname);
4087 devmode->specversion = ntdevmode->specversion;
4088 devmode->driverversion = ntdevmode->driverversion;
4089 devmode->size = ntdevmode->size;
4090 devmode->driverextra = ntdevmode->driverextra;
4091 devmode->fields = ntdevmode->fields;
4093 devmode->orientation = ntdevmode->orientation;
4094 devmode->papersize = ntdevmode->papersize;
4095 devmode->paperlength = ntdevmode->paperlength;
4096 devmode->paperwidth = ntdevmode->paperwidth;
4097 devmode->scale = ntdevmode->scale;
4098 devmode->copies = ntdevmode->copies;
4099 devmode->defaultsource = ntdevmode->defaultsource;
4100 devmode->printquality = ntdevmode->printquality;
4101 devmode->color = ntdevmode->color;
4102 devmode->duplex = ntdevmode->duplex;
4103 devmode->yresolution = ntdevmode->yresolution;
4104 devmode->ttoption = ntdevmode->ttoption;
4105 devmode->collate = ntdevmode->collate;
4106 devmode->icmmethod = ntdevmode->icmmethod;
4107 devmode->icmintent = ntdevmode->icmintent;
4108 devmode->mediatype = ntdevmode->mediatype;
4109 devmode->dithertype = ntdevmode->dithertype;
4111 if (ntdevmode->private != NULL) {
4112 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4119 /****************************************************************************
4120 Create a DEVMODE struct. Returns malloced memory.
4121 ****************************************************************************/
4123 DEVICEMODE *construct_dev_mode(int snum)
4125 NT_PRINTER_INFO_LEVEL *printer = NULL;
4126 DEVICEMODE *devmode = NULL;
4128 DEBUG(7,("construct_dev_mode\n"));
4130 DEBUGADD(8,("getting printer characteristics\n"));
4132 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4135 if ( !printer->info_2->devmode ) {
4136 DEBUG(5, ("BONG! There was no device mode!\n"));
4140 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4141 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4145 ZERO_STRUCTP(devmode);
4147 DEBUGADD(8,("loading DEVICEMODE\n"));
4149 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4150 free_dev_mode( devmode );
4155 free_a_printer(&printer,2);
4160 /********************************************************************
4161 * construct_printer_info_2
4162 * fill a printer_info_2 struct
4163 ********************************************************************/
4165 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4168 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4170 print_status_struct status;
4172 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4175 count = print_queue_length(snum, &status);
4177 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4178 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4179 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4180 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4181 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4183 if (*ntprinter->info_2->comment == '\0')
4184 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4186 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4188 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4189 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4190 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4191 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4192 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4194 printer->attributes = ntprinter->info_2->attributes;
4196 printer->priority = ntprinter->info_2->priority; /* priority */
4197 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4198 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4199 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4200 printer->status = nt_printq_status(status.status); /* status */
4201 printer->cjobs = count; /* jobs */
4202 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4204 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4205 DEBUG(8, ("Returning NULL Devicemode!\n"));
4208 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4209 /* steal the printer info sec_desc structure. [badly done]. */
4210 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4211 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4212 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4213 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4216 printer->secdesc = NULL;
4219 free_a_printer(&ntprinter, 2);
4223 /********************************************************************
4224 * construct_printer_info_3
4225 * fill a printer_info_3 struct
4226 ********************************************************************/
4228 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4230 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4231 PRINTER_INFO_3 *printer = NULL;
4233 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4237 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4238 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4242 ZERO_STRUCTP(printer);
4244 printer->flags = 4; /* These are the components of the SD we are returning. */
4245 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4246 /* steal the printer info sec_desc structure. [badly done]. */
4247 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4251 * Set the flags for the components we are returning.
4254 if (printer->secdesc->owner_sid)
4255 printer->flags |= OWNER_SECURITY_INFORMATION;
4257 if (printer->secdesc->grp_sid)
4258 printer->flags |= GROUP_SECURITY_INFORMATION;
4260 if (printer->secdesc->dacl)
4261 printer->flags |= DACL_SECURITY_INFORMATION;
4263 if (printer->secdesc->sacl)
4264 printer->flags |= SACL_SECURITY_INFORMATION;
4267 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4268 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4269 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4272 free_a_printer(&ntprinter, 2);
4274 *pp_printer = printer;
4278 /********************************************************************
4279 * construct_printer_info_4
4280 * fill a printer_info_4 struct
4281 ********************************************************************/
4283 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4285 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4287 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4290 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4291 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4292 printer->attributes = ntprinter->info_2->attributes;
4294 free_a_printer(&ntprinter, 2);
4298 /********************************************************************
4299 * construct_printer_info_5
4300 * fill a printer_info_5 struct
4301 ********************************************************************/
4303 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4305 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4307 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4310 init_unistr(&printer->printername, ntprinter->info_2->printername);
4311 init_unistr(&printer->portname, ntprinter->info_2->portname);
4312 printer->attributes = ntprinter->info_2->attributes;
4314 /* these two are not used by NT+ according to MSDN */
4316 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4317 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4319 free_a_printer(&ntprinter, 2);
4324 /********************************************************************
4325 * construct_printer_info_7
4326 * fill a printer_info_7 struct
4327 ********************************************************************/
4329 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4331 char *guid_str = NULL;
4334 if (is_printer_published(print_hnd, snum, &guid)) {
4335 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4336 strupper_m(guid_str);
4337 init_unistr(&printer->guid, guid_str);
4338 printer->action = SPOOL_DS_PUBLISH;
4340 init_unistr(&printer->guid, "");
4341 printer->action = SPOOL_DS_UNPUBLISH;
4347 /********************************************************************
4348 Spoolss_enumprinters.
4349 ********************************************************************/
4351 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4355 int n_services=lp_numservices();
4356 PRINTER_INFO_1 *tp, *printers=NULL;
4357 PRINTER_INFO_1 current_prt;
4359 DEBUG(4,("enum_all_printers_info_1\n"));
4361 for (snum=0; snum<n_services; snum++) {
4362 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4363 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4365 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4366 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4367 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4368 SAFE_FREE(printers);
4373 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4375 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4381 /* check the required size. */
4382 for (i=0; i<*returned; i++)
4383 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4385 if (!alloc_buffer_size(buffer, *needed))
4386 return WERR_INSUFFICIENT_BUFFER;
4388 /* fill the buffer with the structures */
4389 for (i=0; i<*returned; i++)
4390 smb_io_printer_info_1("", buffer, &printers[i], 0);
4393 SAFE_FREE(printers);
4395 if (*needed > offered) {
4397 return WERR_INSUFFICIENT_BUFFER;
4403 /********************************************************************
4404 enum_all_printers_info_1_local.
4405 *********************************************************************/
4407 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4409 DEBUG(4,("enum_all_printers_info_1_local\n"));
4411 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4414 /********************************************************************
4415 enum_all_printers_info_1_name.
4416 *********************************************************************/
4418 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4422 DEBUG(4,("enum_all_printers_info_1_name\n"));
4424 if ((name[0] == '\\') && (name[1] == '\\'))
4427 if (is_myname_or_ipaddr(s)) {
4428 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4431 return WERR_INVALID_NAME;
4434 /********************************************************************
4435 enum_all_printers_info_1_remote.
4436 *********************************************************************/
4438 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4440 PRINTER_INFO_1 *printer;
4441 fstring printername;
4444 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4446 /* JFM: currently it's more a place holder than anything else.
4447 * In the spooler world there is a notion of server registration.
4448 * the print servers are registring (sp ?) on the PDC (in the same domain)
4450 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4453 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4458 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4459 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4460 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4462 init_unistr(&printer->description, desc);
4463 init_unistr(&printer->name, printername);
4464 init_unistr(&printer->comment, comment);
4465 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4467 /* check the required size. */
4468 *needed += spoolss_size_printer_info_1(printer);
4470 if (!alloc_buffer_size(buffer, *needed)) {
4472 return WERR_INSUFFICIENT_BUFFER;
4475 /* fill the buffer with the structures */
4476 smb_io_printer_info_1("", buffer, printer, 0);
4481 if (*needed > offered) {
4483 return WERR_INSUFFICIENT_BUFFER;
4489 /********************************************************************
4490 enum_all_printers_info_1_network.
4491 *********************************************************************/
4493 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4497 DEBUG(4,("enum_all_printers_info_1_network\n"));
4499 /* If we respond to a enum_printers level 1 on our name with flags
4500 set to PRINTER_ENUM_REMOTE with a list of printers then these
4501 printers incorrectly appear in the APW browse list.
4502 Specifically the printers for the server appear at the workgroup
4503 level where all the other servers in the domain are
4504 listed. Windows responds to this call with a
4505 WERR_CAN_NOT_COMPLETE so we should do the same. */
4507 if (name[0] == '\\' && name[1] == '\\')
4510 if (is_myname_or_ipaddr(s))
4511 return WERR_CAN_NOT_COMPLETE;
4513 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4516 /********************************************************************
4517 * api_spoolss_enumprinters
4519 * called from api_spoolss_enumprinters (see this to understand)
4520 ********************************************************************/
4522 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4526 int n_services=lp_numservices();
4527 PRINTER_INFO_2 *tp, *printers=NULL;
4528 PRINTER_INFO_2 current_prt;
4530 for (snum=0; snum<n_services; snum++) {
4531 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4532 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4534 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4535 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4536 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4537 SAFE_FREE(printers);
4542 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4543 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4549 /* check the required size. */
4550 for (i=0; i<*returned; i++)
4551 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4553 if (!alloc_buffer_size(buffer, *needed)) {
4554 for (i=0; i<*returned; i++) {
4555 free_devmode(printers[i].devmode);
4557 SAFE_FREE(printers);
4558 return WERR_INSUFFICIENT_BUFFER;
4561 /* fill the buffer with the structures */
4562 for (i=0; i<*returned; i++)
4563 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4566 for (i=0; i<*returned; i++) {
4567 free_devmode(printers[i].devmode);
4569 SAFE_FREE(printers);
4571 if (*needed > offered) {
4573 return WERR_INSUFFICIENT_BUFFER;
4579 /********************************************************************
4580 * handle enumeration of printers at level 1
4581 ********************************************************************/
4583 static WERROR enumprinters_level1( uint32 flags, fstring name,
4584 NEW_BUFFER *buffer, uint32 offered,
4585 uint32 *needed, uint32 *returned)
4587 /* Not all the flags are equals */
4589 if (flags & PRINTER_ENUM_LOCAL)
4590 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4592 if (flags & PRINTER_ENUM_NAME)
4593 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4595 if (flags & PRINTER_ENUM_REMOTE)
4596 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4598 if (flags & PRINTER_ENUM_NETWORK)
4599 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4601 return WERR_OK; /* NT4sp5 does that */
4604 /********************************************************************
4605 * handle enumeration of printers at level 2
4606 ********************************************************************/
4608 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4609 NEW_BUFFER *buffer, uint32 offered,
4610 uint32 *needed, uint32 *returned)
4612 char *s = servername;
4614 if (flags & PRINTER_ENUM_LOCAL) {
4615 return enum_all_printers_info_2(buffer, offered, needed, returned);
4618 if (flags & PRINTER_ENUM_NAME) {
4619 if ((servername[0] == '\\') && (servername[1] == '\\'))
4621 if (is_myname_or_ipaddr(s))
4622 return enum_all_printers_info_2(buffer, offered, needed, returned);
4624 return WERR_INVALID_NAME;
4627 if (flags & PRINTER_ENUM_REMOTE)
4628 return WERR_UNKNOWN_LEVEL;
4633 /********************************************************************
4634 * handle enumeration of printers at level 5
4635 ********************************************************************/
4637 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4638 NEW_BUFFER *buffer, uint32 offered,
4639 uint32 *needed, uint32 *returned)
4641 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4645 /********************************************************************
4646 * api_spoolss_enumprinters
4648 * called from api_spoolss_enumprinters (see this to understand)
4649 ********************************************************************/
4651 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4653 uint32 flags = q_u->flags;
4654 UNISTR2 *servername = &q_u->servername;
4655 uint32 level = q_u->level;
4656 NEW_BUFFER *buffer = NULL;
4657 uint32 offered = q_u->offered;
4658 uint32 *needed = &r_u->needed;
4659 uint32 *returned = &r_u->returned;
4663 /* that's an [in out] buffer */
4664 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4665 buffer = r_u->buffer;
4667 DEBUG(4,("_spoolss_enumprinters\n"));
4674 * flags==PRINTER_ENUM_NAME
4675 * if name=="" then enumerates all printers
4676 * if name!="" then enumerate the printer
4677 * flags==PRINTER_ENUM_REMOTE
4678 * name is NULL, enumerate printers
4679 * Level 2: name!="" enumerates printers, name can't be NULL
4680 * Level 3: doesn't exist
4681 * Level 4: does a local registry lookup
4682 * Level 5: same as Level 2
4685 unistr2_to_ascii(name, servername, sizeof(name)-1);
4690 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4692 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4694 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4699 return WERR_UNKNOWN_LEVEL;
4702 /****************************************************************************
4703 ****************************************************************************/
4705 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4707 PRINTER_INFO_0 *printer=NULL;
4709 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4712 construct_printer_info_0(print_hnd, printer, snum);
4714 /* check the required size. */
4715 *needed += spoolss_size_printer_info_0(printer);
4717 if (!alloc_buffer_size(buffer, *needed)) {
4719 return WERR_INSUFFICIENT_BUFFER;
4722 /* fill the buffer with the structures */
4723 smb_io_printer_info_0("", buffer, printer, 0);
4728 if (*needed > offered) {
4729 return WERR_INSUFFICIENT_BUFFER;
4735 /****************************************************************************
4736 ****************************************************************************/
4738 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4740 PRINTER_INFO_1 *printer=NULL;
4742 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4745 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4747 /* check the required size. */
4748 *needed += spoolss_size_printer_info_1(printer);
4750 if (!alloc_buffer_size(buffer, *needed)) {
4752 return WERR_INSUFFICIENT_BUFFER;
4755 /* fill the buffer with the structures */
4756 smb_io_printer_info_1("", buffer, printer, 0);
4761 if (*needed > offered) {
4762 return WERR_INSUFFICIENT_BUFFER;
4768 /****************************************************************************
4769 ****************************************************************************/
4771 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4773 PRINTER_INFO_2 *printer=NULL;
4775 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4778 construct_printer_info_2(print_hnd, printer, snum);
4780 /* check the required size. */
4781 *needed += spoolss_size_printer_info_2(printer);
4783 if (!alloc_buffer_size(buffer, *needed)) {
4784 free_printer_info_2(printer);
4785 return WERR_INSUFFICIENT_BUFFER;
4788 /* fill the buffer with the structures */
4789 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4790 free_printer_info_2(printer);
4795 free_printer_info_2(printer);
4797 if (*needed > offered) {
4798 return WERR_INSUFFICIENT_BUFFER;
4804 /****************************************************************************
4805 ****************************************************************************/
4807 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4809 PRINTER_INFO_3 *printer=NULL;
4811 if (!construct_printer_info_3(print_hnd, &printer, snum))
4814 /* check the required size. */
4815 *needed += spoolss_size_printer_info_3(printer);
4817 if (!alloc_buffer_size(buffer, *needed)) {
4818 free_printer_info_3(printer);
4819 return WERR_INSUFFICIENT_BUFFER;
4822 /* fill the buffer with the structures */
4823 smb_io_printer_info_3("", buffer, printer, 0);
4826 free_printer_info_3(printer);
4828 if (*needed > offered) {
4829 return WERR_INSUFFICIENT_BUFFER;
4835 /****************************************************************************
4836 ****************************************************************************/
4838 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4840 PRINTER_INFO_4 *printer=NULL;
4842 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4845 if (!construct_printer_info_4(print_hnd, printer, snum))
4848 /* check the required size. */
4849 *needed += spoolss_size_printer_info_4(printer);
4851 if (!alloc_buffer_size(buffer, *needed)) {
4852 free_printer_info_4(printer);
4853 return WERR_INSUFFICIENT_BUFFER;
4856 /* fill the buffer with the structures */
4857 smb_io_printer_info_4("", buffer, printer, 0);
4860 free_printer_info_4(printer);
4862 if (*needed > offered) {
4863 return WERR_INSUFFICIENT_BUFFER;
4869 /****************************************************************************
4870 ****************************************************************************/
4872 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4874 PRINTER_INFO_5 *printer=NULL;
4876 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4879 if (!construct_printer_info_5(print_hnd, printer, snum))
4882 /* check the required size. */
4883 *needed += spoolss_size_printer_info_5(printer);
4885 if (!alloc_buffer_size(buffer, *needed)) {
4886 free_printer_info_5(printer);
4887 return WERR_INSUFFICIENT_BUFFER;
4890 /* fill the buffer with the structures */
4891 smb_io_printer_info_5("", buffer, printer, 0);
4894 free_printer_info_5(printer);
4896 if (*needed > offered) {
4897 return WERR_INSUFFICIENT_BUFFER;
4903 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4905 PRINTER_INFO_7 *printer=NULL;
4907 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4910 if (!construct_printer_info_7(print_hnd, printer, snum))
4913 /* check the required size. */
4914 *needed += spoolss_size_printer_info_7(printer);
4916 if (!alloc_buffer_size(buffer, *needed)) {
4917 free_printer_info_7(printer);
4918 return WERR_INSUFFICIENT_BUFFER;
4921 /* fill the buffer with the structures */
4922 smb_io_printer_info_7("", buffer, printer, 0);
4925 free_printer_info_7(printer);
4927 if (*needed > offered) {
4928 return WERR_INSUFFICIENT_BUFFER;
4934 /****************************************************************************
4935 ****************************************************************************/
4937 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4939 POLICY_HND *handle = &q_u->handle;
4940 uint32 level = q_u->level;
4941 NEW_BUFFER *buffer = NULL;
4942 uint32 offered = q_u->offered;
4943 uint32 *needed = &r_u->needed;
4944 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4948 /* that's an [in out] buffer */
4949 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4950 buffer = r_u->buffer;
4954 if (!get_printer_snum(p, handle, &snum))
4959 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4961 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4963 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4965 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4967 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4969 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4971 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4973 return WERR_UNKNOWN_LEVEL;
4976 /********************************************************************
4977 * fill a DRIVER_INFO_1 struct
4978 ********************************************************************/
4980 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4982 init_unistr( &info->name, driver.info_3->name);
4985 /********************************************************************
4986 * construct_printer_driver_info_1
4987 ********************************************************************/
4989 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4991 NT_PRINTER_INFO_LEVEL *printer = NULL;
4992 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4994 ZERO_STRUCT(driver);
4996 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4997 return WERR_INVALID_PRINTER_NAME;
4999 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5000 return WERR_UNKNOWN_PRINTER_DRIVER;
5002 fill_printer_driver_info_1(info, driver, servername, architecture);
5004 free_a_printer(&printer,2);
5009 /********************************************************************
5010 * construct_printer_driver_info_2
5011 * fill a printer_info_2 struct
5012 ********************************************************************/
5014 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5018 info->version=driver.info_3->cversion;
5020 init_unistr( &info->name, driver.info_3->name );
5021 init_unistr( &info->architecture, driver.info_3->environment );
5024 if (strlen(driver.info_3->driverpath)) {
5025 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5026 init_unistr( &info->driverpath, temp );
5028 init_unistr( &info->driverpath, "" );
5030 if (strlen(driver.info_3->datafile)) {
5031 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5032 init_unistr( &info->datafile, temp );
5034 init_unistr( &info->datafile, "" );
5036 if (strlen(driver.info_3->configfile)) {
5037 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5038 init_unistr( &info->configfile, temp );
5040 init_unistr( &info->configfile, "" );
5043 /********************************************************************
5044 * construct_printer_driver_info_2
5045 * fill a printer_info_2 struct
5046 ********************************************************************/
5048 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5050 NT_PRINTER_INFO_LEVEL *printer = NULL;
5051 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5053 ZERO_STRUCT(printer);
5054 ZERO_STRUCT(driver);
5056 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5057 return WERR_INVALID_PRINTER_NAME;
5059 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5060 return WERR_UNKNOWN_PRINTER_DRIVER;
5062 fill_printer_driver_info_2(info, driver, servername);
5064 free_a_printer(&printer,2);
5069 /********************************************************************
5070 * copy a strings array and convert to UNICODE
5072 * convert an array of ascii string to a UNICODE string
5073 ********************************************************************/
5075 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5083 DEBUG(6,("init_unistr_array\n"));
5094 v = ""; /* hack to handle null lists */
5097 /* hack to allow this to be used in places other than when generating
5098 the list of dependent files */
5101 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5105 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5107 /* add one extra unit16 for the second terminating NULL */
5109 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5110 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5118 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5123 /* special case for ""; we need to add both NULL's here */
5125 (*uni_array)[j++]=0x0000;
5126 (*uni_array)[j]=0x0000;
5129 DEBUGADD(6,("last one:done\n"));
5131 /* return size of array in uint16's */
5136 /********************************************************************
5137 * construct_printer_info_3
5138 * fill a printer_info_3 struct
5139 ********************************************************************/
5141 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5147 info->version=driver.info_3->cversion;
5149 init_unistr( &info->name, driver.info_3->name );
5150 init_unistr( &info->architecture, driver.info_3->environment );
5152 if (strlen(driver.info_3->driverpath)) {
5153 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5154 init_unistr( &info->driverpath, temp );
5156 init_unistr( &info->driverpath, "" );
5158 if (strlen(driver.info_3->datafile)) {
5159 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5160 init_unistr( &info->datafile, temp );
5162 init_unistr( &info->datafile, "" );
5164 if (strlen(driver.info_3->configfile)) {
5165 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5166 init_unistr( &info->configfile, temp );
5168 init_unistr( &info->configfile, "" );
5170 if (strlen(driver.info_3->helpfile)) {
5171 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5172 init_unistr( &info->helpfile, temp );
5174 init_unistr( &info->helpfile, "" );
5176 init_unistr( &info->monitorname, driver.info_3->monitorname );
5177 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5179 info->dependentfiles=NULL;
5180 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5183 /********************************************************************
5184 * construct_printer_info_3
5185 * fill a printer_info_3 struct
5186 ********************************************************************/
5188 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5190 NT_PRINTER_INFO_LEVEL *printer = NULL;
5191 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5193 ZERO_STRUCT(driver);
5195 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5196 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5197 if (!W_ERROR_IS_OK(status))
5198 return WERR_INVALID_PRINTER_NAME;
5200 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5201 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5206 * I put this code in during testing. Helpful when commenting out the
5207 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5208 * as win2k always queries the driver using an infor level of 6.
5209 * I've left it in (but ifdef'd out) because I'll probably
5210 * use it in experimentation again in the future. --jerry 22/01/2002
5213 if (!W_ERROR_IS_OK(status)) {
5215 * Is this a W2k client ?
5218 /* Yes - try again with a WinNT driver. */
5220 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5221 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5225 if (!W_ERROR_IS_OK(status)) {
5226 free_a_printer(&printer,2);
5227 return WERR_UNKNOWN_PRINTER_DRIVER;
5235 fill_printer_driver_info_3(info, driver, servername);
5237 free_a_printer(&printer,2);
5242 /********************************************************************
5243 * construct_printer_info_6
5244 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5245 ********************************************************************/
5247 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5253 memset(&nullstr, '\0', sizeof(fstring));
5255 info->version=driver.info_3->cversion;
5257 init_unistr( &info->name, driver.info_3->name );
5258 init_unistr( &info->architecture, driver.info_3->environment );
5260 if (strlen(driver.info_3->driverpath)) {
5261 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5262 init_unistr( &info->driverpath, temp );
5264 init_unistr( &info->driverpath, "" );
5266 if (strlen(driver.info_3->datafile)) {
5267 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5268 init_unistr( &info->datafile, temp );
5270 init_unistr( &info->datafile, "" );
5272 if (strlen(driver.info_3->configfile)) {
5273 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5274 init_unistr( &info->configfile, temp );
5276 init_unistr( &info->configfile, "" );
5278 if (strlen(driver.info_3->helpfile)) {
5279 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5280 init_unistr( &info->helpfile, temp );
5282 init_unistr( &info->helpfile, "" );
5284 init_unistr( &info->monitorname, driver.info_3->monitorname );
5285 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5287 info->dependentfiles = NULL;
5288 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5290 info->previousdrivernames=NULL;
5291 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5293 info->driver_date.low=0;
5294 info->driver_date.high=0;
5297 info->driver_version_low=0;
5298 info->driver_version_high=0;
5300 init_unistr( &info->mfgname, "");
5301 init_unistr( &info->oem_url, "");
5302 init_unistr( &info->hardware_id, "");
5303 init_unistr( &info->provider, "");
5306 /********************************************************************
5307 * construct_printer_info_6
5308 * fill a printer_info_6 struct
5309 ********************************************************************/
5311 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5312 fstring servername, fstring architecture, uint32 version)
5314 NT_PRINTER_INFO_LEVEL *printer = NULL;
5315 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5318 ZERO_STRUCT(driver);
5320 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5322 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5324 if (!W_ERROR_IS_OK(status))
5325 return WERR_INVALID_PRINTER_NAME;
5327 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5329 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5331 if (!W_ERROR_IS_OK(status))
5334 * Is this a W2k client ?
5338 free_a_printer(&printer,2);
5339 return WERR_UNKNOWN_PRINTER_DRIVER;
5342 /* Yes - try again with a WinNT driver. */
5344 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5345 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5346 if (!W_ERROR_IS_OK(status)) {
5347 free_a_printer(&printer,2);
5348 return WERR_UNKNOWN_PRINTER_DRIVER;
5352 fill_printer_driver_info_6(info, driver, servername);
5354 free_a_printer(&printer,2);
5355 free_a_printer_driver(driver, 3);
5360 /****************************************************************************
5361 ****************************************************************************/
5363 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5365 SAFE_FREE(info->dependentfiles);
5368 /****************************************************************************
5369 ****************************************************************************/
5371 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5373 SAFE_FREE(info->dependentfiles);
5377 /****************************************************************************
5378 ****************************************************************************/
5380 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5382 DRIVER_INFO_1 *info=NULL;
5385 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5388 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5389 if (!W_ERROR_IS_OK(status)) {
5394 /* check the required size. */
5395 *needed += spoolss_size_printer_driver_info_1(info);
5397 if (!alloc_buffer_size(buffer, *needed)) {
5399 return WERR_INSUFFICIENT_BUFFER;
5402 /* fill the buffer with the structures */
5403 smb_io_printer_driver_info_1("", buffer, info, 0);
5408 if (*needed > offered)
5409 return WERR_INSUFFICIENT_BUFFER;
5414 /****************************************************************************
5415 ****************************************************************************/
5417 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5419 DRIVER_INFO_2 *info=NULL;
5422 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5425 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5426 if (!W_ERROR_IS_OK(status)) {
5431 /* check the required size. */
5432 *needed += spoolss_size_printer_driver_info_2(info);
5434 if (!alloc_buffer_size(buffer, *needed)) {
5436 return WERR_INSUFFICIENT_BUFFER;
5439 /* fill the buffer with the structures */
5440 smb_io_printer_driver_info_2("", buffer, info, 0);
5445 if (*needed > offered)
5446 return WERR_INSUFFICIENT_BUFFER;
5451 /****************************************************************************
5452 ****************************************************************************/
5454 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5461 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5462 if (!W_ERROR_IS_OK(status)) {
5466 /* check the required size. */
5467 *needed += spoolss_size_printer_driver_info_3(&info);
5469 if (!alloc_buffer_size(buffer, *needed)) {
5470 free_printer_driver_info_3(&info);
5471 return WERR_INSUFFICIENT_BUFFER;
5474 /* fill the buffer with the structures */
5475 smb_io_printer_driver_info_3("", buffer, &info, 0);
5477 free_printer_driver_info_3(&info);
5479 if (*needed > offered)
5480 return WERR_INSUFFICIENT_BUFFER;
5485 /****************************************************************************
5486 ****************************************************************************/
5488 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5495 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5496 if (!W_ERROR_IS_OK(status)) {
5500 /* check the required size. */
5501 *needed += spoolss_size_printer_driver_info_6(&info);
5503 if (!alloc_buffer_size(buffer, *needed)) {
5504 free_printer_driver_info_6(&info);
5505 return WERR_INSUFFICIENT_BUFFER;
5508 /* fill the buffer with the structures */
5509 smb_io_printer_driver_info_6("", buffer, &info, 0);
5511 free_printer_driver_info_6(&info);
5513 if (*needed > offered)
5514 return WERR_INSUFFICIENT_BUFFER;
5519 /****************************************************************************
5520 ****************************************************************************/
5522 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5524 POLICY_HND *handle = &q_u->handle;
5525 UNISTR2 *uni_arch = &q_u->architecture;
5526 uint32 level = q_u->level;
5527 uint32 clientmajorversion = q_u->clientmajorversion;
5528 NEW_BUFFER *buffer = NULL;
5529 uint32 offered = q_u->offered;
5530 uint32 *needed = &r_u->needed;
5531 uint32 *servermajorversion = &r_u->servermajorversion;
5532 uint32 *serverminorversion = &r_u->serverminorversion;
5535 fstring architecture;
5538 /* that's an [in out] buffer */
5539 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5540 buffer = r_u->buffer;
5542 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5545 *servermajorversion = 0;
5546 *serverminorversion = 0;
5548 fstrcpy(servername, get_called_name());
5549 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5551 if (!get_printer_snum(p, handle, &snum))
5556 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5558 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5560 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5562 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5565 return WERR_UNKNOWN_LEVEL;
5568 /****************************************************************************
5569 ****************************************************************************/
5571 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5573 POLICY_HND *handle = &q_u->handle;
5575 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5578 DEBUG(3,("Error in startpageprinter printer handle\n"));
5582 Printer->page_started=True;
5586 /****************************************************************************
5587 ****************************************************************************/
5589 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5591 POLICY_HND *handle = &q_u->handle;
5594 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5597 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5601 if (!get_printer_snum(p, handle, &snum))
5604 Printer->page_started=False;
5605 print_job_endpage(snum, Printer->jobid);
5610 /********************************************************************
5611 * api_spoolss_getprinter
5612 * called from the spoolss dispatcher
5614 ********************************************************************/
5616 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5618 POLICY_HND *handle = &q_u->handle;
5619 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5620 uint32 *jobid = &r_u->jobid;
5622 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5626 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5627 struct current_user user;
5630 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5634 get_current_user(&user, p);
5637 * a nice thing with NT is it doesn't listen to what you tell it.
5638 * when asked to send _only_ RAW datas, it tries to send datas
5641 * So I add checks like in NT Server ...
5644 if (info_1->p_datatype != 0) {
5645 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5646 if (strcmp(datatype, "RAW") != 0) {
5648 return WERR_INVALID_DATATYPE;
5652 /* get the share number of the printer */
5653 if (!get_printer_snum(p, handle, &snum)) {
5657 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5659 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5661 /* An error occured in print_job_start() so return an appropriate
5664 if (Printer->jobid == -1) {
5665 return map_werror_from_unix(errno);
5668 Printer->document_started=True;
5669 (*jobid) = Printer->jobid;
5674 /********************************************************************
5675 * api_spoolss_getprinter
5676 * called from the spoolss dispatcher
5678 ********************************************************************/
5680 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5682 POLICY_HND *handle = &q_u->handle;
5684 return _spoolss_enddocprinter_internal(p, handle);
5687 /****************************************************************************
5688 ****************************************************************************/
5690 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5692 POLICY_HND *handle = &q_u->handle;
5693 uint32 buffer_size = q_u->buffer_size;
5694 uint8 *buffer = q_u->buffer;
5695 uint32 *buffer_written = &q_u->buffer_size2;
5697 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5700 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5701 r_u->buffer_written = q_u->buffer_size2;
5705 if (!get_printer_snum(p, handle, &snum))
5708 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5709 if (*buffer_written == -1) {
5710 r_u->buffer_written = 0;
5711 if (errno == ENOSPC)
5712 return WERR_NO_SPOOL_SPACE;
5714 return WERR_ACCESS_DENIED;
5717 r_u->buffer_written = q_u->buffer_size2;
5722 /********************************************************************
5723 * api_spoolss_getprinter
5724 * called from the spoolss dispatcher
5726 ********************************************************************/
5728 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5731 struct current_user user;
5733 WERROR errcode = WERR_BADFUNC;
5734 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5736 get_current_user(&user, p);
5739 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5743 if (!get_printer_snum(p, handle, &snum))
5747 case PRINTER_CONTROL_PAUSE:
5748 if (print_queue_pause(&user, snum, &errcode)) {
5752 case PRINTER_CONTROL_RESUME:
5753 case PRINTER_CONTROL_UNPAUSE:
5754 if (print_queue_resume(&user, snum, &errcode)) {
5758 case PRINTER_CONTROL_PURGE:
5759 if (print_queue_purge(&user, snum, &errcode)) {
5764 return WERR_UNKNOWN_LEVEL;
5770 /********************************************************************
5771 * api_spoolss_abortprinter
5772 * From MSDN: "Deletes printer's spool file if printer is configured
5774 ********************************************************************/
5776 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5778 POLICY_HND *handle = &q_u->handle;
5779 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5781 struct current_user user;
5782 WERROR errcode = WERR_OK;
5785 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5789 if (!get_printer_snum(p, handle, &snum))
5792 get_current_user( &user, p );
5794 print_job_delete( &user, snum, Printer->jobid, &errcode );
5799 /********************************************************************
5800 * called by spoolss_api_setprinter
5801 * when updating a printer description
5802 ********************************************************************/
5804 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5805 const SPOOL_PRINTER_INFO_LEVEL *info,
5806 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5808 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5809 struct current_user user;
5813 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5815 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5816 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5817 OUR_HANDLE(handle)));
5819 result = WERR_BADFID;
5823 /* NT seems to like setting the security descriptor even though
5824 nothing may have actually changed. This causes annoying
5825 dialog boxes when the user doesn't have permission to change
5826 the security descriptor. */
5828 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5830 if (DEBUGLEVEL >= 10) {
5834 the_acl = old_secdesc_ctr->sec->dacl;
5835 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5836 PRINTERNAME(snum), the_acl->num_aces));
5838 for (i = 0; i < the_acl->num_aces; i++) {
5841 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5843 DEBUG(10, ("%s 0x%08x\n", sid_str,
5844 the_acl->ace[i].info.mask));
5847 the_acl = secdesc_ctr->sec->dacl;
5850 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5851 PRINTERNAME(snum), the_acl->num_aces));
5853 for (i = 0; i < the_acl->num_aces; i++) {
5856 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5858 DEBUG(10, ("%s 0x%08x\n", sid_str,
5859 the_acl->ace[i].info.mask));
5862 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5866 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5868 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5873 /* Work out which user is performing the operation */
5875 get_current_user(&user, p);
5877 /* Check the user has permissions to change the security
5878 descriptor. By experimentation with two NT machines, the user
5879 requires Full Access to the printer to change security
5882 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5883 result = WERR_ACCESS_DENIED;
5887 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5894 /********************************************************************
5895 Do Samba sanity checks on a printer info struct.
5896 this has changed purpose: it now "canonicalises" printer
5897 info from a client rather than just checking it is correct
5898 ********************************************************************/
5900 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5902 fstring printername;
5905 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5906 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5908 /* we force some elements to "correct" values */
5909 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5910 fstrcpy(info->sharename, lp_servicename(snum));
5912 /* make sure printername is in \\server\printername format */
5914 fstrcpy( printername, info->printername );
5916 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5917 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5921 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5922 get_called_name(), p );
5924 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5930 /****************************************************************************
5931 ****************************************************************************/
5933 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5935 extern userdom_struct current_user_info;
5936 char *cmd = lp_addprinter_cmd();
5942 fstring remote_machine = "%m";
5944 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5946 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5947 cmd, printer->info_2->printername, printer->info_2->sharename,
5948 printer->info_2->portname, printer->info_2->drivername,
5949 printer->info_2->location, printer->info_2->comment, remote_machine);
5951 DEBUG(10,("Running [%s]\n", command));
5952 ret = smbrun(command, &fd);
5953 DEBUGADD(10,("returned [%d]\n", ret));
5962 /* Get lines and convert them back to dos-codepage */
5963 qlines = fd_lines_load(fd, &numlines);
5964 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5968 /* Set the portname to what the script says the portname should be. */
5969 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5970 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5972 /* Send SIGHUP to process group... is there a better way? */
5975 /* reload our services immediately */
5976 reload_services( False );
5979 file_lines_free(qlines);
5983 /********************************************************************
5984 * Called by spoolss_api_setprinter
5985 * when updating a printer description.
5986 ********************************************************************/
5988 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5989 const SPOOL_PRINTER_INFO_LEVEL *info,
5990 DEVICEMODE *devmode)
5993 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5994 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5999 DEBUG(8,("update_printer\n"));
6004 result = WERR_BADFID;
6008 if (!get_printer_snum(p, handle, &snum)) {
6009 result = WERR_BADFID;
6013 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6014 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6015 result = WERR_BADFID;
6019 DEBUGADD(8,("Converting info_2 struct\n"));
6022 * convert_printer_info converts the incoming
6023 * info from the client and overwrites the info
6024 * just read from the tdb in the pointer 'printer'.
6027 if (!convert_printer_info(info, printer, level)) {
6028 result = WERR_NOMEM;
6033 /* we have a valid devmode
6034 convert it and link it*/
6036 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6037 if (!convert_devicemode(printer->info_2->printername, devmode,
6038 &printer->info_2->devmode)) {
6039 result = WERR_NOMEM;
6044 /* Do sanity check on the requested changes for Samba */
6046 if (!check_printer_ok(printer->info_2, snum)) {
6047 result = WERR_INVALID_PARAM;
6051 /* FIXME!!! If the driver has changed we really should verify that
6052 it is installed before doing much else --jerry */
6054 /* Check calling user has permission to update printer description */
6056 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6057 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6058 result = WERR_ACCESS_DENIED;
6062 /* Call addprinter hook */
6063 /* Check changes to see if this is really needed */
6065 if ( *lp_addprinter_cmd()
6066 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6067 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6068 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6069 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6071 if ( !add_printer_hook(printer) ) {
6072 result = WERR_ACCESS_DENIED;
6077 * make sure we actually reload the services after
6078 * this as smb.conf could have a new section in it
6079 * .... shouldn't .... but could
6081 reload_services(False);
6085 * When a *new* driver is bound to a printer, the drivername is used to
6086 * lookup previously saved driver initialization info, which is then
6087 * bound to the printer, simulating what happens in the Windows arch.
6089 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6091 if (!set_driver_init(printer, 2))
6093 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6094 printer->info_2->drivername));
6097 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6098 printer->info_2->drivername));
6100 notify_printer_driver(snum, printer->info_2->drivername);
6104 * flag which changes actually occured. This is a small subset of
6105 * all the possible changes. We also have to update things in the
6109 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6110 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6111 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6112 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6114 notify_printer_comment(snum, printer->info_2->comment);
6117 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6118 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6119 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6120 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6122 notify_printer_sharename(snum, printer->info_2->sharename);
6125 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6128 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6131 pname = printer->info_2->printername;
6134 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6135 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6136 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6138 notify_printer_printername( snum, pname );
6141 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6142 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6143 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6144 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6146 notify_printer_port(snum, printer->info_2->portname);
6149 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6150 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6151 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6152 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6154 notify_printer_location(snum, printer->info_2->location);
6157 /* here we need to update some more DsSpooler keys */
6158 /* uNCName, serverName, shortServerName */
6160 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6161 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6162 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6163 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6164 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6166 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6167 global_myname(), printer->info_2->sharename );
6168 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6169 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6170 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6172 /* Update printer info */
6173 result = mod_a_printer(*printer, 2);
6176 free_a_printer(&printer, 2);
6177 free_a_printer(&old_printer, 2);
6183 /****************************************************************************
6184 ****************************************************************************/
6185 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6186 const SPOOL_PRINTER_INFO_LEVEL *info)
6189 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6191 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6193 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6198 if (!get_printer_snum(p, handle, &snum))
6201 nt_printer_publish(Printer, snum, info7->action);
6205 return WERR_UNKNOWN_LEVEL;
6208 /****************************************************************************
6209 ****************************************************************************/
6211 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6213 POLICY_HND *handle = &q_u->handle;
6214 uint32 level = q_u->level;
6215 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6216 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6217 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6218 uint32 command = q_u->command;
6220 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6223 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6227 /* check the level */
6230 return control_printer(handle, command, p);
6232 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6234 return update_printer_sec(handle, level, info, p,
6237 return publish_or_unpublish_printer(p, handle, info);
6239 return WERR_UNKNOWN_LEVEL;
6243 /****************************************************************************
6244 ****************************************************************************/
6246 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6248 POLICY_HND *handle = &q_u->handle;
6249 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6252 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6256 if (Printer->notify.client_connected==True) {
6259 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6261 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6262 !get_printer_snum(p, handle, &snum) )
6265 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6268 Printer->notify.flags=0;
6269 Printer->notify.options=0;
6270 Printer->notify.localmachine[0]='\0';
6271 Printer->notify.printerlocal=0;
6272 if (Printer->notify.option)
6273 free_spool_notify_option(&Printer->notify.option);
6274 Printer->notify.client_connected=False;
6279 /****************************************************************************
6280 ****************************************************************************/
6282 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6284 /* that's an [in out] buffer (despite appearences to the contrary) */
6285 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6288 return WERR_INVALID_PARAM; /* this is what a NT server
6289 returns for AddJob. AddJob
6290 must fail on non-local
6294 /****************************************************************************
6295 ****************************************************************************/
6297 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6298 int position, int snum)
6304 t=gmtime(&queue->time);
6305 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6307 job_info->jobid=queue->job;
6308 init_unistr(&job_info->printername, lp_servicename(snum));
6309 init_unistr(&job_info->machinename, temp_name);
6310 init_unistr(&job_info->username, queue->fs_user);
6311 init_unistr(&job_info->document, queue->fs_file);
6312 init_unistr(&job_info->datatype, "RAW");
6313 init_unistr(&job_info->text_status, "");
6314 job_info->status=nt_printj_status(queue->status);
6315 job_info->priority=queue->priority;
6316 job_info->position=position;
6317 job_info->totalpages=queue->page_count;
6318 job_info->pagesprinted=0;
6320 make_systemtime(&job_info->submitted, t);
6323 /****************************************************************************
6324 ****************************************************************************/
6326 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6327 int position, int snum,
6328 NT_PRINTER_INFO_LEVEL *ntprinter,
6329 DEVICEMODE *devmode)
6334 t=gmtime(&queue->time);
6335 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6337 job_info->jobid=queue->job;
6339 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6341 init_unistr(&job_info->machinename, temp_name);
6342 init_unistr(&job_info->username, queue->fs_user);
6343 init_unistr(&job_info->document, queue->fs_file);
6344 init_unistr(&job_info->notifyname, queue->fs_user);
6345 init_unistr(&job_info->datatype, "RAW");
6346 init_unistr(&job_info->printprocessor, "winprint");
6347 init_unistr(&job_info->parameters, "");
6348 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6349 init_unistr(&job_info->text_status, "");
6351 /* and here the security descriptor */
6353 job_info->status=nt_printj_status(queue->status);
6354 job_info->priority=queue->priority;
6355 job_info->position=position;
6356 job_info->starttime=0;
6357 job_info->untiltime=0;
6358 job_info->totalpages=queue->page_count;
6359 job_info->size=queue->size;
6360 make_systemtime(&(job_info->submitted), t);
6361 job_info->timeelapsed=0;
6362 job_info->pagesprinted=0;
6364 job_info->devmode = devmode;
6369 /****************************************************************************
6370 Enumjobs at level 1.
6371 ****************************************************************************/
6373 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6374 NEW_BUFFER *buffer, uint32 offered,
6375 uint32 *needed, uint32 *returned)
6380 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6387 for (i=0; i<*returned; i++)
6388 fill_job_info_1(&info[i], &queue[i], i, snum);
6392 /* check the required size. */
6393 for (i=0; i<*returned; i++)
6394 (*needed) += spoolss_size_job_info_1(&info[i]);
6396 if (!alloc_buffer_size(buffer, *needed)) {
6398 return WERR_INSUFFICIENT_BUFFER;
6401 /* fill the buffer with the structures */
6402 for (i=0; i<*returned; i++)
6403 smb_io_job_info_1("", buffer, &info[i], 0);
6408 if (*needed > offered) {
6410 return WERR_INSUFFICIENT_BUFFER;
6416 /****************************************************************************
6417 Enumjobs at level 2.
6418 ****************************************************************************/
6420 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6421 NEW_BUFFER *buffer, uint32 offered,
6422 uint32 *needed, uint32 *returned)
6424 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6425 JOB_INFO_2 *info = NULL;
6428 DEVICEMODE *devmode = NULL;
6430 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6433 result = WERR_NOMEM;
6437 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6438 if (!W_ERROR_IS_OK(result)) {
6443 /* this should not be a failure condition if the devmode is NULL */
6445 devmode = construct_dev_mode(snum);
6447 for (i=0; i<*returned; i++)
6448 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6451 free_a_printer(&ntprinter, 2);
6454 /* check the required size. */
6455 for (i=0; i<*returned; i++)
6456 (*needed) += spoolss_size_job_info_2(&info[i]);
6458 if (*needed > offered) {
6460 result = WERR_INSUFFICIENT_BUFFER;
6464 if (!alloc_buffer_size(buffer, *needed)) {
6466 result = WERR_INSUFFICIENT_BUFFER;
6470 /* fill the buffer with the structures */
6471 for (i=0; i<*returned; i++)
6472 smb_io_job_info_2("", buffer, &info[i], 0);
6477 free_a_printer(&ntprinter, 2);
6478 free_devmode(devmode);
6486 /****************************************************************************
6488 ****************************************************************************/
6490 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6492 POLICY_HND *handle = &q_u->handle;
6493 uint32 level = q_u->level;
6494 NEW_BUFFER *buffer = NULL;
6495 uint32 offered = q_u->offered;
6496 uint32 *needed = &r_u->needed;
6497 uint32 *returned = &r_u->returned;
6501 print_status_struct prt_status;
6502 print_queue_struct *queue=NULL;
6504 /* that's an [in out] buffer */
6505 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6506 buffer = r_u->buffer;
6508 DEBUG(4,("_spoolss_enumjobs\n"));
6513 if (!get_printer_snum(p, handle, &snum))
6516 *returned = print_queue_status(snum, &queue, &prt_status);
6517 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6519 if (*returned == 0) {
6526 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6529 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6534 return WERR_UNKNOWN_LEVEL;
6538 /****************************************************************************
6539 ****************************************************************************/
6541 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6546 /****************************************************************************
6547 ****************************************************************************/
6549 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6551 POLICY_HND *handle = &q_u->handle;
6552 uint32 jobid = q_u->jobid;
6553 uint32 command = q_u->command;
6555 struct current_user user;
6557 WERROR errcode = WERR_BADFUNC;
6559 if (!get_printer_snum(p, handle, &snum)) {
6563 if (!print_job_exists(snum, jobid)) {
6564 return WERR_INVALID_PRINTER_NAME;
6567 get_current_user(&user, p);
6570 case JOB_CONTROL_CANCEL:
6571 case JOB_CONTROL_DELETE:
6572 if (print_job_delete(&user, snum, jobid, &errcode)) {
6576 case JOB_CONTROL_PAUSE:
6577 if (print_job_pause(&user, snum, jobid, &errcode)) {
6581 case JOB_CONTROL_RESTART:
6582 case JOB_CONTROL_RESUME:
6583 if (print_job_resume(&user, snum, jobid, &errcode)) {
6588 return WERR_UNKNOWN_LEVEL;
6594 /****************************************************************************
6595 Enumerates all printer drivers at level 1.
6596 ****************************************************************************/
6598 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6603 fstring *list = NULL;
6605 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6606 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6610 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6612 ndrivers=get_ntdrivers(&list, architecture, version);
6613 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6619 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6620 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6621 SAFE_FREE(driver_info_1);
6625 else driver_info_1 = tdi1;
6628 for (i=0; i<ndrivers; i++) {
6630 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6631 ZERO_STRUCT(driver);
6632 status = get_a_printer_driver(&driver, 3, list[i],
6633 architecture, version);
6634 if (!W_ERROR_IS_OK(status)) {
6638 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6639 free_a_printer_driver(driver, 3);
6642 *returned+=ndrivers;
6646 /* check the required size. */
6647 for (i=0; i<*returned; i++) {
6648 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6649 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6652 if (!alloc_buffer_size(buffer, *needed)) {
6653 SAFE_FREE(driver_info_1);
6654 return WERR_INSUFFICIENT_BUFFER;
6657 /* fill the buffer with the driver structures */
6658 for (i=0; i<*returned; i++) {
6659 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6660 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6663 SAFE_FREE(driver_info_1);
6665 if (*needed > offered) {
6667 return WERR_INSUFFICIENT_BUFFER;
6673 /****************************************************************************
6674 Enumerates all printer drivers at level 2.
6675 ****************************************************************************/
6677 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6682 fstring *list = NULL;
6684 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6685 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6689 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6691 ndrivers=get_ntdrivers(&list, architecture, version);
6692 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6698 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6699 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6700 SAFE_FREE(driver_info_2);
6704 else driver_info_2 = tdi2;
6707 for (i=0; i<ndrivers; i++) {
6710 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6711 ZERO_STRUCT(driver);
6712 status = get_a_printer_driver(&driver, 3, list[i],
6713 architecture, version);
6714 if (!W_ERROR_IS_OK(status)) {
6718 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6719 free_a_printer_driver(driver, 3);
6722 *returned+=ndrivers;
6726 /* check the required size. */
6727 for (i=0; i<*returned; i++) {
6728 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6729 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6732 if (!alloc_buffer_size(buffer, *needed)) {
6733 SAFE_FREE(driver_info_2);
6734 return WERR_INSUFFICIENT_BUFFER;
6737 /* fill the buffer with the form structures */
6738 for (i=0; i<*returned; i++) {
6739 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6740 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6743 SAFE_FREE(driver_info_2);
6745 if (*needed > offered) {
6747 return WERR_INSUFFICIENT_BUFFER;
6753 /****************************************************************************
6754 Enumerates all printer drivers at level 3.
6755 ****************************************************************************/
6757 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6762 fstring *list = NULL;
6764 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6765 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6769 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6771 ndrivers=get_ntdrivers(&list, architecture, version);
6772 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6778 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6779 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6780 SAFE_FREE(driver_info_3);
6784 else driver_info_3 = tdi3;
6787 for (i=0; i<ndrivers; i++) {
6790 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6791 ZERO_STRUCT(driver);
6792 status = get_a_printer_driver(&driver, 3, list[i],
6793 architecture, version);
6794 if (!W_ERROR_IS_OK(status)) {
6798 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6799 free_a_printer_driver(driver, 3);
6802 *returned+=ndrivers;
6806 /* check the required size. */
6807 for (i=0; i<*returned; i++) {
6808 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6809 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6812 if (!alloc_buffer_size(buffer, *needed)) {
6813 SAFE_FREE(driver_info_3);
6814 return WERR_INSUFFICIENT_BUFFER;
6817 /* fill the buffer with the driver structures */
6818 for (i=0; i<*returned; i++) {
6819 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6820 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6823 for (i=0; i<*returned; i++)
6824 SAFE_FREE(driver_info_3[i].dependentfiles);
6826 SAFE_FREE(driver_info_3);
6828 if (*needed > offered) {
6830 return WERR_INSUFFICIENT_BUFFER;
6836 /****************************************************************************
6837 Enumerates all printer drivers.
6838 ****************************************************************************/
6840 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6842 UNISTR2 *environment = &q_u->environment;
6843 uint32 level = q_u->level;
6844 NEW_BUFFER *buffer = NULL;
6845 uint32 offered = q_u->offered;
6846 uint32 *needed = &r_u->needed;
6847 uint32 *returned = &r_u->returned;
6849 fstring *list = NULL;
6851 fstring architecture;
6853 /* that's an [in out] buffer */
6854 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6855 buffer = r_u->buffer;
6857 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6858 fstrcpy(servername, get_called_name());
6862 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6866 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6868 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6870 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6874 return WERR_UNKNOWN_LEVEL;
6878 /****************************************************************************
6879 ****************************************************************************/
6881 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6883 form->flag=list->flag;
6884 init_unistr(&form->name, list->name);
6885 form->width=list->width;
6886 form->length=list->length;
6887 form->left=list->left;
6888 form->top=list->top;
6889 form->right=list->right;
6890 form->bottom=list->bottom;
6893 /****************************************************************************
6894 ****************************************************************************/
6896 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6898 uint32 level = q_u->level;
6899 NEW_BUFFER *buffer = NULL;
6900 uint32 offered = q_u->offered;
6901 uint32 *needed = &r_u->needed;
6902 uint32 *numofforms = &r_u->numofforms;
6903 uint32 numbuiltinforms;
6905 nt_forms_struct *list=NULL;
6906 nt_forms_struct *builtinlist=NULL;
6911 /* that's an [in out] buffer */
6912 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6913 buffer = r_u->buffer;
6915 DEBUG(4,("_spoolss_enumforms\n"));
6916 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6917 DEBUGADD(5,("Info level [%d]\n", level));
6919 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6920 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6921 *numofforms = get_ntforms(&list);
6922 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6923 *numofforms += numbuiltinforms;
6925 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6929 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6934 /* construct the list of form structures */
6935 for (i=0; i<numbuiltinforms; i++) {
6936 DEBUGADD(6,("Filling form number [%d]\n",i));
6937 fill_form_1(&forms_1[i], &builtinlist[i]);
6940 SAFE_FREE(builtinlist);
6942 for (; i<*numofforms; i++) {
6943 DEBUGADD(6,("Filling form number [%d]\n",i));
6944 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6949 /* check the required size. */
6950 for (i=0; i<numbuiltinforms; i++) {
6951 DEBUGADD(6,("adding form [%d]'s size\n",i));
6952 buffer_size += spoolss_size_form_1(&forms_1[i]);
6954 for (; i<*numofforms; i++) {
6955 DEBUGADD(6,("adding form [%d]'s size\n",i));
6956 buffer_size += spoolss_size_form_1(&forms_1[i]);
6959 *needed=buffer_size;
6961 if (!alloc_buffer_size(buffer, buffer_size)){
6963 return WERR_INSUFFICIENT_BUFFER;
6966 /* fill the buffer with the form structures */
6967 for (i=0; i<numbuiltinforms; i++) {
6968 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6969 smb_io_form_1("", buffer, &forms_1[i], 0);
6971 for (; i<*numofforms; i++) {
6972 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6973 smb_io_form_1("", buffer, &forms_1[i], 0);
6978 if (*needed > offered) {
6980 return WERR_INSUFFICIENT_BUFFER;
6987 SAFE_FREE(builtinlist);
6988 return WERR_UNKNOWN_LEVEL;
6993 /****************************************************************************
6994 ****************************************************************************/
6996 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6998 uint32 level = q_u->level;
6999 UNISTR2 *uni_formname = &q_u->formname;
7000 NEW_BUFFER *buffer = NULL;
7001 uint32 offered = q_u->offered;
7002 uint32 *needed = &r_u->needed;
7004 nt_forms_struct *list=NULL;
7005 nt_forms_struct builtin_form;
7010 int numofforms=0, i=0;
7012 /* that's an [in out] buffer */
7013 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7014 buffer = r_u->buffer;
7016 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7018 DEBUG(4,("_spoolss_getform\n"));
7019 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7020 DEBUGADD(5,("Info level [%d]\n", level));
7022 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7023 if (!foundBuiltin) {
7024 numofforms = get_ntforms(&list);
7025 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7027 if (numofforms == 0)
7034 fill_form_1(&form_1, &builtin_form);
7037 /* Check if the requested name is in the list of form structures */
7038 for (i=0; i<numofforms; i++) {
7040 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7042 if (strequal(form_name, list[i].name)) {
7043 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7044 fill_form_1(&form_1, &list[i]);
7050 if (i == numofforms) {
7054 /* check the required size. */
7056 *needed=spoolss_size_form_1(&form_1);
7058 if (!alloc_buffer_size(buffer, buffer_size)){
7059 return WERR_INSUFFICIENT_BUFFER;
7062 if (*needed > offered) {
7063 return WERR_INSUFFICIENT_BUFFER;
7066 /* fill the buffer with the form structures */
7067 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7068 smb_io_form_1("", buffer, &form_1, 0);
7074 return WERR_UNKNOWN_LEVEL;
7078 /****************************************************************************
7079 ****************************************************************************/
7081 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7083 init_unistr(&port->port_name, name);
7086 /****************************************************************************
7087 ****************************************************************************/
7089 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7091 init_unistr(&port->port_name, name);
7092 init_unistr(&port->monitor_name, "Local Monitor");
7093 init_unistr(&port->description, "Local Port");
7094 port->port_type=PORT_TYPE_WRITE;
7098 /****************************************************************************
7100 ****************************************************************************/
7102 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7104 PORT_INFO_1 *ports=NULL;
7107 if (*lp_enumports_cmd()) {
7108 char *cmd = lp_enumports_cmd();
7115 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7117 DEBUG(10,("Running [%s]\n", command));
7118 ret = smbrun(command, &fd);
7119 DEBUG(10,("Returned [%d]\n", ret));
7123 /* Is this the best error to return here? */
7124 return WERR_ACCESS_DENIED;
7128 qlines = fd_lines_load(fd, &numlines);
7129 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7133 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7134 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7135 dos_errstr(WERR_NOMEM)));
7136 file_lines_free(qlines);
7140 for (i=0; i<numlines; i++) {
7141 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7142 fill_port_1(&ports[i], qlines[i]);
7145 file_lines_free(qlines);
7148 *returned = numlines;
7151 *returned = 1; /* Sole Samba port returned. */
7153 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7156 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7158 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7161 /* check the required size. */
7162 for (i=0; i<*returned; i++) {
7163 DEBUGADD(6,("adding port [%d]'s size\n", i));
7164 *needed += spoolss_size_port_info_1(&ports[i]);
7167 if (!alloc_buffer_size(buffer, *needed)) {
7169 return WERR_INSUFFICIENT_BUFFER;
7172 /* fill the buffer with the ports structures */
7173 for (i=0; i<*returned; i++) {
7174 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7175 smb_io_port_1("", buffer, &ports[i], 0);
7180 if (*needed > offered) {
7182 return WERR_INSUFFICIENT_BUFFER;
7188 /****************************************************************************
7190 ****************************************************************************/
7192 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7194 PORT_INFO_2 *ports=NULL;
7197 if (*lp_enumports_cmd()) {
7198 char *cmd = lp_enumports_cmd();
7207 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7208 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7210 path = lp_lockdir();
7212 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7213 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7216 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7217 ret = smbrun(command, &fd);
7218 DEBUGADD(10,("returned [%d]\n", ret));
7222 /* Is this the best error to return here? */
7223 return WERR_ACCESS_DENIED;
7227 qlines = fd_lines_load(fd, &numlines);
7228 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7232 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7233 file_lines_free(qlines);
7237 for (i=0; i<numlines; i++) {
7238 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7239 fill_port_2(&(ports[i]), qlines[i]);
7242 file_lines_free(qlines);
7245 *returned = numlines;
7251 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7254 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7256 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7259 /* check the required size. */
7260 for (i=0; i<*returned; i++) {
7261 DEBUGADD(6,("adding port [%d]'s size\n", i));
7262 *needed += spoolss_size_port_info_2(&ports[i]);
7265 if (!alloc_buffer_size(buffer, *needed)) {
7267 return WERR_INSUFFICIENT_BUFFER;
7270 /* fill the buffer with the ports structures */
7271 for (i=0; i<*returned; i++) {
7272 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7273 smb_io_port_2("", buffer, &ports[i], 0);
7278 if (*needed > offered) {
7280 return WERR_INSUFFICIENT_BUFFER;
7286 /****************************************************************************
7288 ****************************************************************************/
7290 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7292 uint32 level = q_u->level;
7293 NEW_BUFFER *buffer = NULL;
7294 uint32 offered = q_u->offered;
7295 uint32 *needed = &r_u->needed;
7296 uint32 *returned = &r_u->returned;
7298 /* that's an [in out] buffer */
7299 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7300 buffer = r_u->buffer;
7302 DEBUG(4,("_spoolss_enumports\n"));
7309 return enumports_level_1(buffer, offered, needed, returned);
7311 return enumports_level_2(buffer, offered, needed, returned);
7313 return WERR_UNKNOWN_LEVEL;
7317 /****************************************************************************
7318 ****************************************************************************/
7320 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7321 const SPOOL_PRINTER_INFO_LEVEL *info,
7322 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7323 uint32 user_switch, const SPOOL_USER_CTR *user,
7326 NT_PRINTER_INFO_LEVEL *printer = NULL;
7329 WERROR err = WERR_OK;
7331 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7332 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7336 ZERO_STRUCTP(printer);
7338 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7339 if (!convert_printer_info(info, printer, 2)) {
7340 free_a_printer(&printer, 2);
7344 /* check to see if the printer already exists */
7346 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7347 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7348 printer->info_2->sharename));
7349 free_a_printer(&printer, 2);
7350 return WERR_PRINTER_ALREADY_EXISTS;
7353 /* FIXME!!! smbd should check to see if the driver is installed before
7354 trying to add a printer like this --jerry */
7356 if (*lp_addprinter_cmd() ) {
7357 if ( !add_printer_hook(printer) ) {
7358 free_a_printer(&printer,2);
7359 return WERR_ACCESS_DENIED;
7363 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7364 printer->info_2->sharename);
7367 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7368 free_a_printer(&printer,2);
7369 return WERR_ACCESS_DENIED;
7372 /* you must be a printer admin to add a new printer */
7373 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7374 free_a_printer(&printer,2);
7375 return WERR_ACCESS_DENIED;
7379 * Do sanity check on the requested changes for Samba.
7382 if (!check_printer_ok(printer->info_2, snum)) {
7383 free_a_printer(&printer,2);
7384 return WERR_INVALID_PARAM;
7388 * When a printer is created, the drivername bound to the printer is used
7389 * to lookup previously saved driver initialization info, which is then
7390 * bound to the new printer, simulating what happens in the Windows arch.
7395 set_driver_init(printer, 2);
7399 /* A valid devmode was included, convert and link it
7401 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7403 if (!convert_devicemode(printer->info_2->printername, devmode,
7404 &printer->info_2->devmode))
7408 /* write the ASCII on disk */
7409 err = mod_a_printer(*printer, 2);
7410 if (!W_ERROR_IS_OK(err)) {
7411 free_a_printer(&printer,2);
7415 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7416 /* Handle open failed - remove addition. */
7417 del_a_printer(printer->info_2->sharename);
7418 free_a_printer(&printer,2);
7419 return WERR_ACCESS_DENIED;
7422 update_c_setprinter(False);
7423 free_a_printer(&printer,2);
7428 /****************************************************************************
7429 ****************************************************************************/
7431 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7433 UNISTR2 *uni_srv_name = &q_u->server_name;
7434 uint32 level = q_u->level;
7435 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7436 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7437 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7438 uint32 user_switch = q_u->user_switch;
7439 SPOOL_USER_CTR *user = &q_u->user_ctr;
7440 POLICY_HND *handle = &r_u->handle;
7444 /* we don't handle yet */
7445 /* but I know what to do ... */
7446 return WERR_UNKNOWN_LEVEL;
7448 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7450 user_switch, user, handle);
7452 return WERR_UNKNOWN_LEVEL;
7456 /****************************************************************************
7457 ****************************************************************************/
7459 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7461 uint32 level = q_u->level;
7462 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7463 WERROR err = WERR_OK;
7464 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7465 struct current_user user;
7466 fstring driver_name;
7469 ZERO_STRUCT(driver);
7471 get_current_user(&user, p);
7473 if (!convert_printer_driver_info(info, &driver, level)) {
7478 DEBUG(5,("Cleaning driver's information\n"));
7479 err = clean_up_driver_struct(driver, level, &user);
7480 if (!W_ERROR_IS_OK(err))
7483 DEBUG(5,("Moving driver to final destination\n"));
7484 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7485 if (W_ERROR_IS_OK(err))
7486 err = WERR_ACCESS_DENIED;
7490 if (add_a_printer_driver(driver, level)!=0) {
7491 err = WERR_ACCESS_DENIED;
7495 /* BEGIN_ADMIN_LOG */
7498 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7499 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7500 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7503 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7504 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7505 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7511 * I think this is where he DrvUpgradePrinter() hook would be
7512 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7513 * server. Right now, we just need to send ourselves a message
7514 * to update each printer bound to this driver. --jerry
7517 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7518 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7523 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7524 * decide if the driver init data should be deleted. The rules are:
7525 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7526 * 2) delete init data only if there is no 2k/Xp driver
7527 * 3) always delete init data
7528 * The generalized rule is always use init data from the highest order driver.
7529 * It is necessary to follow the driver install by an initialization step to
7530 * finish off this process.
7533 version = driver.info_3->cversion;
7534 else if (level == 6)
7535 version = driver.info_6->version;
7540 * 9x printer driver - never delete init data
7543 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7548 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7549 * there is no 2k/Xp driver init data for this driver name.
7553 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7555 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7557 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7559 if (!del_driver_init(driver_name))
7560 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7563 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7565 free_a_printer_driver(driver1,3);
7566 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7573 * 2k or Xp printer driver - always delete init data
7576 if (!del_driver_init(driver_name))
7577 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7581 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7587 free_a_printer_driver(driver, level);
7591 /********************************************************************
7592 * spoolss_addprinterdriverex
7593 ********************************************************************/
7595 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7597 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7598 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7601 * we only support the semantics of AddPrinterDriver()
7602 * i.e. only copy files that are newer than existing ones
7605 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7606 return WERR_ACCESS_DENIED;
7608 ZERO_STRUCT(q_u_local);
7609 ZERO_STRUCT(r_u_local);
7611 /* just pass the information off to _spoolss_addprinterdriver() */
7612 q_u_local.server_name_ptr = q_u->server_name_ptr;
7613 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7614 q_u_local.level = q_u->level;
7615 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7617 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7620 /****************************************************************************
7621 ****************************************************************************/
7623 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7625 init_unistr(&info->name, name);
7628 /****************************************************************************
7629 ****************************************************************************/
7631 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7635 const char *short_archi;
7636 DRIVER_DIRECTORY_1 *info=NULL;
7638 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7640 if (!(short_archi = get_short_archi(long_archi)))
7641 return WERR_INVALID_ENVIRONMENT;
7643 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7646 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7648 DEBUG(4,("printer driver directory: [%s]\n", path));
7650 fill_driverdir_1(info, path);
7652 *needed += spoolss_size_driverdir_info_1(info);
7654 if (!alloc_buffer_size(buffer, *needed)) {
7656 return WERR_INSUFFICIENT_BUFFER;
7659 smb_io_driverdir_1("", buffer, info, 0);
7663 if (*needed > offered)
7664 return WERR_INSUFFICIENT_BUFFER;
7669 /****************************************************************************
7670 ****************************************************************************/
7672 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7674 UNISTR2 *name = &q_u->name;
7675 UNISTR2 *uni_environment = &q_u->environment;
7676 uint32 level = q_u->level;
7677 NEW_BUFFER *buffer = NULL;
7678 uint32 offered = q_u->offered;
7679 uint32 *needed = &r_u->needed;
7681 /* that's an [in out] buffer */
7682 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7683 buffer = r_u->buffer;
7685 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7691 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7693 return WERR_UNKNOWN_LEVEL;
7697 /****************************************************************************
7698 ****************************************************************************/
7700 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7702 POLICY_HND *handle = &q_u->handle;
7703 uint32 idx = q_u->index;
7704 uint32 in_value_len = q_u->valuesize;
7705 uint32 in_data_len = q_u->datasize;
7706 uint32 *out_max_value_len = &r_u->valuesize;
7707 uint16 **out_value = &r_u->value;
7708 uint32 *out_value_len = &r_u->realvaluesize;
7709 uint32 *out_type = &r_u->type;
7710 uint32 *out_max_data_len = &r_u->datasize;
7711 uint8 **data_out = &r_u->data;
7712 uint32 *out_data_len = &r_u->realdatasize;
7714 NT_PRINTER_INFO_LEVEL *printer = NULL;
7716 uint32 biggest_valuesize;
7717 uint32 biggest_datasize;
7719 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7722 REGISTRY_VALUE *val = NULL;
7723 NT_PRINTER_DATA *p_data;
7724 int i, key_index, num_values;
7727 ZERO_STRUCT( printer );
7731 *out_max_data_len = 0;
7735 DEBUG(5,("spoolss_enumprinterdata\n"));
7738 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7742 if (!get_printer_snum(p,handle, &snum))
7745 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7746 if (!W_ERROR_IS_OK(result))
7749 p_data = &printer->info_2->data;
7750 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7755 * The NT machine wants to know the biggest size of value and data
7757 * cf: MSDN EnumPrinterData remark section
7760 if ( !in_value_len && !in_data_len && (key_index != -1) )
7762 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7764 biggest_valuesize = 0;
7765 biggest_datasize = 0;
7767 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7769 for ( i=0; i<num_values; i++ )
7771 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7773 name_length = strlen(val->valuename);
7774 if ( strlen(val->valuename) > biggest_valuesize )
7775 biggest_valuesize = name_length;
7777 if ( val->size > biggest_datasize )
7778 biggest_datasize = val->size;
7780 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7784 /* the value is an UNICODE string but real_value_size is the length
7785 in bytes including the trailing 0 */
7787 *out_value_len = 2 * (1+biggest_valuesize);
7788 *out_data_len = biggest_datasize;
7790 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7796 * the value len is wrong in NT sp3
7797 * that's the number of bytes not the number of unicode chars
7800 if ( key_index != -1 )
7801 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7806 /* out_value should default to "" or else NT4 has
7807 problems unmarshalling the response */
7809 *out_max_value_len=(in_value_len/sizeof(uint16));
7811 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7813 result = WERR_NOMEM;
7817 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7819 /* the data is counted in bytes */
7821 *out_max_data_len = in_data_len;
7822 *out_data_len = in_data_len;
7824 /* only allocate when given a non-zero data_len */
7826 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7828 result = WERR_NOMEM;
7832 result = WERR_NO_MORE_ITEMS;
7838 * - counted in bytes in the request
7839 * - counted in UNICODE chars in the max reply
7840 * - counted in bytes in the real size
7842 * take a pause *before* coding not *during* coding
7846 *out_max_value_len=(in_value_len/sizeof(uint16));
7847 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7849 result = WERR_NOMEM;
7853 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7857 *out_type = regval_type( val );
7859 /* data - counted in bytes */
7861 *out_max_data_len = in_data_len;
7862 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7864 result = WERR_NOMEM;
7867 data_len = (size_t)regval_size(val);
7868 memcpy( *data_out, regval_data_p(val), data_len );
7869 *out_data_len = data_len;
7873 free_a_printer(&printer, 2);
7877 /****************************************************************************
7878 ****************************************************************************/
7880 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7882 POLICY_HND *handle = &q_u->handle;
7883 UNISTR2 *value = &q_u->value;
7884 uint32 type = q_u->type;
7885 uint8 *data = q_u->data;
7886 uint32 real_len = q_u->real_len;
7888 NT_PRINTER_INFO_LEVEL *printer = NULL;
7890 WERROR status = WERR_OK;
7891 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7894 DEBUG(5,("spoolss_setprinterdata\n"));
7897 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7901 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7902 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7903 return WERR_INVALID_PARAM;
7906 if (!get_printer_snum(p,handle, &snum))
7910 * Access check : NT returns "access denied" if you make a
7911 * SetPrinterData call without the necessary privildge.
7912 * we were originally returning OK if nothing changed
7913 * which made Win2k issue **a lot** of SetPrinterData
7914 * when connecting to a printer --jerry
7917 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7919 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7920 status = WERR_ACCESS_DENIED;
7924 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7925 if (!W_ERROR_IS_OK(status))
7928 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7931 * When client side code sets a magic printer data key, detect it and save
7932 * the current printer data and the magic key's data (its the DEVMODE) for
7933 * future printer/driver initializations.
7935 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7937 /* Set devmode and printer initialization info */
7938 status = save_driver_init( printer, 2, data, real_len );
7940 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7944 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7945 type, data, real_len );
7946 if ( W_ERROR_IS_OK(status) )
7947 status = mod_a_printer(*printer, 2);
7951 free_a_printer(&printer, 2);
7956 /****************************************************************************
7957 ****************************************************************************/
7959 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7961 POLICY_HND *handle = &q_u->handle;
7962 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7965 DEBUG(5,("_spoolss_resetprinter\n"));
7968 * All we do is to check to see if the handle and queue is valid.
7969 * This call really doesn't mean anything to us because we only
7970 * support RAW printing. --jerry
7974 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7978 if (!get_printer_snum(p,handle, &snum))
7982 /* blindly return success */
7987 /****************************************************************************
7988 ****************************************************************************/
7990 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7992 POLICY_HND *handle = &q_u->handle;
7993 UNISTR2 *value = &q_u->valuename;
7995 NT_PRINTER_INFO_LEVEL *printer = NULL;
7997 WERROR status = WERR_OK;
7998 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8001 DEBUG(5,("spoolss_deleteprinterdata\n"));
8004 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8008 if (!get_printer_snum(p, handle, &snum))
8011 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8012 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8013 return WERR_ACCESS_DENIED;
8016 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8017 if (!W_ERROR_IS_OK(status))
8020 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8022 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8024 if ( W_ERROR_IS_OK(status) )
8025 mod_a_printer( *printer, 2 );
8027 free_a_printer(&printer, 2);
8032 /****************************************************************************
8033 ****************************************************************************/
8035 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8037 POLICY_HND *handle = &q_u->handle;
8038 FORM *form = &q_u->form;
8039 nt_forms_struct tmpForm;
8041 WERROR status = WERR_OK;
8042 NT_PRINTER_INFO_LEVEL *printer = NULL;
8045 nt_forms_struct *list=NULL;
8046 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8048 DEBUG(5,("spoolss_addform\n"));
8051 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8056 /* forms can be added on printer of on the print server handle */
8058 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8060 if (!get_printer_snum(p,handle, &snum))
8063 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8064 if (!W_ERROR_IS_OK(status))
8068 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8069 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8070 status = WERR_ACCESS_DENIED;
8074 /* can't add if builtin */
8076 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8077 status = WERR_ALREADY_EXISTS;
8081 count = get_ntforms(&list);
8083 if(!add_a_form(&list, form, &count)) {
8084 status = WERR_NOMEM;
8088 write_ntforms(&list, count);
8091 * ChangeID must always be set if this is a printer
8094 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8095 status = mod_a_printer(*printer, 2);
8099 free_a_printer(&printer, 2);
8105 /****************************************************************************
8106 ****************************************************************************/
8108 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8110 POLICY_HND *handle = &q_u->handle;
8111 UNISTR2 *form_name = &q_u->name;
8112 nt_forms_struct tmpForm;
8114 nt_forms_struct *list=NULL;
8115 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8117 WERROR status = WERR_OK;
8118 NT_PRINTER_INFO_LEVEL *printer = NULL;
8120 DEBUG(5,("spoolss_deleteform\n"));
8123 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8127 /* forms can be deleted on printer of on the print server handle */
8129 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8131 if (!get_printer_snum(p,handle, &snum))
8134 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8135 if (!W_ERROR_IS_OK(status))
8139 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8140 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8141 status = WERR_ACCESS_DENIED;
8145 /* can't delete if builtin */
8147 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8148 status = WERR_INVALID_PARAM;
8152 count = get_ntforms(&list);
8154 if ( !delete_a_form(&list, form_name, &count, &status ))
8158 * ChangeID must always be set if this is a printer
8161 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8162 status = mod_a_printer(*printer, 2);
8166 free_a_printer(&printer, 2);
8172 /****************************************************************************
8173 ****************************************************************************/
8175 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8177 POLICY_HND *handle = &q_u->handle;
8178 FORM *form = &q_u->form;
8179 nt_forms_struct tmpForm;
8181 WERROR status = WERR_OK;
8182 NT_PRINTER_INFO_LEVEL *printer = NULL;
8185 nt_forms_struct *list=NULL;
8186 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8188 DEBUG(5,("spoolss_setform\n"));
8191 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8195 /* forms can be modified on printer of on the print server handle */
8197 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8199 if (!get_printer_snum(p,handle, &snum))
8202 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8203 if (!W_ERROR_IS_OK(status))
8207 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8208 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8209 status = WERR_ACCESS_DENIED;
8213 /* can't set if builtin */
8214 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8215 status = WERR_INVALID_PARAM;
8219 count = get_ntforms(&list);
8220 update_a_form(&list, form, count);
8221 write_ntforms(&list, count);
8224 * ChangeID must always be set if this is a printer
8227 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8228 status = mod_a_printer(*printer, 2);
8233 free_a_printer(&printer, 2);
8239 /****************************************************************************
8240 enumprintprocessors level 1.
8241 ****************************************************************************/
8243 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8245 PRINTPROCESSOR_1 *info_1=NULL;
8247 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8252 init_unistr(&info_1->name, "winprint");
8254 *needed += spoolss_size_printprocessor_info_1(info_1);
8256 if (!alloc_buffer_size(buffer, *needed))
8257 return WERR_INSUFFICIENT_BUFFER;
8259 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8263 if (*needed > offered) {
8265 return WERR_INSUFFICIENT_BUFFER;
8271 /****************************************************************************
8272 ****************************************************************************/
8274 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8276 uint32 level = q_u->level;
8277 NEW_BUFFER *buffer = NULL;
8278 uint32 offered = q_u->offered;
8279 uint32 *needed = &r_u->needed;
8280 uint32 *returned = &r_u->returned;
8282 /* that's an [in out] buffer */
8283 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8284 buffer = r_u->buffer;
8286 DEBUG(5,("spoolss_enumprintprocessors\n"));
8289 * Enumerate the print processors ...
8291 * Just reply with "winprint", to keep NT happy
8292 * and I can use my nice printer checker.
8300 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8302 return WERR_UNKNOWN_LEVEL;
8306 /****************************************************************************
8307 enumprintprocdatatypes level 1.
8308 ****************************************************************************/
8310 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8312 PRINTPROCDATATYPE_1 *info_1=NULL;
8314 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8319 init_unistr(&info_1->name, "RAW");
8321 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8323 if (!alloc_buffer_size(buffer, *needed))
8324 return WERR_INSUFFICIENT_BUFFER;
8326 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8330 if (*needed > offered) {
8332 return WERR_INSUFFICIENT_BUFFER;
8338 /****************************************************************************
8339 ****************************************************************************/
8341 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8343 uint32 level = q_u->level;
8344 NEW_BUFFER *buffer = NULL;
8345 uint32 offered = q_u->offered;
8346 uint32 *needed = &r_u->needed;
8347 uint32 *returned = &r_u->returned;
8349 /* that's an [in out] buffer */
8350 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8351 buffer = r_u->buffer;
8353 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8360 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8362 return WERR_UNKNOWN_LEVEL;
8366 /****************************************************************************
8367 enumprintmonitors level 1.
8368 ****************************************************************************/
8370 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8372 PRINTMONITOR_1 *info_1=NULL;
8374 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8379 init_unistr(&info_1->name, "Local Port");
8381 *needed += spoolss_size_printmonitor_info_1(info_1);
8383 if (!alloc_buffer_size(buffer, *needed))
8384 return WERR_INSUFFICIENT_BUFFER;
8386 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8390 if (*needed > offered) {
8392 return WERR_INSUFFICIENT_BUFFER;
8398 /****************************************************************************
8399 enumprintmonitors level 2.
8400 ****************************************************************************/
8402 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8404 PRINTMONITOR_2 *info_2=NULL;
8406 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8411 init_unistr(&info_2->name, "Local Port");
8412 init_unistr(&info_2->environment, "Windows NT X86");
8413 init_unistr(&info_2->dll_name, "localmon.dll");
8415 *needed += spoolss_size_printmonitor_info_2(info_2);
8417 if (!alloc_buffer_size(buffer, *needed))
8418 return WERR_INSUFFICIENT_BUFFER;
8420 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8424 if (*needed > offered) {
8426 return WERR_INSUFFICIENT_BUFFER;
8432 /****************************************************************************
8433 ****************************************************************************/
8435 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8437 uint32 level = q_u->level;
8438 NEW_BUFFER *buffer = NULL;
8439 uint32 offered = q_u->offered;
8440 uint32 *needed = &r_u->needed;
8441 uint32 *returned = &r_u->returned;
8443 /* that's an [in out] buffer */
8444 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8445 buffer = r_u->buffer;
8447 DEBUG(5,("spoolss_enumprintmonitors\n"));
8450 * Enumerate the print monitors ...
8452 * Just reply with "Local Port", to keep NT happy
8453 * and I can use my nice printer checker.
8461 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8463 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8465 return WERR_UNKNOWN_LEVEL;
8469 /****************************************************************************
8470 ****************************************************************************/
8472 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8476 JOB_INFO_1 *info_1=NULL;
8478 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8480 if (info_1 == NULL) {
8484 for (i=0; i<count && found==False; i++) {
8485 if ((*queue)[i].job==(int)jobid)
8491 /* NT treats not found as bad param... yet another bad choice */
8492 return WERR_INVALID_PARAM;
8495 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8497 *needed += spoolss_size_job_info_1(info_1);
8499 if (!alloc_buffer_size(buffer, *needed)) {
8501 return WERR_INSUFFICIENT_BUFFER;
8504 smb_io_job_info_1("", buffer, info_1, 0);
8508 if (*needed > offered)
8509 return WERR_INSUFFICIENT_BUFFER;
8514 /****************************************************************************
8515 ****************************************************************************/
8517 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8522 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8524 DEVICEMODE *devmode = NULL;
8525 NT_DEVICEMODE *nt_devmode = NULL;
8527 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8529 ZERO_STRUCTP(info_2);
8531 if (info_2 == NULL) {
8536 for ( i=0; i<count && found==False; i++ )
8538 if ((*queue)[i].job == (int)jobid)
8544 /* NT treats not found as bad param... yet another bad
8546 ret = WERR_INVALID_PARAM;
8550 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8551 if (!W_ERROR_IS_OK(ret))
8555 * if the print job does not have a DEVMODE associated with it,
8556 * just use the one for the printer. A NULL devicemode is not
8557 * a failure condition
8560 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8561 devmode = construct_dev_mode(snum);
8563 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8564 ZERO_STRUCTP( devmode );
8565 convert_nt_devicemode( devmode, nt_devmode );
8569 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8571 *needed += spoolss_size_job_info_2(info_2);
8573 if (!alloc_buffer_size(buffer, *needed)) {
8574 ret = WERR_INSUFFICIENT_BUFFER;
8578 smb_io_job_info_2("", buffer, info_2, 0);
8580 if (*needed > offered) {
8581 ret = WERR_INSUFFICIENT_BUFFER;
8588 /* Cleanup allocated memory */
8590 free_job_info_2(info_2); /* Also frees devmode */
8592 free_a_printer(&ntprinter, 2);
8597 /****************************************************************************
8598 ****************************************************************************/
8600 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8602 POLICY_HND *handle = &q_u->handle;
8603 uint32 jobid = q_u->jobid;
8604 uint32 level = q_u->level;
8605 NEW_BUFFER *buffer = NULL;
8606 uint32 offered = q_u->offered;
8607 uint32 *needed = &r_u->needed;
8608 WERROR wstatus = WERR_OK;
8612 print_queue_struct *queue = NULL;
8613 print_status_struct prt_status;
8615 /* that's an [in out] buffer */
8616 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8617 buffer = r_u->buffer;
8619 DEBUG(5,("spoolss_getjob\n"));
8623 if (!get_printer_snum(p, handle, &snum))
8626 count = print_queue_status(snum, &queue, &prt_status);
8628 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8629 count, prt_status.status, prt_status.message));
8633 wstatus = getjob_level_1(&queue, count, snum, jobid,
8634 buffer, offered, needed);
8637 wstatus = getjob_level_2(&queue, count, snum, jobid,
8638 buffer, offered, needed);
8641 wstatus = WERR_UNKNOWN_LEVEL;
8649 /********************************************************************
8650 spoolss_getprinterdataex
8652 From MSDN documentation of GetPrinterDataEx: pass request
8653 to GetPrinterData if key is "PrinterDriverData".
8654 ********************************************************************/
8656 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8658 POLICY_HND *handle = &q_u->handle;
8659 uint32 in_size = q_u->size;
8660 uint32 *type = &r_u->type;
8661 uint32 *out_size = &r_u->size;
8662 uint8 **data = &r_u->data;
8663 uint32 *needed = &r_u->needed;
8664 fstring keyname, valuename;
8666 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8668 NT_PRINTER_INFO_LEVEL *printer = NULL;
8670 WERROR status = WERR_OK;
8672 DEBUG(4,("_spoolss_getprinterdataex\n"));
8674 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8675 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8677 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8678 keyname, valuename));
8680 /* in case of problem, return some default values */
8684 *out_size = in_size;
8687 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8688 status = WERR_BADFID;
8692 /* Is the handle to a printer or to the server? */
8694 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8695 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8696 status = WERR_INVALID_PARAM;
8700 if ( !get_printer_snum(p,handle, &snum) )
8703 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8704 if ( !W_ERROR_IS_OK(status) )
8707 /* check to see if the keyname is valid */
8708 if ( !strlen(keyname) ) {
8709 status = WERR_INVALID_PARAM;
8713 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8714 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8715 free_a_printer( &printer, 2 );
8716 status = WERR_BADFILE;
8720 /* When given a new keyname, we should just create it */
8722 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8724 if (*needed > *out_size)
8725 status = WERR_MORE_DATA;
8728 if ( !W_ERROR_IS_OK(status) )
8730 DEBUG(5, ("error: allocating %d\n", *out_size));
8732 /* reply this param doesn't exist */
8736 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8737 status = WERR_NOMEM;
8747 free_a_printer( &printer, 2 );
8752 /********************************************************************
8753 * spoolss_setprinterdataex
8754 ********************************************************************/
8756 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8758 POLICY_HND *handle = &q_u->handle;
8759 uint32 type = q_u->type;
8760 uint8 *data = q_u->data;
8761 uint32 real_len = q_u->real_len;
8763 NT_PRINTER_INFO_LEVEL *printer = NULL;
8765 WERROR status = WERR_OK;
8766 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8771 DEBUG(4,("_spoolss_setprinterdataex\n"));
8773 /* From MSDN documentation of SetPrinterDataEx: pass request to
8774 SetPrinterData if key is "PrinterDriverData" */
8777 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8781 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8782 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8783 return WERR_INVALID_PARAM;
8786 if ( !get_printer_snum(p,handle, &snum) )
8790 * Access check : NT returns "access denied" if you make a
8791 * SetPrinterData call without the necessary privildge.
8792 * we were originally returning OK if nothing changed
8793 * which made Win2k issue **a lot** of SetPrinterData
8794 * when connecting to a printer --jerry
8797 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8799 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8800 return WERR_ACCESS_DENIED;
8803 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8804 if (!W_ERROR_IS_OK(status))
8807 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8808 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8810 /* check for OID in valuename */
8812 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8818 /* save the registry data */
8820 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8822 if ( W_ERROR_IS_OK(status) )
8824 /* save the OID if one was specified */
8826 fstrcat( keyname, "\\" );
8827 fstrcat( keyname, SPOOL_OID_KEY );
8830 * I'm not checking the status here on purpose. Don't know
8831 * if this is right, but I'm returning the status from the
8832 * previous set_printer_dataex() call. I have no idea if
8833 * this is right. --jerry
8836 set_printer_dataex( printer, keyname, valuename,
8837 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8840 status = mod_a_printer(*printer, 2);
8843 free_a_printer(&printer, 2);
8849 /********************************************************************
8850 * spoolss_deleteprinterdataex
8851 ********************************************************************/
8853 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8855 POLICY_HND *handle = &q_u->handle;
8856 UNISTR2 *value = &q_u->valuename;
8857 UNISTR2 *key = &q_u->keyname;
8859 NT_PRINTER_INFO_LEVEL *printer = NULL;
8861 WERROR status = WERR_OK;
8862 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8863 pstring valuename, keyname;
8865 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8868 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8872 if (!get_printer_snum(p, handle, &snum))
8875 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8876 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8877 return WERR_ACCESS_DENIED;
8880 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8881 if (!W_ERROR_IS_OK(status))
8884 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8885 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8887 status = delete_printer_dataex( printer, keyname, valuename );
8889 if ( W_ERROR_IS_OK(status) )
8890 mod_a_printer( *printer, 2 );
8892 free_a_printer(&printer, 2);
8897 /********************************************************************
8898 * spoolss_enumprinterkey
8899 ********************************************************************/
8902 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8905 fstring *keynames = NULL;
8906 uint16 *enumkeys = NULL;
8909 POLICY_HND *handle = &q_u->handle;
8910 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8911 NT_PRINTER_DATA *data;
8912 NT_PRINTER_INFO_LEVEL *printer = NULL;
8914 WERROR status = WERR_BADFILE;
8917 DEBUG(4,("_spoolss_enumprinterkey\n"));
8920 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8924 if ( !get_printer_snum(p,handle, &snum) )
8927 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8928 if (!W_ERROR_IS_OK(status))
8931 /* get the list of subkey names */
8933 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8934 data = &printer->info_2->data;
8936 num_keys = get_printer_subkeys( data, key, &keynames );
8938 if ( num_keys == -1 ) {
8939 status = WERR_BADFILE;
8943 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8945 r_u->needed = printerkey_len*2;
8947 if ( q_u->size < r_u->needed ) {
8948 status = WERR_MORE_DATA;
8952 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8953 status = WERR_NOMEM;
8959 if ( q_u->size < r_u->needed )
8960 status = WERR_MORE_DATA;
8963 free_a_printer( &printer, 2 );
8964 SAFE_FREE( keynames );
8969 /********************************************************************
8970 * spoolss_deleteprinterkey
8971 ********************************************************************/
8973 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8975 POLICY_HND *handle = &q_u->handle;
8976 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8978 NT_PRINTER_INFO_LEVEL *printer = NULL;
8982 DEBUG(5,("spoolss_deleteprinterkey\n"));
8985 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8989 /* if keyname == NULL, return error */
8991 if ( !q_u->keyname.buffer )
8992 return WERR_INVALID_PARAM;
8994 if (!get_printer_snum(p, handle, &snum))
8997 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8998 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8999 return WERR_ACCESS_DENIED;
9002 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9003 if (!W_ERROR_IS_OK(status))
9006 /* delete the key and all subneys */
9008 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9010 status = delete_all_printer_data( printer->info_2, key );
9012 if ( W_ERROR_IS_OK(status) )
9013 status = mod_a_printer(*printer, 2);
9015 free_a_printer( &printer, 2 );
9021 /********************************************************************
9022 * spoolss_enumprinterdataex
9023 ********************************************************************/
9025 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9027 POLICY_HND *handle = &q_u->handle;
9028 uint32 in_size = q_u->size;
9031 NT_PRINTER_INFO_LEVEL *printer = NULL;
9032 PRINTER_ENUM_VALUES *enum_values = NULL;
9033 NT_PRINTER_DATA *p_data;
9035 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9040 REGISTRY_VALUE *val;
9045 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9048 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9053 * first check for a keyname of NULL or "". Win2k seems to send
9054 * this a lot and we should send back WERR_INVALID_PARAM
9055 * no need to spend time looking up the printer in this case.
9059 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9060 if ( !strlen(key) ) {
9061 result = WERR_INVALID_PARAM;
9065 /* get the printer off of disk */
9067 if (!get_printer_snum(p,handle, &snum))
9070 ZERO_STRUCT(printer);
9071 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9072 if (!W_ERROR_IS_OK(result))
9075 /* now look for a match on the key name */
9077 p_data = &printer->info_2->data;
9079 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9080 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9082 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9083 result = WERR_INVALID_PARAM;
9090 /* allocate the memory for the array of pointers -- if necessary */
9092 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9095 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9097 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9098 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9099 result = WERR_NOMEM;
9103 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9107 * loop through all params and build the array to pass
9108 * back to the client
9111 for ( i=0; i<num_entries; i++ )
9113 /* lookup the registry value */
9115 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9116 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9120 value_name = regval_name( val );
9121 init_unistr( &enum_values[i].valuename, value_name );
9122 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9123 enum_values[i].type = regval_type( val );
9125 data_len = regval_size( val );
9127 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9129 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9131 result = WERR_NOMEM;
9135 enum_values[i].data_len = data_len;
9137 /* keep track of the size of the array in bytes */
9139 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9142 /* housekeeping information in the reply */
9144 r_u->needed = needed;
9145 r_u->returned = num_entries;
9147 if (needed > in_size) {
9148 result = WERR_MORE_DATA;
9152 /* copy data into the reply */
9154 r_u->ctr.size = r_u->needed;
9155 r_u->ctr.size_of_array = r_u->returned;
9156 r_u->ctr.values = enum_values;
9162 free_a_printer(&printer, 2);
9167 /****************************************************************************
9168 ****************************************************************************/
9170 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9172 init_unistr(&info->name, name);
9175 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9176 UNISTR2 *environment,
9183 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9185 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9187 if (!get_short_archi(long_archi))
9188 return WERR_INVALID_ENVIRONMENT;
9190 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9193 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9195 fill_printprocessordirectory_1(info, path);
9197 *needed += spoolss_size_printprocessordirectory_info_1(info);
9199 if (!alloc_buffer_size(buffer, *needed)) {
9201 return WERR_INSUFFICIENT_BUFFER;
9204 smb_io_printprocessordirectory_1("", buffer, info, 0);
9208 if (*needed > offered)
9209 return WERR_INSUFFICIENT_BUFFER;
9214 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9216 uint32 level = q_u->level;
9217 NEW_BUFFER *buffer = NULL;
9218 uint32 offered = q_u->offered;
9219 uint32 *needed = &r_u->needed;
9222 /* that's an [in out] buffer */
9223 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9224 buffer = r_u->buffer;
9226 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9232 result = getprintprocessordirectory_level_1
9233 (&q_u->name, &q_u->environment, buffer, offered, needed);
9236 result = WERR_UNKNOWN_LEVEL;
9244 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9245 SPOOL_R_REPLYOPENPRINTER *r_u)
9247 DEBUG(5,("_spoolss_replyopenprinter\n"));
9249 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9254 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9255 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9257 DEBUG(5,("_spoolss_replycloseprinter\n"));