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 for (i=0; i<option->count; i++) {
3729 option_type=&(option->ctr.type[i]);
3731 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3734 for (snum=0; snum<n_services; snum++)
3736 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3737 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3743 * Debugging information, don't delete.
3746 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3747 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3748 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3750 for (i=0; i<info->count; i++) {
3751 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3752 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3753 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3760 /*******************************************************************
3762 * fill a notify_info struct with info asked
3764 ********************************************************************/
3766 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3767 TALLOC_CTX *mem_ctx)
3770 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3773 SPOOL_NOTIFY_OPTION *option;
3774 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3776 print_queue_struct *queue=NULL;
3777 print_status_struct status;
3779 DEBUG(4,("printer_notify_info\n"));
3784 option=Printer->notify.option;
3790 get_printer_snum(p, hnd, &snum);
3792 for (i=0; i<option->count; i++) {
3793 option_type=&option->ctr.type[i];
3795 switch ( option_type->type ) {
3796 case PRINTER_NOTIFY_TYPE:
3797 if(construct_notify_printer_info(Printer, info, snum,
3803 case JOB_NOTIFY_TYPE: {
3804 NT_PRINTER_INFO_LEVEL *printer = NULL;
3806 count = print_queue_status(snum, &queue, &status);
3808 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3811 for (j=0; j<count; j++) {
3812 construct_notify_jobs_info(&queue[j], info,
3819 free_a_printer(&printer, 2);
3829 * Debugging information, don't delete.
3832 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3833 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3834 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3836 for (i=0; i<info->count; i++) {
3837 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3838 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3839 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3845 /********************************************************************
3847 ********************************************************************/
3849 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3851 POLICY_HND *handle = &q_u->handle;
3852 SPOOL_NOTIFY_INFO *info = &r_u->info;
3854 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3855 WERROR result = WERR_BADFID;
3857 /* we always have a NOTIFY_INFO struct */
3861 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3862 OUR_HANDLE(handle)));
3866 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3869 * We are now using the change value, and
3870 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3871 * I don't have a global notification system, I'm sending back all the
3872 * informations even when _NOTHING_ has changed.
3875 /* We need to keep track of the change value to send back in
3876 RRPCN replies otherwise our updates are ignored. */
3878 Printer->notify.fnpcn = True;
3880 if (Printer->notify.client_connected) {
3881 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3882 Printer->notify.change = q_u->change;
3885 /* just ignore the SPOOL_NOTIFY_OPTION */
3887 switch (Printer->printer_type) {
3888 case PRINTER_HANDLE_IS_PRINTSERVER:
3889 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3892 case PRINTER_HANDLE_IS_PRINTER:
3893 result = printer_notify_info(p, handle, info, p->mem_ctx);
3897 Printer->notify.fnpcn = False;
3903 /********************************************************************
3904 * construct_printer_info_0
3905 * fill a printer_info_0 struct
3906 ********************************************************************/
3908 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3912 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3913 counter_printer_0 *session_counter;
3914 uint32 global_counter;
3917 print_status_struct status;
3919 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3922 count = print_queue_length(snum, &status);
3924 /* check if we already have a counter for this printer */
3925 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3927 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3928 if (session_counter->snum == snum)
3932 /* it's the first time, add it to the list */
3933 if (session_counter==NULL) {
3934 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3935 free_a_printer(&ntprinter, 2);
3938 ZERO_STRUCTP(session_counter);
3939 session_counter->snum=snum;
3940 session_counter->counter=0;
3941 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3945 session_counter->counter++;
3948 * the global_counter should be stored in a TDB as it's common to all the clients
3949 * and should be zeroed on samba startup
3951 global_counter=session_counter->counter;
3953 pstrcpy(chaine,ntprinter->info_2->printername);
3955 init_unistr(&printer->printername, chaine);
3957 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3958 init_unistr(&printer->servername, chaine);
3960 printer->cjobs = count;
3961 printer->total_jobs = 0;
3962 printer->total_bytes = 0;
3964 setuptime = (time_t)ntprinter->info_2->setuptime;
3965 t=gmtime(&setuptime);
3967 printer->year = t->tm_year+1900;
3968 printer->month = t->tm_mon+1;
3969 printer->dayofweek = t->tm_wday;
3970 printer->day = t->tm_mday;
3971 printer->hour = t->tm_hour;
3972 printer->minute = t->tm_min;
3973 printer->second = t->tm_sec;
3974 printer->milliseconds = 0;
3976 printer->global_counter = global_counter;
3977 printer->total_pages = 0;
3979 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3980 printer->major_version = 0x0005; /* NT 5 */
3981 printer->build_version = 0x0893; /* build 2195 */
3983 printer->unknown7 = 0x1;
3984 printer->unknown8 = 0x0;
3985 printer->unknown9 = 0x0;
3986 printer->session_counter = session_counter->counter;
3987 printer->unknown11 = 0x0;
3988 printer->printer_errors = 0x0; /* number of print failure */
3989 printer->unknown13 = 0x0;
3990 printer->unknown14 = 0x1;
3991 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3992 printer->unknown16 = 0x0;
3993 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3994 printer->unknown18 = 0x0;
3995 printer->status = nt_printq_status(status.status);
3996 printer->unknown20 = 0x0;
3997 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3998 printer->unknown22 = 0x0;
3999 printer->unknown23 = 0x6; /* 6 ???*/
4000 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4001 printer->unknown25 = 0;
4002 printer->unknown26 = 0;
4003 printer->unknown27 = 0;
4004 printer->unknown28 = 0;
4005 printer->unknown29 = 0;
4007 free_a_printer(&ntprinter,2);
4011 /********************************************************************
4012 * construct_printer_info_1
4013 * fill a printer_info_1 struct
4014 ********************************************************************/
4015 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4019 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4021 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4024 printer->flags=flags;
4026 if (*ntprinter->info_2->comment == '\0') {
4027 init_unistr(&printer->comment, lp_comment(snum));
4028 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4029 ntprinter->info_2->drivername, lp_comment(snum));
4032 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4033 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4034 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4037 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4039 init_unistr(&printer->description, chaine);
4040 init_unistr(&printer->name, chaine2);
4042 free_a_printer(&ntprinter,2);
4047 /****************************************************************************
4048 Free a DEVMODE struct.
4049 ****************************************************************************/
4051 static void free_dev_mode(DEVICEMODE *dev)
4056 SAFE_FREE(dev->private);
4061 /****************************************************************************
4062 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4063 should be valid upon entry
4064 ****************************************************************************/
4066 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4068 if ( !devmode || !ntdevmode )
4071 init_unistr(&devmode->devicename, ntdevmode->devicename);
4073 init_unistr(&devmode->formname, ntdevmode->formname);
4075 devmode->specversion = ntdevmode->specversion;
4076 devmode->driverversion = ntdevmode->driverversion;
4077 devmode->size = ntdevmode->size;
4078 devmode->driverextra = ntdevmode->driverextra;
4079 devmode->fields = ntdevmode->fields;
4081 devmode->orientation = ntdevmode->orientation;
4082 devmode->papersize = ntdevmode->papersize;
4083 devmode->paperlength = ntdevmode->paperlength;
4084 devmode->paperwidth = ntdevmode->paperwidth;
4085 devmode->scale = ntdevmode->scale;
4086 devmode->copies = ntdevmode->copies;
4087 devmode->defaultsource = ntdevmode->defaultsource;
4088 devmode->printquality = ntdevmode->printquality;
4089 devmode->color = ntdevmode->color;
4090 devmode->duplex = ntdevmode->duplex;
4091 devmode->yresolution = ntdevmode->yresolution;
4092 devmode->ttoption = ntdevmode->ttoption;
4093 devmode->collate = ntdevmode->collate;
4094 devmode->icmmethod = ntdevmode->icmmethod;
4095 devmode->icmintent = ntdevmode->icmintent;
4096 devmode->mediatype = ntdevmode->mediatype;
4097 devmode->dithertype = ntdevmode->dithertype;
4099 if (ntdevmode->private != NULL) {
4100 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4107 /****************************************************************************
4108 Create a DEVMODE struct. Returns malloced memory.
4109 ****************************************************************************/
4111 DEVICEMODE *construct_dev_mode(int snum)
4113 NT_PRINTER_INFO_LEVEL *printer = NULL;
4114 DEVICEMODE *devmode = NULL;
4116 DEBUG(7,("construct_dev_mode\n"));
4118 DEBUGADD(8,("getting printer characteristics\n"));
4120 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4123 if ( !printer->info_2->devmode ) {
4124 DEBUG(5, ("BONG! There was no device mode!\n"));
4128 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4129 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4133 ZERO_STRUCTP(devmode);
4135 DEBUGADD(8,("loading DEVICEMODE\n"));
4137 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4138 free_dev_mode( devmode );
4143 free_a_printer(&printer,2);
4148 /********************************************************************
4149 * construct_printer_info_2
4150 * fill a printer_info_2 struct
4151 ********************************************************************/
4153 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4156 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4158 print_status_struct status;
4160 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4163 count = print_queue_length(snum, &status);
4165 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4166 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4167 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4168 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4169 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4171 if (*ntprinter->info_2->comment == '\0')
4172 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4174 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4176 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4177 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4178 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4179 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4180 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4182 printer->attributes = ntprinter->info_2->attributes;
4184 printer->priority = ntprinter->info_2->priority; /* priority */
4185 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4186 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4187 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4188 printer->status = nt_printq_status(status.status); /* status */
4189 printer->cjobs = count; /* jobs */
4190 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4192 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4193 DEBUG(8, ("Returning NULL Devicemode!\n"));
4196 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4197 /* steal the printer info sec_desc structure. [badly done]. */
4198 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4199 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4200 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4201 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4204 printer->secdesc = NULL;
4207 free_a_printer(&ntprinter, 2);
4211 /********************************************************************
4212 * construct_printer_info_3
4213 * fill a printer_info_3 struct
4214 ********************************************************************/
4216 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4218 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4219 PRINTER_INFO_3 *printer = NULL;
4221 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4225 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4226 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4230 ZERO_STRUCTP(printer);
4232 printer->flags = 4; /* These are the components of the SD we are returning. */
4233 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4234 /* steal the printer info sec_desc structure. [badly done]. */
4235 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4239 * Set the flags for the components we are returning.
4242 if (printer->secdesc->owner_sid)
4243 printer->flags |= OWNER_SECURITY_INFORMATION;
4245 if (printer->secdesc->grp_sid)
4246 printer->flags |= GROUP_SECURITY_INFORMATION;
4248 if (printer->secdesc->dacl)
4249 printer->flags |= DACL_SECURITY_INFORMATION;
4251 if (printer->secdesc->sacl)
4252 printer->flags |= SACL_SECURITY_INFORMATION;
4255 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4256 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4257 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4260 free_a_printer(&ntprinter, 2);
4262 *pp_printer = printer;
4266 /********************************************************************
4267 * construct_printer_info_4
4268 * fill a printer_info_4 struct
4269 ********************************************************************/
4271 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4273 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4275 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4278 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4279 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4280 printer->attributes = ntprinter->info_2->attributes;
4282 free_a_printer(&ntprinter, 2);
4286 /********************************************************************
4287 * construct_printer_info_5
4288 * fill a printer_info_5 struct
4289 ********************************************************************/
4291 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4293 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4295 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4298 init_unistr(&printer->printername, ntprinter->info_2->printername);
4299 init_unistr(&printer->portname, ntprinter->info_2->portname);
4300 printer->attributes = ntprinter->info_2->attributes;
4302 /* these two are not used by NT+ according to MSDN */
4304 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4305 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4307 free_a_printer(&ntprinter, 2);
4312 /********************************************************************
4313 * construct_printer_info_7
4314 * fill a printer_info_7 struct
4315 ********************************************************************/
4317 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4319 char *guid_str = NULL;
4322 if (is_printer_published(print_hnd, snum, &guid)) {
4323 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4324 strupper_m(guid_str);
4325 init_unistr(&printer->guid, guid_str);
4326 printer->action = SPOOL_DS_PUBLISH;
4328 init_unistr(&printer->guid, "");
4329 printer->action = SPOOL_DS_UNPUBLISH;
4335 /********************************************************************
4336 Spoolss_enumprinters.
4337 ********************************************************************/
4339 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4343 int n_services=lp_numservices();
4344 PRINTER_INFO_1 *tp, *printers=NULL;
4345 PRINTER_INFO_1 current_prt;
4347 DEBUG(4,("enum_all_printers_info_1\n"));
4349 for (snum=0; snum<n_services; snum++) {
4350 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4351 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4353 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4354 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4355 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4356 SAFE_FREE(printers);
4361 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4363 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4369 /* check the required size. */
4370 for (i=0; i<*returned; i++)
4371 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4373 if (!alloc_buffer_size(buffer, *needed))
4374 return WERR_INSUFFICIENT_BUFFER;
4376 /* fill the buffer with the structures */
4377 for (i=0; i<*returned; i++)
4378 smb_io_printer_info_1("", buffer, &printers[i], 0);
4381 SAFE_FREE(printers);
4383 if (*needed > offered) {
4385 return WERR_INSUFFICIENT_BUFFER;
4391 /********************************************************************
4392 enum_all_printers_info_1_local.
4393 *********************************************************************/
4395 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4397 DEBUG(4,("enum_all_printers_info_1_local\n"));
4399 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4402 /********************************************************************
4403 enum_all_printers_info_1_name.
4404 *********************************************************************/
4406 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4410 DEBUG(4,("enum_all_printers_info_1_name\n"));
4412 if ((name[0] == '\\') && (name[1] == '\\'))
4415 if (is_myname_or_ipaddr(s)) {
4416 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4419 return WERR_INVALID_NAME;
4422 /********************************************************************
4423 enum_all_printers_info_1_remote.
4424 *********************************************************************/
4426 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4428 PRINTER_INFO_1 *printer;
4429 fstring printername;
4432 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4434 /* JFM: currently it's more a place holder than anything else.
4435 * In the spooler world there is a notion of server registration.
4436 * the print servers are registring (sp ?) on the PDC (in the same domain)
4438 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4441 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4446 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4447 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4448 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4450 init_unistr(&printer->description, desc);
4451 init_unistr(&printer->name, printername);
4452 init_unistr(&printer->comment, comment);
4453 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4455 /* check the required size. */
4456 *needed += spoolss_size_printer_info_1(printer);
4458 if (!alloc_buffer_size(buffer, *needed)) {
4460 return WERR_INSUFFICIENT_BUFFER;
4463 /* fill the buffer with the structures */
4464 smb_io_printer_info_1("", buffer, printer, 0);
4469 if (*needed > offered) {
4471 return WERR_INSUFFICIENT_BUFFER;
4477 /********************************************************************
4478 enum_all_printers_info_1_network.
4479 *********************************************************************/
4481 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4485 DEBUG(4,("enum_all_printers_info_1_network\n"));
4487 /* If we respond to a enum_printers level 1 on our name with flags
4488 set to PRINTER_ENUM_REMOTE with a list of printers then these
4489 printers incorrectly appear in the APW browse list.
4490 Specifically the printers for the server appear at the workgroup
4491 level where all the other servers in the domain are
4492 listed. Windows responds to this call with a
4493 WERR_CAN_NOT_COMPLETE so we should do the same. */
4495 if (name[0] == '\\' && name[1] == '\\')
4498 if (is_myname_or_ipaddr(s))
4499 return WERR_CAN_NOT_COMPLETE;
4501 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4504 /********************************************************************
4505 * api_spoolss_enumprinters
4507 * called from api_spoolss_enumprinters (see this to understand)
4508 ********************************************************************/
4510 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4514 int n_services=lp_numservices();
4515 PRINTER_INFO_2 *tp, *printers=NULL;
4516 PRINTER_INFO_2 current_prt;
4518 for (snum=0; snum<n_services; snum++) {
4519 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4520 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4522 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4523 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4524 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4525 SAFE_FREE(printers);
4530 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4531 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4537 /* check the required size. */
4538 for (i=0; i<*returned; i++)
4539 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4541 if (!alloc_buffer_size(buffer, *needed)) {
4542 for (i=0; i<*returned; i++) {
4543 free_devmode(printers[i].devmode);
4545 SAFE_FREE(printers);
4546 return WERR_INSUFFICIENT_BUFFER;
4549 /* fill the buffer with the structures */
4550 for (i=0; i<*returned; i++)
4551 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4554 for (i=0; i<*returned; i++) {
4555 free_devmode(printers[i].devmode);
4557 SAFE_FREE(printers);
4559 if (*needed > offered) {
4561 return WERR_INSUFFICIENT_BUFFER;
4567 /********************************************************************
4568 * handle enumeration of printers at level 1
4569 ********************************************************************/
4571 static WERROR enumprinters_level1( uint32 flags, fstring name,
4572 NEW_BUFFER *buffer, uint32 offered,
4573 uint32 *needed, uint32 *returned)
4575 /* Not all the flags are equals */
4577 if (flags & PRINTER_ENUM_LOCAL)
4578 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4580 if (flags & PRINTER_ENUM_NAME)
4581 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4583 if (flags & PRINTER_ENUM_REMOTE)
4584 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4586 if (flags & PRINTER_ENUM_NETWORK)
4587 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4589 return WERR_OK; /* NT4sp5 does that */
4592 /********************************************************************
4593 * handle enumeration of printers at level 2
4594 ********************************************************************/
4596 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4597 NEW_BUFFER *buffer, uint32 offered,
4598 uint32 *needed, uint32 *returned)
4600 char *s = servername;
4602 if (flags & PRINTER_ENUM_LOCAL) {
4603 return enum_all_printers_info_2(buffer, offered, needed, returned);
4606 if (flags & PRINTER_ENUM_NAME) {
4607 if ((servername[0] == '\\') && (servername[1] == '\\'))
4609 if (is_myname_or_ipaddr(s))
4610 return enum_all_printers_info_2(buffer, offered, needed, returned);
4612 return WERR_INVALID_NAME;
4615 if (flags & PRINTER_ENUM_REMOTE)
4616 return WERR_UNKNOWN_LEVEL;
4621 /********************************************************************
4622 * handle enumeration of printers at level 5
4623 ********************************************************************/
4625 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4626 NEW_BUFFER *buffer, uint32 offered,
4627 uint32 *needed, uint32 *returned)
4629 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4633 /********************************************************************
4634 * api_spoolss_enumprinters
4636 * called from api_spoolss_enumprinters (see this to understand)
4637 ********************************************************************/
4639 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4641 uint32 flags = q_u->flags;
4642 UNISTR2 *servername = &q_u->servername;
4643 uint32 level = q_u->level;
4644 NEW_BUFFER *buffer = NULL;
4645 uint32 offered = q_u->offered;
4646 uint32 *needed = &r_u->needed;
4647 uint32 *returned = &r_u->returned;
4651 /* that's an [in out] buffer */
4652 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4653 buffer = r_u->buffer;
4655 DEBUG(4,("_spoolss_enumprinters\n"));
4662 * flags==PRINTER_ENUM_NAME
4663 * if name=="" then enumerates all printers
4664 * if name!="" then enumerate the printer
4665 * flags==PRINTER_ENUM_REMOTE
4666 * name is NULL, enumerate printers
4667 * Level 2: name!="" enumerates printers, name can't be NULL
4668 * Level 3: doesn't exist
4669 * Level 4: does a local registry lookup
4670 * Level 5: same as Level 2
4673 unistr2_to_ascii(name, servername, sizeof(name)-1);
4678 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4680 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4682 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4687 return WERR_UNKNOWN_LEVEL;
4690 /****************************************************************************
4691 ****************************************************************************/
4693 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4695 PRINTER_INFO_0 *printer=NULL;
4697 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4700 construct_printer_info_0(print_hnd, printer, snum);
4702 /* check the required size. */
4703 *needed += spoolss_size_printer_info_0(printer);
4705 if (!alloc_buffer_size(buffer, *needed)) {
4707 return WERR_INSUFFICIENT_BUFFER;
4710 /* fill the buffer with the structures */
4711 smb_io_printer_info_0("", buffer, printer, 0);
4716 if (*needed > offered) {
4717 return WERR_INSUFFICIENT_BUFFER;
4723 /****************************************************************************
4724 ****************************************************************************/
4726 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4728 PRINTER_INFO_1 *printer=NULL;
4730 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4733 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4735 /* check the required size. */
4736 *needed += spoolss_size_printer_info_1(printer);
4738 if (!alloc_buffer_size(buffer, *needed)) {
4740 return WERR_INSUFFICIENT_BUFFER;
4743 /* fill the buffer with the structures */
4744 smb_io_printer_info_1("", buffer, printer, 0);
4749 if (*needed > offered) {
4750 return WERR_INSUFFICIENT_BUFFER;
4756 /****************************************************************************
4757 ****************************************************************************/
4759 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4761 PRINTER_INFO_2 *printer=NULL;
4763 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4766 construct_printer_info_2(print_hnd, printer, snum);
4768 /* check the required size. */
4769 *needed += spoolss_size_printer_info_2(printer);
4771 if (!alloc_buffer_size(buffer, *needed)) {
4772 free_printer_info_2(printer);
4773 return WERR_INSUFFICIENT_BUFFER;
4776 /* fill the buffer with the structures */
4777 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4778 free_printer_info_2(printer);
4783 free_printer_info_2(printer);
4785 if (*needed > offered) {
4786 return WERR_INSUFFICIENT_BUFFER;
4792 /****************************************************************************
4793 ****************************************************************************/
4795 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4797 PRINTER_INFO_3 *printer=NULL;
4799 if (!construct_printer_info_3(print_hnd, &printer, snum))
4802 /* check the required size. */
4803 *needed += spoolss_size_printer_info_3(printer);
4805 if (!alloc_buffer_size(buffer, *needed)) {
4806 free_printer_info_3(printer);
4807 return WERR_INSUFFICIENT_BUFFER;
4810 /* fill the buffer with the structures */
4811 smb_io_printer_info_3("", buffer, printer, 0);
4814 free_printer_info_3(printer);
4816 if (*needed > offered) {
4817 return WERR_INSUFFICIENT_BUFFER;
4823 /****************************************************************************
4824 ****************************************************************************/
4826 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4828 PRINTER_INFO_4 *printer=NULL;
4830 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4833 if (!construct_printer_info_4(print_hnd, printer, snum))
4836 /* check the required size. */
4837 *needed += spoolss_size_printer_info_4(printer);
4839 if (!alloc_buffer_size(buffer, *needed)) {
4840 free_printer_info_4(printer);
4841 return WERR_INSUFFICIENT_BUFFER;
4844 /* fill the buffer with the structures */
4845 smb_io_printer_info_4("", buffer, printer, 0);
4848 free_printer_info_4(printer);
4850 if (*needed > offered) {
4851 return WERR_INSUFFICIENT_BUFFER;
4857 /****************************************************************************
4858 ****************************************************************************/
4860 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4862 PRINTER_INFO_5 *printer=NULL;
4864 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4867 if (!construct_printer_info_5(print_hnd, printer, snum))
4870 /* check the required size. */
4871 *needed += spoolss_size_printer_info_5(printer);
4873 if (!alloc_buffer_size(buffer, *needed)) {
4874 free_printer_info_5(printer);
4875 return WERR_INSUFFICIENT_BUFFER;
4878 /* fill the buffer with the structures */
4879 smb_io_printer_info_5("", buffer, printer, 0);
4882 free_printer_info_5(printer);
4884 if (*needed > offered) {
4885 return WERR_INSUFFICIENT_BUFFER;
4891 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4893 PRINTER_INFO_7 *printer=NULL;
4895 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4898 if (!construct_printer_info_7(print_hnd, printer, snum))
4901 /* check the required size. */
4902 *needed += spoolss_size_printer_info_7(printer);
4904 if (!alloc_buffer_size(buffer, *needed)) {
4905 free_printer_info_7(printer);
4906 return WERR_INSUFFICIENT_BUFFER;
4909 /* fill the buffer with the structures */
4910 smb_io_printer_info_7("", buffer, printer, 0);
4913 free_printer_info_7(printer);
4915 if (*needed > offered) {
4916 return WERR_INSUFFICIENT_BUFFER;
4922 /****************************************************************************
4923 ****************************************************************************/
4925 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4927 POLICY_HND *handle = &q_u->handle;
4928 uint32 level = q_u->level;
4929 NEW_BUFFER *buffer = NULL;
4930 uint32 offered = q_u->offered;
4931 uint32 *needed = &r_u->needed;
4932 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4936 /* that's an [in out] buffer */
4937 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4938 buffer = r_u->buffer;
4942 if (!get_printer_snum(p, handle, &snum))
4947 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4949 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4951 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4953 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4955 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4957 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4959 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4961 return WERR_UNKNOWN_LEVEL;
4964 /********************************************************************
4965 * fill a DRIVER_INFO_1 struct
4966 ********************************************************************/
4968 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4970 init_unistr( &info->name, driver.info_3->name);
4973 /********************************************************************
4974 * construct_printer_driver_info_1
4975 ********************************************************************/
4977 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4979 NT_PRINTER_INFO_LEVEL *printer = NULL;
4980 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4982 ZERO_STRUCT(driver);
4984 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4985 return WERR_INVALID_PRINTER_NAME;
4987 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4988 return WERR_UNKNOWN_PRINTER_DRIVER;
4990 fill_printer_driver_info_1(info, driver, servername, architecture);
4992 free_a_printer(&printer,2);
4997 /********************************************************************
4998 * construct_printer_driver_info_2
4999 * fill a printer_info_2 struct
5000 ********************************************************************/
5002 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5006 info->version=driver.info_3->cversion;
5008 init_unistr( &info->name, driver.info_3->name );
5009 init_unistr( &info->architecture, driver.info_3->environment );
5012 if (strlen(driver.info_3->driverpath)) {
5013 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5014 init_unistr( &info->driverpath, temp );
5016 init_unistr( &info->driverpath, "" );
5018 if (strlen(driver.info_3->datafile)) {
5019 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5020 init_unistr( &info->datafile, temp );
5022 init_unistr( &info->datafile, "" );
5024 if (strlen(driver.info_3->configfile)) {
5025 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5026 init_unistr( &info->configfile, temp );
5028 init_unistr( &info->configfile, "" );
5031 /********************************************************************
5032 * construct_printer_driver_info_2
5033 * fill a printer_info_2 struct
5034 ********************************************************************/
5036 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5038 NT_PRINTER_INFO_LEVEL *printer = NULL;
5039 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5041 ZERO_STRUCT(printer);
5042 ZERO_STRUCT(driver);
5044 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5045 return WERR_INVALID_PRINTER_NAME;
5047 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5048 return WERR_UNKNOWN_PRINTER_DRIVER;
5050 fill_printer_driver_info_2(info, driver, servername);
5052 free_a_printer(&printer,2);
5057 /********************************************************************
5058 * copy a strings array and convert to UNICODE
5060 * convert an array of ascii string to a UNICODE string
5061 ********************************************************************/
5063 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5071 DEBUG(6,("init_unistr_array\n"));
5082 v = ""; /* hack to handle null lists */
5085 /* hack to allow this to be used in places other than when generating
5086 the list of dependent files */
5089 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5093 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5095 /* add one extra unit16 for the second terminating NULL */
5097 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5098 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5106 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5111 /* special case for ""; we need to add both NULL's here */
5113 (*uni_array)[j++]=0x0000;
5114 (*uni_array)[j]=0x0000;
5117 DEBUGADD(6,("last one:done\n"));
5119 /* return size of array in uint16's */
5124 /********************************************************************
5125 * construct_printer_info_3
5126 * fill a printer_info_3 struct
5127 ********************************************************************/
5129 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5135 info->version=driver.info_3->cversion;
5137 init_unistr( &info->name, driver.info_3->name );
5138 init_unistr( &info->architecture, driver.info_3->environment );
5140 if (strlen(driver.info_3->driverpath)) {
5141 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5142 init_unistr( &info->driverpath, temp );
5144 init_unistr( &info->driverpath, "" );
5146 if (strlen(driver.info_3->datafile)) {
5147 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5148 init_unistr( &info->datafile, temp );
5150 init_unistr( &info->datafile, "" );
5152 if (strlen(driver.info_3->configfile)) {
5153 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5154 init_unistr( &info->configfile, temp );
5156 init_unistr( &info->configfile, "" );
5158 if (strlen(driver.info_3->helpfile)) {
5159 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5160 init_unistr( &info->helpfile, temp );
5162 init_unistr( &info->helpfile, "" );
5164 init_unistr( &info->monitorname, driver.info_3->monitorname );
5165 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5167 info->dependentfiles=NULL;
5168 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5171 /********************************************************************
5172 * construct_printer_info_3
5173 * fill a printer_info_3 struct
5174 ********************************************************************/
5176 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5178 NT_PRINTER_INFO_LEVEL *printer = NULL;
5179 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5181 ZERO_STRUCT(driver);
5183 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5184 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5185 if (!W_ERROR_IS_OK(status))
5186 return WERR_INVALID_PRINTER_NAME;
5188 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5189 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5194 * I put this code in during testing. Helpful when commenting out the
5195 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5196 * as win2k always queries the driver using an infor level of 6.
5197 * I've left it in (but ifdef'd out) because I'll probably
5198 * use it in experimentation again in the future. --jerry 22/01/2002
5201 if (!W_ERROR_IS_OK(status)) {
5203 * Is this a W2k client ?
5206 /* Yes - try again with a WinNT driver. */
5208 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5209 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5213 if (!W_ERROR_IS_OK(status)) {
5214 free_a_printer(&printer,2);
5215 return WERR_UNKNOWN_PRINTER_DRIVER;
5223 fill_printer_driver_info_3(info, driver, servername);
5225 free_a_printer(&printer,2);
5230 /********************************************************************
5231 * construct_printer_info_6
5232 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5233 ********************************************************************/
5235 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5241 memset(&nullstr, '\0', sizeof(fstring));
5243 info->version=driver.info_3->cversion;
5245 init_unistr( &info->name, driver.info_3->name );
5246 init_unistr( &info->architecture, driver.info_3->environment );
5248 if (strlen(driver.info_3->driverpath)) {
5249 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5250 init_unistr( &info->driverpath, temp );
5252 init_unistr( &info->driverpath, "" );
5254 if (strlen(driver.info_3->datafile)) {
5255 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5256 init_unistr( &info->datafile, temp );
5258 init_unistr( &info->datafile, "" );
5260 if (strlen(driver.info_3->configfile)) {
5261 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5262 init_unistr( &info->configfile, temp );
5264 init_unistr( &info->configfile, "" );
5266 if (strlen(driver.info_3->helpfile)) {
5267 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5268 init_unistr( &info->helpfile, temp );
5270 init_unistr( &info->helpfile, "" );
5272 init_unistr( &info->monitorname, driver.info_3->monitorname );
5273 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5275 info->dependentfiles = NULL;
5276 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5278 info->previousdrivernames=NULL;
5279 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5281 info->driver_date.low=0;
5282 info->driver_date.high=0;
5285 info->driver_version_low=0;
5286 info->driver_version_high=0;
5288 init_unistr( &info->mfgname, "");
5289 init_unistr( &info->oem_url, "");
5290 init_unistr( &info->hardware_id, "");
5291 init_unistr( &info->provider, "");
5294 /********************************************************************
5295 * construct_printer_info_6
5296 * fill a printer_info_6 struct
5297 ********************************************************************/
5299 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5300 fstring servername, fstring architecture, uint32 version)
5302 NT_PRINTER_INFO_LEVEL *printer = NULL;
5303 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5306 ZERO_STRUCT(driver);
5308 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5310 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5312 if (!W_ERROR_IS_OK(status))
5313 return WERR_INVALID_PRINTER_NAME;
5315 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5317 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5319 if (!W_ERROR_IS_OK(status))
5322 * Is this a W2k client ?
5326 free_a_printer(&printer,2);
5327 return WERR_UNKNOWN_PRINTER_DRIVER;
5330 /* Yes - try again with a WinNT driver. */
5332 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5333 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5334 if (!W_ERROR_IS_OK(status)) {
5335 free_a_printer(&printer,2);
5336 return WERR_UNKNOWN_PRINTER_DRIVER;
5340 fill_printer_driver_info_6(info, driver, servername);
5342 free_a_printer(&printer,2);
5343 free_a_printer_driver(driver, 3);
5348 /****************************************************************************
5349 ****************************************************************************/
5351 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5353 SAFE_FREE(info->dependentfiles);
5356 /****************************************************************************
5357 ****************************************************************************/
5359 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5361 SAFE_FREE(info->dependentfiles);
5365 /****************************************************************************
5366 ****************************************************************************/
5368 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5370 DRIVER_INFO_1 *info=NULL;
5373 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5376 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5377 if (!W_ERROR_IS_OK(status)) {
5382 /* check the required size. */
5383 *needed += spoolss_size_printer_driver_info_1(info);
5385 if (!alloc_buffer_size(buffer, *needed)) {
5387 return WERR_INSUFFICIENT_BUFFER;
5390 /* fill the buffer with the structures */
5391 smb_io_printer_driver_info_1("", buffer, info, 0);
5396 if (*needed > offered)
5397 return WERR_INSUFFICIENT_BUFFER;
5402 /****************************************************************************
5403 ****************************************************************************/
5405 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5407 DRIVER_INFO_2 *info=NULL;
5410 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5413 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5414 if (!W_ERROR_IS_OK(status)) {
5419 /* check the required size. */
5420 *needed += spoolss_size_printer_driver_info_2(info);
5422 if (!alloc_buffer_size(buffer, *needed)) {
5424 return WERR_INSUFFICIENT_BUFFER;
5427 /* fill the buffer with the structures */
5428 smb_io_printer_driver_info_2("", buffer, info, 0);
5433 if (*needed > offered)
5434 return WERR_INSUFFICIENT_BUFFER;
5439 /****************************************************************************
5440 ****************************************************************************/
5442 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5449 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5450 if (!W_ERROR_IS_OK(status)) {
5454 /* check the required size. */
5455 *needed += spoolss_size_printer_driver_info_3(&info);
5457 if (!alloc_buffer_size(buffer, *needed)) {
5458 free_printer_driver_info_3(&info);
5459 return WERR_INSUFFICIENT_BUFFER;
5462 /* fill the buffer with the structures */
5463 smb_io_printer_driver_info_3("", buffer, &info, 0);
5465 free_printer_driver_info_3(&info);
5467 if (*needed > offered)
5468 return WERR_INSUFFICIENT_BUFFER;
5473 /****************************************************************************
5474 ****************************************************************************/
5476 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5483 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5484 if (!W_ERROR_IS_OK(status)) {
5488 /* check the required size. */
5489 *needed += spoolss_size_printer_driver_info_6(&info);
5491 if (!alloc_buffer_size(buffer, *needed)) {
5492 free_printer_driver_info_6(&info);
5493 return WERR_INSUFFICIENT_BUFFER;
5496 /* fill the buffer with the structures */
5497 smb_io_printer_driver_info_6("", buffer, &info, 0);
5499 free_printer_driver_info_6(&info);
5501 if (*needed > offered)
5502 return WERR_INSUFFICIENT_BUFFER;
5507 /****************************************************************************
5508 ****************************************************************************/
5510 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5512 POLICY_HND *handle = &q_u->handle;
5513 UNISTR2 *uni_arch = &q_u->architecture;
5514 uint32 level = q_u->level;
5515 uint32 clientmajorversion = q_u->clientmajorversion;
5516 NEW_BUFFER *buffer = NULL;
5517 uint32 offered = q_u->offered;
5518 uint32 *needed = &r_u->needed;
5519 uint32 *servermajorversion = &r_u->servermajorversion;
5520 uint32 *serverminorversion = &r_u->serverminorversion;
5523 fstring architecture;
5526 /* that's an [in out] buffer */
5527 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5528 buffer = r_u->buffer;
5530 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5533 *servermajorversion = 0;
5534 *serverminorversion = 0;
5536 fstrcpy(servername, get_called_name());
5537 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5539 if (!get_printer_snum(p, handle, &snum))
5544 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5546 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5548 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5550 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5553 return WERR_UNKNOWN_LEVEL;
5556 /****************************************************************************
5557 ****************************************************************************/
5559 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5561 POLICY_HND *handle = &q_u->handle;
5563 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5566 DEBUG(3,("Error in startpageprinter printer handle\n"));
5570 Printer->page_started=True;
5574 /****************************************************************************
5575 ****************************************************************************/
5577 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5579 POLICY_HND *handle = &q_u->handle;
5582 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5585 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5589 if (!get_printer_snum(p, handle, &snum))
5592 Printer->page_started=False;
5593 print_job_endpage(snum, Printer->jobid);
5598 /********************************************************************
5599 * api_spoolss_getprinter
5600 * called from the spoolss dispatcher
5602 ********************************************************************/
5604 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5606 POLICY_HND *handle = &q_u->handle;
5607 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5608 uint32 *jobid = &r_u->jobid;
5610 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5614 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5615 struct current_user user;
5618 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5622 get_current_user(&user, p);
5625 * a nice thing with NT is it doesn't listen to what you tell it.
5626 * when asked to send _only_ RAW datas, it tries to send datas
5629 * So I add checks like in NT Server ...
5632 if (info_1->p_datatype != 0) {
5633 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5634 if (strcmp(datatype, "RAW") != 0) {
5636 return WERR_INVALID_DATATYPE;
5640 /* get the share number of the printer */
5641 if (!get_printer_snum(p, handle, &snum)) {
5645 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5647 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5649 /* An error occured in print_job_start() so return an appropriate
5652 if (Printer->jobid == -1) {
5653 return map_werror_from_unix(errno);
5656 Printer->document_started=True;
5657 (*jobid) = Printer->jobid;
5662 /********************************************************************
5663 * api_spoolss_getprinter
5664 * called from the spoolss dispatcher
5666 ********************************************************************/
5668 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5670 POLICY_HND *handle = &q_u->handle;
5672 return _spoolss_enddocprinter_internal(p, handle);
5675 /****************************************************************************
5676 ****************************************************************************/
5678 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5680 POLICY_HND *handle = &q_u->handle;
5681 uint32 buffer_size = q_u->buffer_size;
5682 uint8 *buffer = q_u->buffer;
5683 uint32 *buffer_written = &q_u->buffer_size2;
5685 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5688 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5689 r_u->buffer_written = q_u->buffer_size2;
5693 if (!get_printer_snum(p, handle, &snum))
5696 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5697 if (*buffer_written == -1) {
5698 r_u->buffer_written = 0;
5699 if (errno == ENOSPC)
5700 return WERR_NO_SPOOL_SPACE;
5702 return WERR_ACCESS_DENIED;
5705 r_u->buffer_written = q_u->buffer_size2;
5710 /********************************************************************
5711 * api_spoolss_getprinter
5712 * called from the spoolss dispatcher
5714 ********************************************************************/
5716 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5719 struct current_user user;
5721 WERROR errcode = WERR_BADFUNC;
5722 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5724 get_current_user(&user, p);
5727 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5731 if (!get_printer_snum(p, handle, &snum))
5735 case PRINTER_CONTROL_PAUSE:
5736 if (print_queue_pause(&user, snum, &errcode)) {
5740 case PRINTER_CONTROL_RESUME:
5741 case PRINTER_CONTROL_UNPAUSE:
5742 if (print_queue_resume(&user, snum, &errcode)) {
5746 case PRINTER_CONTROL_PURGE:
5747 if (print_queue_purge(&user, snum, &errcode)) {
5752 return WERR_UNKNOWN_LEVEL;
5758 /********************************************************************
5759 * api_spoolss_abortprinter
5760 * From MSDN: "Deletes printer's spool file if printer is configured
5762 ********************************************************************/
5764 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5766 POLICY_HND *handle = &q_u->handle;
5767 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5769 struct current_user user;
5770 WERROR errcode = WERR_OK;
5773 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5777 if (!get_printer_snum(p, handle, &snum))
5780 get_current_user( &user, p );
5782 print_job_delete( &user, snum, Printer->jobid, &errcode );
5787 /********************************************************************
5788 * called by spoolss_api_setprinter
5789 * when updating a printer description
5790 ********************************************************************/
5792 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5793 const SPOOL_PRINTER_INFO_LEVEL *info,
5794 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5796 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5797 struct current_user user;
5801 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5803 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5804 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5805 OUR_HANDLE(handle)));
5807 result = WERR_BADFID;
5811 /* NT seems to like setting the security descriptor even though
5812 nothing may have actually changed. This causes annoying
5813 dialog boxes when the user doesn't have permission to change
5814 the security descriptor. */
5816 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5818 if (DEBUGLEVEL >= 10) {
5822 the_acl = old_secdesc_ctr->sec->dacl;
5823 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5824 PRINTERNAME(snum), the_acl->num_aces));
5826 for (i = 0; i < the_acl->num_aces; i++) {
5829 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5831 DEBUG(10, ("%s 0x%08x\n", sid_str,
5832 the_acl->ace[i].info.mask));
5835 the_acl = secdesc_ctr->sec->dacl;
5838 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5839 PRINTERNAME(snum), the_acl->num_aces));
5841 for (i = 0; i < the_acl->num_aces; i++) {
5844 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5846 DEBUG(10, ("%s 0x%08x\n", sid_str,
5847 the_acl->ace[i].info.mask));
5850 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5854 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5856 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5861 /* Work out which user is performing the operation */
5863 get_current_user(&user, p);
5865 /* Check the user has permissions to change the security
5866 descriptor. By experimentation with two NT machines, the user
5867 requires Full Access to the printer to change security
5870 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5871 result = WERR_ACCESS_DENIED;
5875 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5882 /********************************************************************
5883 Do Samba sanity checks on a printer info struct.
5884 this has changed purpose: it now "canonicalises" printer
5885 info from a client rather than just checking it is correct
5886 ********************************************************************/
5888 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5890 fstring printername;
5893 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5894 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5896 /* we force some elements to "correct" values */
5897 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5898 fstrcpy(info->sharename, lp_servicename(snum));
5900 /* make sure printername is in \\server\printername format */
5902 fstrcpy( printername, info->printername );
5904 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5905 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5909 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5910 get_called_name(), p );
5912 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5918 /****************************************************************************
5919 ****************************************************************************/
5921 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5923 extern userdom_struct current_user_info;
5924 char *cmd = lp_addprinter_cmd();
5930 fstring remote_machine = "%m";
5932 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5934 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5935 cmd, printer->info_2->printername, printer->info_2->sharename,
5936 printer->info_2->portname, printer->info_2->drivername,
5937 printer->info_2->location, printer->info_2->comment, remote_machine);
5939 DEBUG(10,("Running [%s]\n", command));
5940 ret = smbrun(command, &fd);
5941 DEBUGADD(10,("returned [%d]\n", ret));
5950 /* Get lines and convert them back to dos-codepage */
5951 qlines = fd_lines_load(fd, &numlines);
5952 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5956 /* Set the portname to what the script says the portname should be. */
5957 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5958 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5960 /* Send SIGHUP to process group... is there a better way? */
5963 /* reload our services immediately */
5964 reload_services( False );
5967 file_lines_free(qlines);
5971 /********************************************************************
5972 * Called by spoolss_api_setprinter
5973 * when updating a printer description.
5974 ********************************************************************/
5976 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5977 const SPOOL_PRINTER_INFO_LEVEL *info,
5978 DEVICEMODE *devmode)
5981 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5982 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5987 DEBUG(8,("update_printer\n"));
5992 result = WERR_BADFID;
5996 if (!get_printer_snum(p, handle, &snum)) {
5997 result = WERR_BADFID;
6001 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6002 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6003 result = WERR_BADFID;
6007 DEBUGADD(8,("Converting info_2 struct\n"));
6010 * convert_printer_info converts the incoming
6011 * info from the client and overwrites the info
6012 * just read from the tdb in the pointer 'printer'.
6015 if (!convert_printer_info(info, printer, level)) {
6016 result = WERR_NOMEM;
6021 /* we have a valid devmode
6022 convert it and link it*/
6024 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6025 if (!convert_devicemode(printer->info_2->printername, devmode,
6026 &printer->info_2->devmode)) {
6027 result = WERR_NOMEM;
6032 /* Do sanity check on the requested changes for Samba */
6034 if (!check_printer_ok(printer->info_2, snum)) {
6035 result = WERR_INVALID_PARAM;
6039 /* FIXME!!! If the driver has changed we really should verify that
6040 it is installed before doing much else --jerry */
6042 /* Check calling user has permission to update printer description */
6044 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6045 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6046 result = WERR_ACCESS_DENIED;
6050 /* Call addprinter hook */
6051 /* Check changes to see if this is really needed */
6053 if ( *lp_addprinter_cmd()
6054 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6055 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6056 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6057 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6059 if ( !add_printer_hook(printer) ) {
6060 result = WERR_ACCESS_DENIED;
6065 * make sure we actually reload the services after
6066 * this as smb.conf could have a new section in it
6067 * .... shouldn't .... but could
6069 reload_services(False);
6073 * When a *new* driver is bound to a printer, the drivername is used to
6074 * lookup previously saved driver initialization info, which is then
6075 * bound to the printer, simulating what happens in the Windows arch.
6077 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6079 if (!set_driver_init(printer, 2))
6081 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6082 printer->info_2->drivername));
6085 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6086 printer->info_2->drivername));
6088 notify_printer_driver(snum, printer->info_2->drivername);
6092 * flag which changes actually occured. This is a small subset of
6093 * all the possible changes. We also have to update things in the
6097 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6098 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6099 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6100 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6102 notify_printer_comment(snum, printer->info_2->comment);
6105 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6106 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6107 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6108 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6110 notify_printer_sharename(snum, printer->info_2->sharename);
6113 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6116 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6119 pname = printer->info_2->printername;
6122 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6123 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6124 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6126 notify_printer_printername( snum, pname );
6129 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6130 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6131 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6132 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6134 notify_printer_port(snum, printer->info_2->portname);
6137 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6138 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6139 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6140 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6142 notify_printer_location(snum, printer->info_2->location);
6145 /* here we need to update some more DsSpooler keys */
6146 /* uNCName, serverName, shortServerName */
6148 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6149 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6150 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6151 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6152 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6154 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6155 global_myname(), printer->info_2->sharename );
6156 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6157 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6158 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6160 /* Update printer info */
6161 result = mod_a_printer(*printer, 2);
6164 free_a_printer(&printer, 2);
6165 free_a_printer(&old_printer, 2);
6171 /****************************************************************************
6172 ****************************************************************************/
6173 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6174 const SPOOL_PRINTER_INFO_LEVEL *info)
6177 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6179 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6181 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6186 if (!get_printer_snum(p, handle, &snum))
6189 nt_printer_publish(Printer, snum, info7->action);
6193 return WERR_UNKNOWN_LEVEL;
6196 /****************************************************************************
6197 ****************************************************************************/
6199 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6201 POLICY_HND *handle = &q_u->handle;
6202 uint32 level = q_u->level;
6203 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6204 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6205 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6206 uint32 command = q_u->command;
6208 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6211 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6215 /* check the level */
6218 return control_printer(handle, command, p);
6220 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6222 return update_printer_sec(handle, level, info, p,
6225 return publish_or_unpublish_printer(p, handle, info);
6227 return WERR_UNKNOWN_LEVEL;
6231 /****************************************************************************
6232 ****************************************************************************/
6234 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6236 POLICY_HND *handle = &q_u->handle;
6237 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6240 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6244 if (Printer->notify.client_connected==True) {
6247 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6249 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6250 !get_printer_snum(p, handle, &snum) )
6253 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6256 Printer->notify.flags=0;
6257 Printer->notify.options=0;
6258 Printer->notify.localmachine[0]='\0';
6259 Printer->notify.printerlocal=0;
6260 if (Printer->notify.option)
6261 free_spool_notify_option(&Printer->notify.option);
6262 Printer->notify.client_connected=False;
6267 /****************************************************************************
6268 ****************************************************************************/
6270 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6272 /* that's an [in out] buffer (despite appearences to the contrary) */
6273 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6276 return WERR_INVALID_PARAM; /* this is what a NT server
6277 returns for AddJob. AddJob
6278 must fail on non-local
6282 /****************************************************************************
6283 ****************************************************************************/
6285 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6286 int position, int snum)
6292 t=gmtime(&queue->time);
6293 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6295 job_info->jobid=queue->job;
6296 init_unistr(&job_info->printername, lp_servicename(snum));
6297 init_unistr(&job_info->machinename, temp_name);
6298 init_unistr(&job_info->username, queue->fs_user);
6299 init_unistr(&job_info->document, queue->fs_file);
6300 init_unistr(&job_info->datatype, "RAW");
6301 init_unistr(&job_info->text_status, "");
6302 job_info->status=nt_printj_status(queue->status);
6303 job_info->priority=queue->priority;
6304 job_info->position=position;
6305 job_info->totalpages=queue->page_count;
6306 job_info->pagesprinted=0;
6308 make_systemtime(&job_info->submitted, t);
6311 /****************************************************************************
6312 ****************************************************************************/
6314 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6315 int position, int snum,
6316 NT_PRINTER_INFO_LEVEL *ntprinter,
6317 DEVICEMODE *devmode)
6322 t=gmtime(&queue->time);
6323 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6325 job_info->jobid=queue->job;
6327 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6329 init_unistr(&job_info->machinename, temp_name);
6330 init_unistr(&job_info->username, queue->fs_user);
6331 init_unistr(&job_info->document, queue->fs_file);
6332 init_unistr(&job_info->notifyname, queue->fs_user);
6333 init_unistr(&job_info->datatype, "RAW");
6334 init_unistr(&job_info->printprocessor, "winprint");
6335 init_unistr(&job_info->parameters, "");
6336 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6337 init_unistr(&job_info->text_status, "");
6339 /* and here the security descriptor */
6341 job_info->status=nt_printj_status(queue->status);
6342 job_info->priority=queue->priority;
6343 job_info->position=position;
6344 job_info->starttime=0;
6345 job_info->untiltime=0;
6346 job_info->totalpages=queue->page_count;
6347 job_info->size=queue->size;
6348 make_systemtime(&(job_info->submitted), t);
6349 job_info->timeelapsed=0;
6350 job_info->pagesprinted=0;
6352 job_info->devmode = devmode;
6357 /****************************************************************************
6358 Enumjobs at level 1.
6359 ****************************************************************************/
6361 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6362 NEW_BUFFER *buffer, uint32 offered,
6363 uint32 *needed, uint32 *returned)
6368 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6375 for (i=0; i<*returned; i++)
6376 fill_job_info_1(&info[i], &queue[i], i, snum);
6380 /* check the required size. */
6381 for (i=0; i<*returned; i++)
6382 (*needed) += spoolss_size_job_info_1(&info[i]);
6384 if (!alloc_buffer_size(buffer, *needed)) {
6386 return WERR_INSUFFICIENT_BUFFER;
6389 /* fill the buffer with the structures */
6390 for (i=0; i<*returned; i++)
6391 smb_io_job_info_1("", buffer, &info[i], 0);
6396 if (*needed > offered) {
6398 return WERR_INSUFFICIENT_BUFFER;
6404 /****************************************************************************
6405 Enumjobs at level 2.
6406 ****************************************************************************/
6408 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6409 NEW_BUFFER *buffer, uint32 offered,
6410 uint32 *needed, uint32 *returned)
6412 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6413 JOB_INFO_2 *info = NULL;
6416 DEVICEMODE *devmode = NULL;
6418 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6421 result = WERR_NOMEM;
6425 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6426 if (!W_ERROR_IS_OK(result)) {
6431 /* this should not be a failure condition if the devmode is NULL */
6433 devmode = construct_dev_mode(snum);
6435 for (i=0; i<*returned; i++)
6436 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6439 free_a_printer(&ntprinter, 2);
6442 /* check the required size. */
6443 for (i=0; i<*returned; i++)
6444 (*needed) += spoolss_size_job_info_2(&info[i]);
6446 if (*needed > offered) {
6448 result = WERR_INSUFFICIENT_BUFFER;
6452 if (!alloc_buffer_size(buffer, *needed)) {
6454 result = WERR_INSUFFICIENT_BUFFER;
6458 /* fill the buffer with the structures */
6459 for (i=0; i<*returned; i++)
6460 smb_io_job_info_2("", buffer, &info[i], 0);
6465 free_a_printer(&ntprinter, 2);
6466 free_devmode(devmode);
6474 /****************************************************************************
6476 ****************************************************************************/
6478 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6480 POLICY_HND *handle = &q_u->handle;
6481 uint32 level = q_u->level;
6482 NEW_BUFFER *buffer = NULL;
6483 uint32 offered = q_u->offered;
6484 uint32 *needed = &r_u->needed;
6485 uint32 *returned = &r_u->returned;
6489 print_status_struct prt_status;
6490 print_queue_struct *queue=NULL;
6492 /* that's an [in out] buffer */
6493 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6494 buffer = r_u->buffer;
6496 DEBUG(4,("_spoolss_enumjobs\n"));
6501 if (!get_printer_snum(p, handle, &snum))
6504 *returned = print_queue_status(snum, &queue, &prt_status);
6505 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6507 if (*returned == 0) {
6514 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6517 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6522 return WERR_UNKNOWN_LEVEL;
6526 /****************************************************************************
6527 ****************************************************************************/
6529 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6534 /****************************************************************************
6535 ****************************************************************************/
6537 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6539 POLICY_HND *handle = &q_u->handle;
6540 uint32 jobid = q_u->jobid;
6541 uint32 command = q_u->command;
6543 struct current_user user;
6545 WERROR errcode = WERR_BADFUNC;
6547 if (!get_printer_snum(p, handle, &snum)) {
6551 if (!print_job_exists(snum, jobid)) {
6552 return WERR_INVALID_PRINTER_NAME;
6555 get_current_user(&user, p);
6558 case JOB_CONTROL_CANCEL:
6559 case JOB_CONTROL_DELETE:
6560 if (print_job_delete(&user, snum, jobid, &errcode)) {
6564 case JOB_CONTROL_PAUSE:
6565 if (print_job_pause(&user, snum, jobid, &errcode)) {
6569 case JOB_CONTROL_RESTART:
6570 case JOB_CONTROL_RESUME:
6571 if (print_job_resume(&user, snum, jobid, &errcode)) {
6576 return WERR_UNKNOWN_LEVEL;
6582 /****************************************************************************
6583 Enumerates all printer drivers at level 1.
6584 ****************************************************************************/
6586 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6591 fstring *list = NULL;
6593 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6594 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6598 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6600 ndrivers=get_ntdrivers(&list, architecture, version);
6601 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6607 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6608 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6609 SAFE_FREE(driver_info_1);
6613 else driver_info_1 = tdi1;
6616 for (i=0; i<ndrivers; i++) {
6618 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6619 ZERO_STRUCT(driver);
6620 status = get_a_printer_driver(&driver, 3, list[i],
6621 architecture, version);
6622 if (!W_ERROR_IS_OK(status)) {
6626 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6627 free_a_printer_driver(driver, 3);
6630 *returned+=ndrivers;
6634 /* check the required size. */
6635 for (i=0; i<*returned; i++) {
6636 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6637 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6640 if (!alloc_buffer_size(buffer, *needed)) {
6641 SAFE_FREE(driver_info_1);
6642 return WERR_INSUFFICIENT_BUFFER;
6645 /* fill the buffer with the driver structures */
6646 for (i=0; i<*returned; i++) {
6647 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6648 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6651 SAFE_FREE(driver_info_1);
6653 if (*needed > offered) {
6655 return WERR_INSUFFICIENT_BUFFER;
6661 /****************************************************************************
6662 Enumerates all printer drivers at level 2.
6663 ****************************************************************************/
6665 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6670 fstring *list = NULL;
6672 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6673 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6677 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6679 ndrivers=get_ntdrivers(&list, architecture, version);
6680 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6686 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6687 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6688 SAFE_FREE(driver_info_2);
6692 else driver_info_2 = tdi2;
6695 for (i=0; i<ndrivers; i++) {
6698 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6699 ZERO_STRUCT(driver);
6700 status = get_a_printer_driver(&driver, 3, list[i],
6701 architecture, version);
6702 if (!W_ERROR_IS_OK(status)) {
6706 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6707 free_a_printer_driver(driver, 3);
6710 *returned+=ndrivers;
6714 /* check the required size. */
6715 for (i=0; i<*returned; i++) {
6716 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6717 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6720 if (!alloc_buffer_size(buffer, *needed)) {
6721 SAFE_FREE(driver_info_2);
6722 return WERR_INSUFFICIENT_BUFFER;
6725 /* fill the buffer with the form structures */
6726 for (i=0; i<*returned; i++) {
6727 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6728 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6731 SAFE_FREE(driver_info_2);
6733 if (*needed > offered) {
6735 return WERR_INSUFFICIENT_BUFFER;
6741 /****************************************************************************
6742 Enumerates all printer drivers at level 3.
6743 ****************************************************************************/
6745 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6750 fstring *list = NULL;
6752 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6753 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6757 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6759 ndrivers=get_ntdrivers(&list, architecture, version);
6760 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6766 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6767 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6768 SAFE_FREE(driver_info_3);
6772 else driver_info_3 = tdi3;
6775 for (i=0; i<ndrivers; i++) {
6778 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6779 ZERO_STRUCT(driver);
6780 status = get_a_printer_driver(&driver, 3, list[i],
6781 architecture, version);
6782 if (!W_ERROR_IS_OK(status)) {
6786 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6787 free_a_printer_driver(driver, 3);
6790 *returned+=ndrivers;
6794 /* check the required size. */
6795 for (i=0; i<*returned; i++) {
6796 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6797 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6800 if (!alloc_buffer_size(buffer, *needed)) {
6801 SAFE_FREE(driver_info_3);
6802 return WERR_INSUFFICIENT_BUFFER;
6805 /* fill the buffer with the driver structures */
6806 for (i=0; i<*returned; i++) {
6807 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6808 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6811 for (i=0; i<*returned; i++)
6812 SAFE_FREE(driver_info_3[i].dependentfiles);
6814 SAFE_FREE(driver_info_3);
6816 if (*needed > offered) {
6818 return WERR_INSUFFICIENT_BUFFER;
6824 /****************************************************************************
6825 Enumerates all printer drivers.
6826 ****************************************************************************/
6828 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6830 UNISTR2 *environment = &q_u->environment;
6831 uint32 level = q_u->level;
6832 NEW_BUFFER *buffer = NULL;
6833 uint32 offered = q_u->offered;
6834 uint32 *needed = &r_u->needed;
6835 uint32 *returned = &r_u->returned;
6837 fstring *list = NULL;
6839 fstring architecture;
6841 /* that's an [in out] buffer */
6842 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6843 buffer = r_u->buffer;
6845 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6846 fstrcpy(servername, get_called_name());
6850 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6854 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6856 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6858 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6862 return WERR_UNKNOWN_LEVEL;
6866 /****************************************************************************
6867 ****************************************************************************/
6869 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6871 form->flag=list->flag;
6872 init_unistr(&form->name, list->name);
6873 form->width=list->width;
6874 form->length=list->length;
6875 form->left=list->left;
6876 form->top=list->top;
6877 form->right=list->right;
6878 form->bottom=list->bottom;
6881 /****************************************************************************
6882 ****************************************************************************/
6884 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6886 uint32 level = q_u->level;
6887 NEW_BUFFER *buffer = NULL;
6888 uint32 offered = q_u->offered;
6889 uint32 *needed = &r_u->needed;
6890 uint32 *numofforms = &r_u->numofforms;
6891 uint32 numbuiltinforms;
6893 nt_forms_struct *list=NULL;
6894 nt_forms_struct *builtinlist=NULL;
6899 /* that's an [in out] buffer */
6900 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6901 buffer = r_u->buffer;
6903 DEBUG(4,("_spoolss_enumforms\n"));
6904 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6905 DEBUGADD(5,("Info level [%d]\n", level));
6907 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6908 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6909 *numofforms = get_ntforms(&list);
6910 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6911 *numofforms += numbuiltinforms;
6913 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6917 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6922 /* construct the list of form structures */
6923 for (i=0; i<numbuiltinforms; i++) {
6924 DEBUGADD(6,("Filling form number [%d]\n",i));
6925 fill_form_1(&forms_1[i], &builtinlist[i]);
6928 SAFE_FREE(builtinlist);
6930 for (; i<*numofforms; i++) {
6931 DEBUGADD(6,("Filling form number [%d]\n",i));
6932 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6937 /* check the required size. */
6938 for (i=0; i<numbuiltinforms; i++) {
6939 DEBUGADD(6,("adding form [%d]'s size\n",i));
6940 buffer_size += spoolss_size_form_1(&forms_1[i]);
6942 for (; i<*numofforms; i++) {
6943 DEBUGADD(6,("adding form [%d]'s size\n",i));
6944 buffer_size += spoolss_size_form_1(&forms_1[i]);
6947 *needed=buffer_size;
6949 if (!alloc_buffer_size(buffer, buffer_size)){
6951 return WERR_INSUFFICIENT_BUFFER;
6954 /* fill the buffer with the form structures */
6955 for (i=0; i<numbuiltinforms; i++) {
6956 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6957 smb_io_form_1("", buffer, &forms_1[i], 0);
6959 for (; i<*numofforms; i++) {
6960 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6961 smb_io_form_1("", buffer, &forms_1[i], 0);
6966 if (*needed > offered) {
6968 return WERR_INSUFFICIENT_BUFFER;
6975 SAFE_FREE(builtinlist);
6976 return WERR_UNKNOWN_LEVEL;
6981 /****************************************************************************
6982 ****************************************************************************/
6984 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6986 uint32 level = q_u->level;
6987 UNISTR2 *uni_formname = &q_u->formname;
6988 NEW_BUFFER *buffer = NULL;
6989 uint32 offered = q_u->offered;
6990 uint32 *needed = &r_u->needed;
6992 nt_forms_struct *list=NULL;
6993 nt_forms_struct builtin_form;
6998 int numofforms=0, i=0;
7000 /* that's an [in out] buffer */
7001 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7002 buffer = r_u->buffer;
7004 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7006 DEBUG(4,("_spoolss_getform\n"));
7007 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7008 DEBUGADD(5,("Info level [%d]\n", level));
7010 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7011 if (!foundBuiltin) {
7012 numofforms = get_ntforms(&list);
7013 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7015 if (numofforms == 0)
7022 fill_form_1(&form_1, &builtin_form);
7025 /* Check if the requested name is in the list of form structures */
7026 for (i=0; i<numofforms; i++) {
7028 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7030 if (strequal(form_name, list[i].name)) {
7031 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7032 fill_form_1(&form_1, &list[i]);
7038 if (i == numofforms) {
7042 /* check the required size. */
7044 *needed=spoolss_size_form_1(&form_1);
7046 if (!alloc_buffer_size(buffer, buffer_size)){
7047 return WERR_INSUFFICIENT_BUFFER;
7050 if (*needed > offered) {
7051 return WERR_INSUFFICIENT_BUFFER;
7054 /* fill the buffer with the form structures */
7055 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7056 smb_io_form_1("", buffer, &form_1, 0);
7062 return WERR_UNKNOWN_LEVEL;
7066 /****************************************************************************
7067 ****************************************************************************/
7069 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7071 init_unistr(&port->port_name, name);
7074 /****************************************************************************
7075 ****************************************************************************/
7077 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7079 init_unistr(&port->port_name, name);
7080 init_unistr(&port->monitor_name, "Local Monitor");
7081 init_unistr(&port->description, "Local Port");
7082 port->port_type=PORT_TYPE_WRITE;
7086 /****************************************************************************
7088 ****************************************************************************/
7090 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7092 PORT_INFO_1 *ports=NULL;
7095 if (*lp_enumports_cmd()) {
7096 char *cmd = lp_enumports_cmd();
7103 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7105 DEBUG(10,("Running [%s]\n", command));
7106 ret = smbrun(command, &fd);
7107 DEBUG(10,("Returned [%d]\n", ret));
7111 /* Is this the best error to return here? */
7112 return WERR_ACCESS_DENIED;
7116 qlines = fd_lines_load(fd, &numlines);
7117 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7121 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7122 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7123 dos_errstr(WERR_NOMEM)));
7124 file_lines_free(qlines);
7128 for (i=0; i<numlines; i++) {
7129 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7130 fill_port_1(&ports[i], qlines[i]);
7133 file_lines_free(qlines);
7136 *returned = numlines;
7139 *returned = 1; /* Sole Samba port returned. */
7141 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7144 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7146 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7149 /* check the required size. */
7150 for (i=0; i<*returned; i++) {
7151 DEBUGADD(6,("adding port [%d]'s size\n", i));
7152 *needed += spoolss_size_port_info_1(&ports[i]);
7155 if (!alloc_buffer_size(buffer, *needed)) {
7157 return WERR_INSUFFICIENT_BUFFER;
7160 /* fill the buffer with the ports structures */
7161 for (i=0; i<*returned; i++) {
7162 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7163 smb_io_port_1("", buffer, &ports[i], 0);
7168 if (*needed > offered) {
7170 return WERR_INSUFFICIENT_BUFFER;
7176 /****************************************************************************
7178 ****************************************************************************/
7180 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7182 PORT_INFO_2 *ports=NULL;
7185 if (*lp_enumports_cmd()) {
7186 char *cmd = lp_enumports_cmd();
7195 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7196 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7198 path = lp_lockdir();
7200 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7201 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7204 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7205 ret = smbrun(command, &fd);
7206 DEBUGADD(10,("returned [%d]\n", ret));
7210 /* Is this the best error to return here? */
7211 return WERR_ACCESS_DENIED;
7215 qlines = fd_lines_load(fd, &numlines);
7216 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7220 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7221 file_lines_free(qlines);
7225 for (i=0; i<numlines; i++) {
7226 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7227 fill_port_2(&(ports[i]), qlines[i]);
7230 file_lines_free(qlines);
7233 *returned = numlines;
7239 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7242 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7244 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7247 /* check the required size. */
7248 for (i=0; i<*returned; i++) {
7249 DEBUGADD(6,("adding port [%d]'s size\n", i));
7250 *needed += spoolss_size_port_info_2(&ports[i]);
7253 if (!alloc_buffer_size(buffer, *needed)) {
7255 return WERR_INSUFFICIENT_BUFFER;
7258 /* fill the buffer with the ports structures */
7259 for (i=0; i<*returned; i++) {
7260 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7261 smb_io_port_2("", buffer, &ports[i], 0);
7266 if (*needed > offered) {
7268 return WERR_INSUFFICIENT_BUFFER;
7274 /****************************************************************************
7276 ****************************************************************************/
7278 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7280 uint32 level = q_u->level;
7281 NEW_BUFFER *buffer = NULL;
7282 uint32 offered = q_u->offered;
7283 uint32 *needed = &r_u->needed;
7284 uint32 *returned = &r_u->returned;
7286 /* that's an [in out] buffer */
7287 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7288 buffer = r_u->buffer;
7290 DEBUG(4,("_spoolss_enumports\n"));
7297 return enumports_level_1(buffer, offered, needed, returned);
7299 return enumports_level_2(buffer, offered, needed, returned);
7301 return WERR_UNKNOWN_LEVEL;
7305 /****************************************************************************
7306 ****************************************************************************/
7308 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7309 const SPOOL_PRINTER_INFO_LEVEL *info,
7310 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7311 uint32 user_switch, const SPOOL_USER_CTR *user,
7314 NT_PRINTER_INFO_LEVEL *printer = NULL;
7317 WERROR err = WERR_OK;
7319 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7320 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7324 ZERO_STRUCTP(printer);
7326 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7327 if (!convert_printer_info(info, printer, 2)) {
7328 free_a_printer(&printer, 2);
7332 /* check to see if the printer already exists */
7334 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7335 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7336 printer->info_2->sharename));
7337 free_a_printer(&printer, 2);
7338 return WERR_PRINTER_ALREADY_EXISTS;
7341 /* FIXME!!! smbd should check to see if the driver is installed before
7342 trying to add a printer like this --jerry */
7344 if (*lp_addprinter_cmd() ) {
7345 if ( !add_printer_hook(printer) ) {
7346 free_a_printer(&printer,2);
7347 return WERR_ACCESS_DENIED;
7351 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7352 printer->info_2->sharename);
7355 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7356 free_a_printer(&printer,2);
7357 return WERR_ACCESS_DENIED;
7360 /* you must be a printer admin to add a new printer */
7361 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7362 free_a_printer(&printer,2);
7363 return WERR_ACCESS_DENIED;
7367 * Do sanity check on the requested changes for Samba.
7370 if (!check_printer_ok(printer->info_2, snum)) {
7371 free_a_printer(&printer,2);
7372 return WERR_INVALID_PARAM;
7376 * When a printer is created, the drivername bound to the printer is used
7377 * to lookup previously saved driver initialization info, which is then
7378 * bound to the new printer, simulating what happens in the Windows arch.
7383 set_driver_init(printer, 2);
7387 /* A valid devmode was included, convert and link it
7389 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7391 if (!convert_devicemode(printer->info_2->printername, devmode,
7392 &printer->info_2->devmode))
7396 /* write the ASCII on disk */
7397 err = mod_a_printer(*printer, 2);
7398 if (!W_ERROR_IS_OK(err)) {
7399 free_a_printer(&printer,2);
7403 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7404 /* Handle open failed - remove addition. */
7405 del_a_printer(printer->info_2->sharename);
7406 free_a_printer(&printer,2);
7407 return WERR_ACCESS_DENIED;
7410 update_c_setprinter(False);
7411 free_a_printer(&printer,2);
7416 /****************************************************************************
7417 ****************************************************************************/
7419 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7421 UNISTR2 *uni_srv_name = &q_u->server_name;
7422 uint32 level = q_u->level;
7423 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7424 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7425 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7426 uint32 user_switch = q_u->user_switch;
7427 SPOOL_USER_CTR *user = &q_u->user_ctr;
7428 POLICY_HND *handle = &r_u->handle;
7432 /* we don't handle yet */
7433 /* but I know what to do ... */
7434 return WERR_UNKNOWN_LEVEL;
7436 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7438 user_switch, user, handle);
7440 return WERR_UNKNOWN_LEVEL;
7444 /****************************************************************************
7445 ****************************************************************************/
7447 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7449 uint32 level = q_u->level;
7450 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7451 WERROR err = WERR_OK;
7452 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7453 struct current_user user;
7454 fstring driver_name;
7457 ZERO_STRUCT(driver);
7459 get_current_user(&user, p);
7461 if (!convert_printer_driver_info(info, &driver, level)) {
7466 DEBUG(5,("Cleaning driver's information\n"));
7467 err = clean_up_driver_struct(driver, level, &user);
7468 if (!W_ERROR_IS_OK(err))
7471 DEBUG(5,("Moving driver to final destination\n"));
7472 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7473 if (W_ERROR_IS_OK(err))
7474 err = WERR_ACCESS_DENIED;
7478 if (add_a_printer_driver(driver, level)!=0) {
7479 err = WERR_ACCESS_DENIED;
7483 /* BEGIN_ADMIN_LOG */
7486 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7487 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7488 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7491 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7492 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7493 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7499 * I think this is where he DrvUpgradePrinter() hook would be
7500 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7501 * server. Right now, we just need to send ourselves a message
7502 * to update each printer bound to this driver. --jerry
7505 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7506 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7511 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7512 * decide if the driver init data should be deleted. The rules are:
7513 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7514 * 2) delete init data only if there is no 2k/Xp driver
7515 * 3) always delete init data
7516 * The generalized rule is always use init data from the highest order driver.
7517 * It is necessary to follow the driver install by an initialization step to
7518 * finish off this process.
7521 version = driver.info_3->cversion;
7522 else if (level == 6)
7523 version = driver.info_6->version;
7528 * 9x printer driver - never delete init data
7531 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7536 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7537 * there is no 2k/Xp driver init data for this driver name.
7541 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7543 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7545 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7547 if (!del_driver_init(driver_name))
7548 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7551 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7553 free_a_printer_driver(driver1,3);
7554 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7561 * 2k or Xp printer driver - always delete init data
7564 if (!del_driver_init(driver_name))
7565 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7569 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7575 free_a_printer_driver(driver, level);
7579 /********************************************************************
7580 * spoolss_addprinterdriverex
7581 ********************************************************************/
7583 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7585 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7586 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7589 * we only support the semantics of AddPrinterDriver()
7590 * i.e. only copy files that are newer than existing ones
7593 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7594 return WERR_ACCESS_DENIED;
7596 ZERO_STRUCT(q_u_local);
7597 ZERO_STRUCT(r_u_local);
7599 /* just pass the information off to _spoolss_addprinterdriver() */
7600 q_u_local.server_name_ptr = q_u->server_name_ptr;
7601 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7602 q_u_local.level = q_u->level;
7603 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7605 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7608 /****************************************************************************
7609 ****************************************************************************/
7611 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7613 init_unistr(&info->name, name);
7616 /****************************************************************************
7617 ****************************************************************************/
7619 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7623 const char *short_archi;
7624 DRIVER_DIRECTORY_1 *info=NULL;
7626 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7628 if (!(short_archi = get_short_archi(long_archi)))
7629 return WERR_INVALID_ENVIRONMENT;
7631 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7634 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7636 DEBUG(4,("printer driver directory: [%s]\n", path));
7638 fill_driverdir_1(info, path);
7640 *needed += spoolss_size_driverdir_info_1(info);
7642 if (!alloc_buffer_size(buffer, *needed)) {
7644 return WERR_INSUFFICIENT_BUFFER;
7647 smb_io_driverdir_1("", buffer, info, 0);
7651 if (*needed > offered)
7652 return WERR_INSUFFICIENT_BUFFER;
7657 /****************************************************************************
7658 ****************************************************************************/
7660 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7662 UNISTR2 *name = &q_u->name;
7663 UNISTR2 *uni_environment = &q_u->environment;
7664 uint32 level = q_u->level;
7665 NEW_BUFFER *buffer = NULL;
7666 uint32 offered = q_u->offered;
7667 uint32 *needed = &r_u->needed;
7669 /* that's an [in out] buffer */
7670 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7671 buffer = r_u->buffer;
7673 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7679 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7681 return WERR_UNKNOWN_LEVEL;
7685 /****************************************************************************
7686 ****************************************************************************/
7688 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7690 POLICY_HND *handle = &q_u->handle;
7691 uint32 idx = q_u->index;
7692 uint32 in_value_len = q_u->valuesize;
7693 uint32 in_data_len = q_u->datasize;
7694 uint32 *out_max_value_len = &r_u->valuesize;
7695 uint16 **out_value = &r_u->value;
7696 uint32 *out_value_len = &r_u->realvaluesize;
7697 uint32 *out_type = &r_u->type;
7698 uint32 *out_max_data_len = &r_u->datasize;
7699 uint8 **data_out = &r_u->data;
7700 uint32 *out_data_len = &r_u->realdatasize;
7702 NT_PRINTER_INFO_LEVEL *printer = NULL;
7704 uint32 biggest_valuesize;
7705 uint32 biggest_datasize;
7707 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7710 REGISTRY_VALUE *val = NULL;
7711 NT_PRINTER_DATA *p_data;
7712 int i, key_index, num_values;
7715 ZERO_STRUCT( printer );
7719 *out_max_data_len = 0;
7723 DEBUG(5,("spoolss_enumprinterdata\n"));
7726 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7730 if (!get_printer_snum(p,handle, &snum))
7733 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7734 if (!W_ERROR_IS_OK(result))
7737 p_data = &printer->info_2->data;
7738 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7743 * The NT machine wants to know the biggest size of value and data
7745 * cf: MSDN EnumPrinterData remark section
7748 if ( !in_value_len && !in_data_len && (key_index != -1) )
7750 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7752 biggest_valuesize = 0;
7753 biggest_datasize = 0;
7755 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7757 for ( i=0; i<num_values; i++ )
7759 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7761 name_length = strlen(val->valuename);
7762 if ( strlen(val->valuename) > biggest_valuesize )
7763 biggest_valuesize = name_length;
7765 if ( val->size > biggest_datasize )
7766 biggest_datasize = val->size;
7768 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7772 /* the value is an UNICODE string but real_value_size is the length
7773 in bytes including the trailing 0 */
7775 *out_value_len = 2 * (1+biggest_valuesize);
7776 *out_data_len = biggest_datasize;
7778 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7784 * the value len is wrong in NT sp3
7785 * that's the number of bytes not the number of unicode chars
7788 if ( key_index != -1 )
7789 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7794 /* out_value should default to "" or else NT4 has
7795 problems unmarshalling the response */
7797 *out_max_value_len=(in_value_len/sizeof(uint16));
7799 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7801 result = WERR_NOMEM;
7805 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7807 /* the data is counted in bytes */
7809 *out_max_data_len = in_data_len;
7810 *out_data_len = in_data_len;
7812 /* only allocate when given a non-zero data_len */
7814 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7816 result = WERR_NOMEM;
7820 result = WERR_NO_MORE_ITEMS;
7826 * - counted in bytes in the request
7827 * - counted in UNICODE chars in the max reply
7828 * - counted in bytes in the real size
7830 * take a pause *before* coding not *during* coding
7834 *out_max_value_len=(in_value_len/sizeof(uint16));
7835 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7837 result = WERR_NOMEM;
7841 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7845 *out_type = regval_type( val );
7847 /* data - counted in bytes */
7849 *out_max_data_len = in_data_len;
7850 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7852 result = WERR_NOMEM;
7855 data_len = (size_t)regval_size(val);
7856 memcpy( *data_out, regval_data_p(val), data_len );
7857 *out_data_len = data_len;
7861 free_a_printer(&printer, 2);
7865 /****************************************************************************
7866 ****************************************************************************/
7868 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7870 POLICY_HND *handle = &q_u->handle;
7871 UNISTR2 *value = &q_u->value;
7872 uint32 type = q_u->type;
7873 uint8 *data = q_u->data;
7874 uint32 real_len = q_u->real_len;
7876 NT_PRINTER_INFO_LEVEL *printer = NULL;
7878 WERROR status = WERR_OK;
7879 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7882 DEBUG(5,("spoolss_setprinterdata\n"));
7885 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7889 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7890 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7891 return WERR_INVALID_PARAM;
7894 if (!get_printer_snum(p,handle, &snum))
7898 * Access check : NT returns "access denied" if you make a
7899 * SetPrinterData call without the necessary privildge.
7900 * we were originally returning OK if nothing changed
7901 * which made Win2k issue **a lot** of SetPrinterData
7902 * when connecting to a printer --jerry
7905 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7907 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7908 status = WERR_ACCESS_DENIED;
7912 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7913 if (!W_ERROR_IS_OK(status))
7916 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7919 * When client side code sets a magic printer data key, detect it and save
7920 * the current printer data and the magic key's data (its the DEVMODE) for
7921 * future printer/driver initializations.
7923 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7925 /* Set devmode and printer initialization info */
7926 status = save_driver_init( printer, 2, data, real_len );
7928 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7932 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7933 type, data, real_len );
7934 if ( W_ERROR_IS_OK(status) )
7935 status = mod_a_printer(*printer, 2);
7939 free_a_printer(&printer, 2);
7944 /****************************************************************************
7945 ****************************************************************************/
7947 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7949 POLICY_HND *handle = &q_u->handle;
7950 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7953 DEBUG(5,("_spoolss_resetprinter\n"));
7956 * All we do is to check to see if the handle and queue is valid.
7957 * This call really doesn't mean anything to us because we only
7958 * support RAW printing. --jerry
7962 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7966 if (!get_printer_snum(p,handle, &snum))
7970 /* blindly return success */
7975 /****************************************************************************
7976 ****************************************************************************/
7978 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7980 POLICY_HND *handle = &q_u->handle;
7981 UNISTR2 *value = &q_u->valuename;
7983 NT_PRINTER_INFO_LEVEL *printer = NULL;
7985 WERROR status = WERR_OK;
7986 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7989 DEBUG(5,("spoolss_deleteprinterdata\n"));
7992 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7996 if (!get_printer_snum(p, handle, &snum))
7999 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8000 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8001 return WERR_ACCESS_DENIED;
8004 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8005 if (!W_ERROR_IS_OK(status))
8008 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8010 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8012 if ( W_ERROR_IS_OK(status) )
8013 mod_a_printer( *printer, 2 );
8015 free_a_printer(&printer, 2);
8020 /****************************************************************************
8021 ****************************************************************************/
8023 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8025 POLICY_HND *handle = &q_u->handle;
8026 FORM *form = &q_u->form;
8027 nt_forms_struct tmpForm;
8029 WERROR status = WERR_OK;
8030 NT_PRINTER_INFO_LEVEL *printer = NULL;
8033 nt_forms_struct *list=NULL;
8034 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8036 DEBUG(5,("spoolss_addform\n"));
8039 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8044 /* forms can be added on printer of on the print server handle */
8046 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8048 if (!get_printer_snum(p,handle, &snum))
8051 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8052 if (!W_ERROR_IS_OK(status))
8056 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8057 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8058 status = WERR_ACCESS_DENIED;
8062 /* can't add if builtin */
8064 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8065 status = WERR_ALREADY_EXISTS;
8069 count = get_ntforms(&list);
8071 if(!add_a_form(&list, form, &count)) {
8072 status = WERR_NOMEM;
8076 write_ntforms(&list, count);
8079 * ChangeID must always be set if this is a printer
8082 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8083 status = mod_a_printer(*printer, 2);
8087 free_a_printer(&printer, 2);
8093 /****************************************************************************
8094 ****************************************************************************/
8096 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8098 POLICY_HND *handle = &q_u->handle;
8099 UNISTR2 *form_name = &q_u->name;
8100 nt_forms_struct tmpForm;
8102 nt_forms_struct *list=NULL;
8103 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8105 WERROR status = WERR_OK;
8106 NT_PRINTER_INFO_LEVEL *printer = NULL;
8108 DEBUG(5,("spoolss_deleteform\n"));
8111 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8115 /* forms can be deleted on printer of on the print server handle */
8117 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8119 if (!get_printer_snum(p,handle, &snum))
8122 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8123 if (!W_ERROR_IS_OK(status))
8127 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8128 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8129 status = WERR_ACCESS_DENIED;
8133 /* can't delete if builtin */
8135 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8136 status = WERR_INVALID_PARAM;
8140 count = get_ntforms(&list);
8142 if ( !delete_a_form(&list, form_name, &count, &status ))
8146 * ChangeID must always be set if this is a printer
8149 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8150 status = mod_a_printer(*printer, 2);
8154 free_a_printer(&printer, 2);
8160 /****************************************************************************
8161 ****************************************************************************/
8163 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8165 POLICY_HND *handle = &q_u->handle;
8166 FORM *form = &q_u->form;
8167 nt_forms_struct tmpForm;
8169 WERROR status = WERR_OK;
8170 NT_PRINTER_INFO_LEVEL *printer = NULL;
8173 nt_forms_struct *list=NULL;
8174 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8176 DEBUG(5,("spoolss_setform\n"));
8179 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8183 /* forms can be modified on printer of on the print server handle */
8185 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8187 if (!get_printer_snum(p,handle, &snum))
8190 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8191 if (!W_ERROR_IS_OK(status))
8195 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8196 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8197 status = WERR_ACCESS_DENIED;
8201 /* can't set if builtin */
8202 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8203 status = WERR_INVALID_PARAM;
8207 count = get_ntforms(&list);
8208 update_a_form(&list, form, count);
8209 write_ntforms(&list, count);
8212 * ChangeID must always be set if this is a printer
8215 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8216 status = mod_a_printer(*printer, 2);
8221 free_a_printer(&printer, 2);
8227 /****************************************************************************
8228 enumprintprocessors level 1.
8229 ****************************************************************************/
8231 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8233 PRINTPROCESSOR_1 *info_1=NULL;
8235 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8240 init_unistr(&info_1->name, "winprint");
8242 *needed += spoolss_size_printprocessor_info_1(info_1);
8244 if (!alloc_buffer_size(buffer, *needed))
8245 return WERR_INSUFFICIENT_BUFFER;
8247 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8251 if (*needed > offered) {
8253 return WERR_INSUFFICIENT_BUFFER;
8259 /****************************************************************************
8260 ****************************************************************************/
8262 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8264 uint32 level = q_u->level;
8265 NEW_BUFFER *buffer = NULL;
8266 uint32 offered = q_u->offered;
8267 uint32 *needed = &r_u->needed;
8268 uint32 *returned = &r_u->returned;
8270 /* that's an [in out] buffer */
8271 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8272 buffer = r_u->buffer;
8274 DEBUG(5,("spoolss_enumprintprocessors\n"));
8277 * Enumerate the print processors ...
8279 * Just reply with "winprint", to keep NT happy
8280 * and I can use my nice printer checker.
8288 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8290 return WERR_UNKNOWN_LEVEL;
8294 /****************************************************************************
8295 enumprintprocdatatypes level 1.
8296 ****************************************************************************/
8298 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8300 PRINTPROCDATATYPE_1 *info_1=NULL;
8302 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8307 init_unistr(&info_1->name, "RAW");
8309 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8311 if (!alloc_buffer_size(buffer, *needed))
8312 return WERR_INSUFFICIENT_BUFFER;
8314 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8318 if (*needed > offered) {
8320 return WERR_INSUFFICIENT_BUFFER;
8326 /****************************************************************************
8327 ****************************************************************************/
8329 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8331 uint32 level = q_u->level;
8332 NEW_BUFFER *buffer = NULL;
8333 uint32 offered = q_u->offered;
8334 uint32 *needed = &r_u->needed;
8335 uint32 *returned = &r_u->returned;
8337 /* that's an [in out] buffer */
8338 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8339 buffer = r_u->buffer;
8341 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8348 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8350 return WERR_UNKNOWN_LEVEL;
8354 /****************************************************************************
8355 enumprintmonitors level 1.
8356 ****************************************************************************/
8358 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8360 PRINTMONITOR_1 *info_1=NULL;
8362 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8367 init_unistr(&info_1->name, "Local Port");
8369 *needed += spoolss_size_printmonitor_info_1(info_1);
8371 if (!alloc_buffer_size(buffer, *needed))
8372 return WERR_INSUFFICIENT_BUFFER;
8374 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8378 if (*needed > offered) {
8380 return WERR_INSUFFICIENT_BUFFER;
8386 /****************************************************************************
8387 enumprintmonitors level 2.
8388 ****************************************************************************/
8390 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8392 PRINTMONITOR_2 *info_2=NULL;
8394 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8399 init_unistr(&info_2->name, "Local Port");
8400 init_unistr(&info_2->environment, "Windows NT X86");
8401 init_unistr(&info_2->dll_name, "localmon.dll");
8403 *needed += spoolss_size_printmonitor_info_2(info_2);
8405 if (!alloc_buffer_size(buffer, *needed))
8406 return WERR_INSUFFICIENT_BUFFER;
8408 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8412 if (*needed > offered) {
8414 return WERR_INSUFFICIENT_BUFFER;
8420 /****************************************************************************
8421 ****************************************************************************/
8423 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8425 uint32 level = q_u->level;
8426 NEW_BUFFER *buffer = NULL;
8427 uint32 offered = q_u->offered;
8428 uint32 *needed = &r_u->needed;
8429 uint32 *returned = &r_u->returned;
8431 /* that's an [in out] buffer */
8432 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8433 buffer = r_u->buffer;
8435 DEBUG(5,("spoolss_enumprintmonitors\n"));
8438 * Enumerate the print monitors ...
8440 * Just reply with "Local Port", to keep NT happy
8441 * and I can use my nice printer checker.
8449 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8451 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8453 return WERR_UNKNOWN_LEVEL;
8457 /****************************************************************************
8458 ****************************************************************************/
8460 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8464 JOB_INFO_1 *info_1=NULL;
8466 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8468 if (info_1 == NULL) {
8472 for (i=0; i<count && found==False; i++) {
8473 if ((*queue)[i].job==(int)jobid)
8479 /* NT treats not found as bad param... yet another bad choice */
8480 return WERR_INVALID_PARAM;
8483 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8485 *needed += spoolss_size_job_info_1(info_1);
8487 if (!alloc_buffer_size(buffer, *needed)) {
8489 return WERR_INSUFFICIENT_BUFFER;
8492 smb_io_job_info_1("", buffer, info_1, 0);
8496 if (*needed > offered)
8497 return WERR_INSUFFICIENT_BUFFER;
8502 /****************************************************************************
8503 ****************************************************************************/
8505 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8510 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8512 DEVICEMODE *devmode = NULL;
8513 NT_DEVICEMODE *nt_devmode = NULL;
8515 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8517 ZERO_STRUCTP(info_2);
8519 if (info_2 == NULL) {
8524 for ( i=0; i<count && found==False; i++ )
8526 if ((*queue)[i].job == (int)jobid)
8532 /* NT treats not found as bad param... yet another bad
8534 ret = WERR_INVALID_PARAM;
8538 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8539 if (!W_ERROR_IS_OK(ret))
8543 * if the print job does not have a DEVMODE associated with it,
8544 * just use the one for the printer. A NULL devicemode is not
8545 * a failure condition
8548 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8549 devmode = construct_dev_mode(snum);
8551 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8552 ZERO_STRUCTP( devmode );
8553 convert_nt_devicemode( devmode, nt_devmode );
8557 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8559 *needed += spoolss_size_job_info_2(info_2);
8561 if (!alloc_buffer_size(buffer, *needed)) {
8562 ret = WERR_INSUFFICIENT_BUFFER;
8566 smb_io_job_info_2("", buffer, info_2, 0);
8568 if (*needed > offered) {
8569 ret = WERR_INSUFFICIENT_BUFFER;
8576 /* Cleanup allocated memory */
8578 free_job_info_2(info_2); /* Also frees devmode */
8580 free_a_printer(&ntprinter, 2);
8585 /****************************************************************************
8586 ****************************************************************************/
8588 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8590 POLICY_HND *handle = &q_u->handle;
8591 uint32 jobid = q_u->jobid;
8592 uint32 level = q_u->level;
8593 NEW_BUFFER *buffer = NULL;
8594 uint32 offered = q_u->offered;
8595 uint32 *needed = &r_u->needed;
8596 WERROR wstatus = WERR_OK;
8600 print_queue_struct *queue = NULL;
8601 print_status_struct prt_status;
8603 /* that's an [in out] buffer */
8604 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8605 buffer = r_u->buffer;
8607 DEBUG(5,("spoolss_getjob\n"));
8611 if (!get_printer_snum(p, handle, &snum))
8614 count = print_queue_status(snum, &queue, &prt_status);
8616 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8617 count, prt_status.status, prt_status.message));
8621 wstatus = getjob_level_1(&queue, count, snum, jobid,
8622 buffer, offered, needed);
8625 wstatus = getjob_level_2(&queue, count, snum, jobid,
8626 buffer, offered, needed);
8629 wstatus = WERR_UNKNOWN_LEVEL;
8637 /********************************************************************
8638 spoolss_getprinterdataex
8640 From MSDN documentation of GetPrinterDataEx: pass request
8641 to GetPrinterData if key is "PrinterDriverData".
8642 ********************************************************************/
8644 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8646 POLICY_HND *handle = &q_u->handle;
8647 uint32 in_size = q_u->size;
8648 uint32 *type = &r_u->type;
8649 uint32 *out_size = &r_u->size;
8650 uint8 **data = &r_u->data;
8651 uint32 *needed = &r_u->needed;
8652 fstring keyname, valuename;
8654 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8656 NT_PRINTER_INFO_LEVEL *printer = NULL;
8658 WERROR status = WERR_OK;
8660 DEBUG(4,("_spoolss_getprinterdataex\n"));
8662 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8663 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8665 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8666 keyname, valuename));
8668 /* in case of problem, return some default values */
8672 *out_size = in_size;
8675 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8676 status = WERR_BADFID;
8680 /* Is the handle to a printer or to the server? */
8682 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8683 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8684 status = WERR_INVALID_PARAM;
8688 if ( !get_printer_snum(p,handle, &snum) )
8691 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8692 if ( !W_ERROR_IS_OK(status) )
8695 /* check to see if the keyname is valid */
8696 if ( !strlen(keyname) ) {
8697 status = WERR_INVALID_PARAM;
8701 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8702 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8703 free_a_printer( &printer, 2 );
8704 status = WERR_BADFILE;
8708 /* When given a new keyname, we should just create it */
8710 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8712 if (*needed > *out_size)
8713 status = WERR_MORE_DATA;
8716 if ( !W_ERROR_IS_OK(status) )
8718 DEBUG(5, ("error: allocating %d\n", *out_size));
8720 /* reply this param doesn't exist */
8724 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8725 status = WERR_NOMEM;
8735 free_a_printer( &printer, 2 );
8740 /********************************************************************
8741 * spoolss_setprinterdataex
8742 ********************************************************************/
8744 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8746 POLICY_HND *handle = &q_u->handle;
8747 uint32 type = q_u->type;
8748 uint8 *data = q_u->data;
8749 uint32 real_len = q_u->real_len;
8751 NT_PRINTER_INFO_LEVEL *printer = NULL;
8753 WERROR status = WERR_OK;
8754 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8759 DEBUG(4,("_spoolss_setprinterdataex\n"));
8761 /* From MSDN documentation of SetPrinterDataEx: pass request to
8762 SetPrinterData if key is "PrinterDriverData" */
8765 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8769 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8770 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8771 return WERR_INVALID_PARAM;
8774 if ( !get_printer_snum(p,handle, &snum) )
8778 * Access check : NT returns "access denied" if you make a
8779 * SetPrinterData call without the necessary privildge.
8780 * we were originally returning OK if nothing changed
8781 * which made Win2k issue **a lot** of SetPrinterData
8782 * when connecting to a printer --jerry
8785 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8787 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8788 return WERR_ACCESS_DENIED;
8791 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8792 if (!W_ERROR_IS_OK(status))
8795 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8796 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8798 /* check for OID in valuename */
8800 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8806 /* save the registry data */
8808 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8810 if ( W_ERROR_IS_OK(status) )
8812 /* save the OID if one was specified */
8814 fstrcat( keyname, "\\" );
8815 fstrcat( keyname, SPOOL_OID_KEY );
8818 * I'm not checking the status here on purpose. Don't know
8819 * if this is right, but I'm returning the status from the
8820 * previous set_printer_dataex() call. I have no idea if
8821 * this is right. --jerry
8824 set_printer_dataex( printer, keyname, valuename,
8825 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8828 status = mod_a_printer(*printer, 2);
8831 free_a_printer(&printer, 2);
8837 /********************************************************************
8838 * spoolss_deleteprinterdataex
8839 ********************************************************************/
8841 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8843 POLICY_HND *handle = &q_u->handle;
8844 UNISTR2 *value = &q_u->valuename;
8845 UNISTR2 *key = &q_u->keyname;
8847 NT_PRINTER_INFO_LEVEL *printer = NULL;
8849 WERROR status = WERR_OK;
8850 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8851 pstring valuename, keyname;
8853 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8856 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8860 if (!get_printer_snum(p, handle, &snum))
8863 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8864 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8865 return WERR_ACCESS_DENIED;
8868 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8869 if (!W_ERROR_IS_OK(status))
8872 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8873 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8875 status = delete_printer_dataex( printer, keyname, valuename );
8877 if ( W_ERROR_IS_OK(status) )
8878 mod_a_printer( *printer, 2 );
8880 free_a_printer(&printer, 2);
8885 /********************************************************************
8886 * spoolss_enumprinterkey
8887 ********************************************************************/
8890 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8893 fstring *keynames = NULL;
8894 uint16 *enumkeys = NULL;
8897 POLICY_HND *handle = &q_u->handle;
8898 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8899 NT_PRINTER_DATA *data;
8900 NT_PRINTER_INFO_LEVEL *printer = NULL;
8902 WERROR status = WERR_BADFILE;
8905 DEBUG(4,("_spoolss_enumprinterkey\n"));
8908 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8912 if ( !get_printer_snum(p,handle, &snum) )
8915 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8916 if (!W_ERROR_IS_OK(status))
8919 /* get the list of subkey names */
8921 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8922 data = &printer->info_2->data;
8924 num_keys = get_printer_subkeys( data, key, &keynames );
8926 if ( num_keys == -1 ) {
8927 status = WERR_BADFILE;
8931 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8933 r_u->needed = printerkey_len*2;
8935 if ( q_u->size < r_u->needed ) {
8936 status = WERR_MORE_DATA;
8940 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8941 status = WERR_NOMEM;
8947 if ( q_u->size < r_u->needed )
8948 status = WERR_MORE_DATA;
8951 free_a_printer( &printer, 2 );
8952 SAFE_FREE( keynames );
8957 /********************************************************************
8958 * spoolss_deleteprinterkey
8959 ********************************************************************/
8961 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8963 POLICY_HND *handle = &q_u->handle;
8964 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8966 NT_PRINTER_INFO_LEVEL *printer = NULL;
8970 DEBUG(5,("spoolss_deleteprinterkey\n"));
8973 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8977 /* if keyname == NULL, return error */
8979 if ( !q_u->keyname.buffer )
8980 return WERR_INVALID_PARAM;
8982 if (!get_printer_snum(p, handle, &snum))
8985 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8986 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8987 return WERR_ACCESS_DENIED;
8990 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8991 if (!W_ERROR_IS_OK(status))
8994 /* delete the key and all subneys */
8996 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8998 status = delete_all_printer_data( printer->info_2, key );
9000 if ( W_ERROR_IS_OK(status) )
9001 status = mod_a_printer(*printer, 2);
9003 free_a_printer( &printer, 2 );
9009 /********************************************************************
9010 * spoolss_enumprinterdataex
9011 ********************************************************************/
9013 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9015 POLICY_HND *handle = &q_u->handle;
9016 uint32 in_size = q_u->size;
9019 NT_PRINTER_INFO_LEVEL *printer = NULL;
9020 PRINTER_ENUM_VALUES *enum_values = NULL;
9021 NT_PRINTER_DATA *p_data;
9023 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9028 REGISTRY_VALUE *val;
9033 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9036 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9041 * first check for a keyname of NULL or "". Win2k seems to send
9042 * this a lot and we should send back WERR_INVALID_PARAM
9043 * no need to spend time looking up the printer in this case.
9047 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9048 if ( !strlen(key) ) {
9049 result = WERR_INVALID_PARAM;
9053 /* get the printer off of disk */
9055 if (!get_printer_snum(p,handle, &snum))
9058 ZERO_STRUCT(printer);
9059 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9060 if (!W_ERROR_IS_OK(result))
9063 /* now look for a match on the key name */
9065 p_data = &printer->info_2->data;
9067 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9068 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9070 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9071 result = WERR_INVALID_PARAM;
9078 /* allocate the memory for the array of pointers -- if necessary */
9080 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9083 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9085 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9086 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9087 result = WERR_NOMEM;
9091 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9095 * loop through all params and build the array to pass
9096 * back to the client
9099 for ( i=0; i<num_entries; i++ )
9101 /* lookup the registry value */
9103 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9104 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9108 value_name = regval_name( val );
9109 init_unistr( &enum_values[i].valuename, value_name );
9110 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9111 enum_values[i].type = regval_type( val );
9113 data_len = regval_size( val );
9115 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9117 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9119 result = WERR_NOMEM;
9123 enum_values[i].data_len = data_len;
9125 /* keep track of the size of the array in bytes */
9127 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9130 /* housekeeping information in the reply */
9132 r_u->needed = needed;
9133 r_u->returned = num_entries;
9135 if (needed > in_size) {
9136 result = WERR_MORE_DATA;
9140 /* copy data into the reply */
9142 r_u->ctr.size = r_u->needed;
9143 r_u->ctr.size_of_array = r_u->returned;
9144 r_u->ctr.values = enum_values;
9150 free_a_printer(&printer, 2);
9155 /****************************************************************************
9156 ****************************************************************************/
9158 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9160 init_unistr(&info->name, name);
9163 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9164 UNISTR2 *environment,
9171 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9173 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9175 if (!get_short_archi(long_archi))
9176 return WERR_INVALID_ENVIRONMENT;
9178 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9181 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9183 fill_printprocessordirectory_1(info, path);
9185 *needed += spoolss_size_printprocessordirectory_info_1(info);
9187 if (!alloc_buffer_size(buffer, *needed)) {
9189 return WERR_INSUFFICIENT_BUFFER;
9192 smb_io_printprocessordirectory_1("", buffer, info, 0);
9196 if (*needed > offered)
9197 return WERR_INSUFFICIENT_BUFFER;
9202 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9204 uint32 level = q_u->level;
9205 NEW_BUFFER *buffer = NULL;
9206 uint32 offered = q_u->offered;
9207 uint32 *needed = &r_u->needed;
9210 /* that's an [in out] buffer */
9211 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9212 buffer = r_u->buffer;
9214 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9220 result = getprintprocessordirectory_level_1
9221 (&q_u->name, &q_u->environment, buffer, offered, needed);
9224 result = WERR_UNKNOWN_LEVEL;
9232 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9233 SPOOL_R_REPLYOPENPRINTER *r_u)
9235 DEBUG(5,("_spoolss_replyopenprinter\n"));
9237 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9242 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9243 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9245 DEBUG(5,("_spoolss_replycloseprinter\n"));