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. */
31 extern userdom_struct current_user_info;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 /* Table to map the driver version */
46 static const char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 static const char *get_drv_ver_to_os(int ver)
55 if (ver < 0 || ver > 3)
57 return drv_ver_to_os[ver];
61 const char *long_archi;
62 const char *short_archi;
66 static Printer_entry *printers_list;
68 typedef struct _counter_printer_0 {
69 struct _counter_printer_0 *next;
70 struct _counter_printer_0 *prev;
76 static counter_printer_0 *counter_list;
78 static struct cli_state notify_cli; /* print notify back-channel */
79 static uint32 smb_connections=0;
82 /* in printing/nt_printing.c */
84 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
96 return JOB_STATUS_PAUSED;
98 return JOB_STATUS_SPOOLING;
100 return JOB_STATUS_PRINTING;
102 return JOB_STATUS_ERROR;
104 return JOB_STATUS_DELETING;
106 return JOB_STATUS_OFFLINE;
108 return JOB_STATUS_PAPEROUT;
110 return JOB_STATUS_PRINTED;
112 return JOB_STATUS_DELETED;
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
121 static int nt_printq_status(int v)
125 return PRINTER_STATUS_PAUSED;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
143 SAFE_FREE((*pp)->ctr.type);
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle);
171 if (!W_ERROR_IS_OK(result))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 dos_errstr(result)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections==1) {
177 cli_nt_session_close(¬ify_cli);
178 cli_ulogoff(¬ify_cli);
179 cli_shutdown(¬ify_cli);
180 message_deregister(MSG_PRINTER_NOTIFY2);
182 /* Tell the connections db we're no longer interested in
183 * printer notify messages. */
185 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
191 /****************************************************************************
192 Functions to free a printer entry datastruct.
193 ****************************************************************************/
195 static void free_printer_entry(void *ptr)
197 Printer_entry *Printer = (Printer_entry *)ptr;
199 if (Printer->notify.client_connected==True) {
202 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
204 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
205 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
206 snum = print_queue_snum(Printer->sharename);
208 srv_spoolss_replycloseprinter(snum,
209 &Printer->notify.client_hnd);
213 Printer->notify.flags=0;
214 Printer->notify.options=0;
215 Printer->notify.localmachine[0]='\0';
216 Printer->notify.printerlocal=0;
217 free_spool_notify_option(&Printer->notify.option);
218 Printer->notify.option=NULL;
219 Printer->notify.client_connected=False;
221 free_nt_devicemode( &Printer->nt_devmode );
222 free_a_printer( &Printer->printer_info, 2 );
224 talloc_destroy( Printer->ctx );
226 /* Remove from the internal list. */
227 DLIST_REMOVE(printers_list, Printer);
232 /****************************************************************************
233 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
234 ****************************************************************************/
236 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
238 SPOOL_NOTIFY_OPTION *new_sp = NULL;
243 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
250 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
252 if (!new_sp->ctr.type) {
261 /****************************************************************************
262 find printer index by handle
263 ****************************************************************************/
265 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
267 Printer_entry *find_printer = NULL;
269 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
270 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
277 /****************************************************************************
278 look for a printer object cached on an open printer handle
279 ****************************************************************************/
281 WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2,
282 const char *servername, const char *printername )
286 DEBUG(10,("find_printer_in_print_hnd_cache: printer [\\\\%s\\%s]\n",
287 servername, printername));
289 for ( p=printers_list; p; p=p->next )
291 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
293 && strequal( p->sharename, printername )
294 && strequal( p->servername, servername ) )
296 DEBUG(10,("Found printer\n"));
297 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
303 return WERR_INVALID_PRINTER_NAME;
306 /****************************************************************************
307 destroy any cached printer_info_2 structures on open handles
308 ****************************************************************************/
310 void invalidate_printer_hnd_cache( char *printername )
314 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
316 for ( p=printers_list; p; p=p->next )
318 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
320 && StrCaseCmp(p->sharename, printername)==0)
322 DEBUG(10,("invalidating printer_info cache for handl:\n"));
323 free_a_printer( &p->printer_info, 2 );
324 p->printer_info = NULL;
330 /****************************************************************************
331 Close printer index by handle.
332 ****************************************************************************/
334 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
336 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
339 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
343 close_policy_hnd(p, hnd);
348 /****************************************************************************
349 Delete a printer given a handle.
350 ****************************************************************************/
352 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
354 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
357 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
362 * It turns out that Windows allows delete printer on a handle
363 * opened by an admin user, then used on a pipe handle created
364 * by an anonymous user..... but they're working on security.... riiight !
368 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
369 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
370 return WERR_ACCESS_DENIED;
374 /* Check calling user has permission to delete printer. Note that
375 since we set the snum parameter to -1 only administrators can
376 delete the printer. This stops people with the Full Control
377 permission from deleting the printer. */
379 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
380 DEBUG(3, ("printer delete denied by security descriptor\n"));
381 return WERR_ACCESS_DENIED;
385 /* this does not need a become root since the access check has been
386 done on the handle already */
388 if (del_a_printer( Printer->sharename ) != 0) {
389 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
393 /* the delete printer script shoudl be run as root if the user has perms */
395 if (*lp_deleteprinter_cmd()) {
397 char *cmd = lp_deleteprinter_cmd();
400 SE_PRIV se_printop = SE_PRINT_OPERATOR;
403 pstr_sprintf(command, "%s \"%s\"", cmd, Printer->sharename);
405 is_print_op = user_has_privileges( p->pipe_user.nt_user_token, &se_printop );
407 DEBUG(10,("Running [%s]\n", command));
409 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
414 if ( (ret = smbrun(command, NULL)) == 0 ) {
415 /* Tell everyone we updated smb.conf. */
416 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
422 /********** END SePrintOperatorPrivlege BLOCK **********/
424 DEBUGADD(10,("returned [%d]\n", ret));
427 return WERR_BADFID; /* What to return here? */
429 /* go ahead and re-read the services immediately */
430 reload_services( False );
432 if ( lp_servicenumber( Printer->sharename ) < 0 )
433 return WERR_ACCESS_DENIED;
439 /****************************************************************************
440 Return the snum of a printer corresponding to an handle.
441 ****************************************************************************/
443 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
445 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
448 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
452 switch (Printer->printer_type) {
453 case PRINTER_HANDLE_IS_PRINTER:
454 DEBUG(4,("short name:%s\n", Printer->sharename));
455 *number = print_queue_snum(Printer->sharename);
456 return (*number != -1);
457 case PRINTER_HANDLE_IS_PRINTSERVER:
464 /****************************************************************************
465 Set printer handle type.
466 Check if it's \\server or \\server\printer
467 ****************************************************************************/
469 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
471 DEBUG(3,("Setting printer type=%s\n", handlename));
473 if ( strlen(handlename) < 3 ) {
474 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
478 /* it's a print server */
479 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
480 DEBUGADD(4,("Printer is a print server\n"));
481 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
485 DEBUGADD(4,("Printer is a printer\n"));
486 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
492 /****************************************************************************
493 Set printer handle name.
494 ****************************************************************************/
496 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
499 int n_services=lp_numservices();
500 char *aprinter, *printername;
501 const char *servername;
504 NT_PRINTER_INFO_LEVEL *printer;
507 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
509 aprinter = handlename;
510 if ( *handlename == '\\' ) {
511 servername = handlename + 2;
512 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
521 /* save the servername to fill in replies on this handle */
523 if ( !is_myname_or_ipaddr( servername ) )
526 fstrcpy( Printer->servername, servername );
528 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
531 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
534 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
536 /* Search all sharenames first as this is easier than pulling
537 the printer_info_2 off of disk */
539 snum = find_service(aprinter);
541 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
543 fstrcpy( sname, aprinter );
546 /* do another loop to look for printernames */
548 for (snum=0; !found && snum<n_services; snum++) {
550 /* no point in checking if this is not a printer or
551 we aren't allowing printername != sharename */
553 if ( !(lp_snum_ok(snum)
555 && !lp_force_printername(snum)) )
560 fstrcpy(sname, lp_servicename(snum));
563 result = get_a_printer( NULL, &printer, 2, sname );
564 if ( !W_ERROR_IS_OK(result) ) {
565 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
566 sname, dos_errstr(result)));
570 /* printername is always returned as \\server\printername */
571 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
572 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
573 printer->info_2->printername));
574 free_a_printer( &printer, 2);
580 if ( strequal(printername, aprinter) ) {
584 DEBUGADD(10, ("printername: %s\n", printername));
586 free_a_printer( &printer, 2);
590 DEBUGADD(4,("Printer not found\n"));
594 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
596 fstrcpy(Printer->sharename, sname);
601 /****************************************************************************
602 Find first available printer slot. creates a printer handle for you.
603 ****************************************************************************/
605 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
607 Printer_entry *new_printer;
609 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
611 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
614 ZERO_STRUCTP(new_printer);
616 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
617 SAFE_FREE(new_printer);
621 /* Add to the internal list. */
622 DLIST_ADD(printers_list, new_printer);
624 new_printer->notify.option=NULL;
626 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
627 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
628 close_printer_handle(p, hnd);
632 if (!set_printer_hnd_printertype(new_printer, name)) {
633 close_printer_handle(p, hnd);
637 if (!set_printer_hnd_name(new_printer, name)) {
638 close_printer_handle(p, hnd);
642 new_printer->access_granted = access_granted;
644 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
649 /***************************************************************************
650 check to see if the client motify handle is monitoring the notification
651 given by (notify_type, notify_field).
652 **************************************************************************/
654 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
660 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
663 SPOOL_NOTIFY_OPTION *option = p->notify.option;
667 * Flags should always be zero when the change notify
668 * is registered by the client's spooler. A user Win32 app
669 * might use the flags though instead of the NOTIFY_OPTION_INFO
678 return is_monitoring_event_flags(
679 p->notify.flags, notify_type, notify_field);
681 for (i = 0; i < option->count; i++) {
683 /* Check match for notify_type */
685 if (option->ctr.type[i].type != notify_type)
688 /* Check match for field */
690 for (j = 0; j < option->ctr.type[i].count; j++) {
691 if (option->ctr.type[i].fields[j] == notify_field) {
697 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
698 p->servername, p->sharename, 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 = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
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_ARRAY( ctr->ctx, ctr->msg_groups, 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_ARRAY( ctr->ctx, msg_grp->msgs, 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\\%s]\n", p->servername, p->sharename));
996 /* For this printer? Print servers always receive
999 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1000 ( !strequal(msg_group->printername, p->sharename) ) )
1003 DEBUG(10,("Our printer\n"));
1005 /* allocate the max entries possible */
1007 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
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 [0x%x] field [0x%2x] for printer [%s]\n",
1026 msg->type, msg->field, p->sharename));
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 /* add to correct list in container */
1195 notify_msg_ctr_addmsg( &messages, ¬ify );
1197 /* free memory that might have been allocated by notify2_unpack_msg() */
1199 if ( notify.len != 0 )
1200 SAFE_FREE( notify.notify.data );
1203 /* process each group of messages */
1205 num_groups = notify_msg_ctr_numgroups( &messages );
1206 for ( i=0; i<num_groups; i++ )
1207 send_notify2_changes( &messages, i );
1212 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1214 notify_msg_ctr_destroy( &messages );
1219 /********************************************************************
1220 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1221 one smbd, all of processes must clear their printer cache immediately.
1222 ********************************************************************/
1224 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1226 fstring printername;
1228 fstrcpy( printername, buf );
1230 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1232 invalidate_printer_hnd_cache( printername );
1235 /********************************************************************
1236 Send a message to ourself about new driver being installed
1237 so we can upgrade the information for each printer bound to this
1239 ********************************************************************/
1241 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1243 int len = strlen(drivername);
1248 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1251 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1256 /**********************************************************************
1257 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1258 over all printers, upgrading ones as necessary
1259 **********************************************************************/
1261 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1265 int n_services = lp_numservices();
1267 len = MIN(len,sizeof(drivername)-1);
1268 strncpy(drivername, buf, len);
1270 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1272 /* Iterate the printer list */
1274 for (snum=0; snum<n_services; snum++)
1276 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1279 NT_PRINTER_INFO_LEVEL *printer = NULL;
1281 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1282 if (!W_ERROR_IS_OK(result))
1285 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1287 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1289 /* all we care about currently is the change_id */
1291 result = mod_a_printer(printer, 2);
1292 if (!W_ERROR_IS_OK(result)) {
1293 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1294 dos_errstr(result)));
1298 free_a_printer(&printer, 2);
1305 /********************************************************************
1306 Update the cache for all printq's with a registered client
1308 ********************************************************************/
1310 void update_monitored_printq_cache( void )
1312 Printer_entry *printer = printers_list;
1315 /* loop through all printers and update the cache where
1316 client_connected == True */
1319 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1320 && printer->notify.client_connected )
1322 snum = print_queue_snum(printer->sharename);
1323 print_queue_status( snum, NULL, NULL );
1326 printer = printer->next;
1331 /********************************************************************
1332 Send a message to ourself about new driver being installed
1333 so we can upgrade the information for each printer bound to this
1335 ********************************************************************/
1337 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1339 int len = strlen(drivername);
1344 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1347 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1352 /**********************************************************************
1353 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1354 over all printers, resetting printer data as neessary
1355 **********************************************************************/
1357 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1361 int n_services = lp_numservices();
1363 len = MIN( len, sizeof(drivername)-1 );
1364 strncpy( drivername, buf, len );
1366 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1368 /* Iterate the printer list */
1370 for ( snum=0; snum<n_services; snum++ )
1372 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1375 NT_PRINTER_INFO_LEVEL *printer = NULL;
1377 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1378 if ( !W_ERROR_IS_OK(result) )
1382 * if the printer is bound to the driver,
1383 * then reset to the new driver initdata
1386 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1388 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1390 if ( !set_driver_init(printer, 2) ) {
1391 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1392 printer->info_2->printername, printer->info_2->drivername));
1395 result = mod_a_printer( printer, 2 );
1396 if ( !W_ERROR_IS_OK(result) ) {
1397 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1398 get_dos_error_msg(result)));
1402 free_a_printer( &printer, 2 );
1411 /********************************************************************
1412 Copy routines used by convert_to_openprinterex()
1413 *******************************************************************/
1415 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1423 DEBUG (8,("dup_devmode\n"));
1425 /* bulk copy first */
1427 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1431 /* dup the pointer members separately */
1433 len = unistrlen(devmode->devicename.buffer);
1435 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1436 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1441 len = unistrlen(devmode->formname.buffer);
1443 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1444 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1448 d->private = TALLOC_MEMDUP(ctx, devmode->private, devmode->driverextra);
1453 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1455 if (!new_ctr || !ctr)
1458 DEBUG(8,("copy_devmode_ctr\n"));
1460 new_ctr->size = ctr->size;
1461 new_ctr->devmode_ptr = ctr->devmode_ptr;
1463 if(ctr->devmode_ptr)
1464 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1467 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1469 if (!new_def || !def)
1472 DEBUG(8,("copy_printer_defaults\n"));
1474 new_def->datatype_ptr = def->datatype_ptr;
1476 if (def->datatype_ptr)
1477 copy_unistr2(&new_def->datatype, &def->datatype);
1479 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1481 new_def->access_required = def->access_required;
1484 /********************************************************************
1485 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1486 * SPOOL_Q_OPEN_PRINTER_EX structure
1487 ********************************************************************/
1489 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1491 if (!q_u_ex || !q_u)
1494 DEBUG(8,("convert_to_openprinterex\n"));
1496 if ( q_u->printername ) {
1497 q_u_ex->printername = TALLOC_P( ctx, UNISTR2 );
1498 copy_unistr2(q_u_ex->printername, q_u->printername);
1501 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1504 /********************************************************************
1505 * spoolss_open_printer
1507 * called from the spoolss dispatcher
1508 ********************************************************************/
1510 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1512 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1513 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1518 ZERO_STRUCT(q_u_ex);
1519 ZERO_STRUCT(r_u_ex);
1521 /* convert the OpenPrinter() call to OpenPrinterEx() */
1523 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1525 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1527 /* convert back to OpenPrinter() */
1529 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1534 /********************************************************************
1535 * spoolss_open_printer
1537 * If the openprinterex rpc call contains a devmode,
1538 * it's a per-user one. This per-user devmode is derivated
1539 * from the global devmode. Openprinterex() contains a per-user
1540 * devmode for when you do EMF printing and spooling.
1541 * In the EMF case, the NT workstation is only doing half the job
1542 * of rendering the page. The other half is done by running the printer
1543 * driver on the server.
1544 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1545 * The EMF file only contains what is to be printed on the page.
1546 * So in order for the server to know how to print, the NT client sends
1547 * a devicemode attached to the openprinterex call.
1548 * But this devicemode is short lived, it's only valid for the current print job.
1550 * If Samba would have supported EMF spooling, this devicemode would
1551 * have been attached to the handle, to sent it to the driver to correctly
1552 * rasterize the EMF file.
1554 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1555 * we just act as a pass-thru between windows and the printer.
1557 * In order to know that Samba supports only RAW spooling, NT has to call
1558 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1559 * and until NT sends a RAW job, we refuse it.
1561 * But to call getprinter() or startdoc(), you first need a valid handle,
1562 * and to get an handle you have to call openprintex(). Hence why you have
1563 * a devicemode in the openprinterex() call.
1566 * Differences between NT4 and NT 2000.
1569 * On NT4, you only have a global devicemode. This global devicemode can be changed
1570 * by the administrator (or by a user with enough privs). Everytime a user
1571 * wants to print, the devicemode is resetted to the default. In Word, everytime
1572 * you print, the printer's characteristics are always reset to the global devicemode.
1576 * In W2K, there is the notion of per-user devicemode. The first time you use
1577 * a printer, a per-user devicemode is build from the global devicemode.
1578 * If you change your per-user devicemode, it is saved in the registry, under the
1579 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1580 * printer preferences available.
1582 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1583 * on the General Tab of the printer properties windows.
1585 * To change the global devicemode: it's the "Printing Defaults..." button
1586 * on the Advanced Tab of the printer properties window.
1589 ********************************************************************/
1591 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1593 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1594 POLICY_HND *handle = &r_u->handle;
1598 struct current_user user;
1599 Printer_entry *Printer=NULL;
1601 if ( !q_u->printername )
1602 return WERR_INVALID_PRINTER_NAME;
1604 /* some sanity check because you can open a printer or a print server */
1605 /* aka: \\server\printer or \\server */
1607 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1609 DEBUGADD(3,("checking name: %s\n",name));
1611 if (!open_printer_hnd(p, handle, name, 0))
1612 return WERR_INVALID_PRINTER_NAME;
1614 Printer=find_printer_index_by_hnd(p, handle);
1616 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1617 "handle we created for printer %s\n", name ));
1618 close_printer_handle(p,handle);
1619 return WERR_INVALID_PRINTER_NAME;
1622 get_current_user(&user, p);
1625 * First case: the user is opening the print server:
1627 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1628 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1630 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1631 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1632 * or if the user is listed in the smb.conf printer admin parameter.
1634 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1635 * client view printer folder, but does not show the MSAPW.
1637 * Note: this test needs code to check access rights here too. Jeremy
1638 * could you look at this?
1640 * Second case: the user is opening a printer:
1641 * NT doesn't let us connect to a printer if the connecting user
1642 * doesn't have print permission.
1645 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1647 /* Printserver handles use global struct... */
1651 /* Map standard access rights to object specific access rights */
1653 se_map_standard(&printer_default->access_required,
1654 &printserver_std_mapping);
1656 /* Deny any object specific bits that don't apply to print
1657 servers (i.e printer and job specific bits) */
1659 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1661 if (printer_default->access_required &
1662 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1663 DEBUG(3, ("access DENIED for non-printserver bits"));
1664 close_printer_handle(p, handle);
1665 return WERR_ACCESS_DENIED;
1668 /* Allow admin access */
1670 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1672 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1674 if (!lp_ms_add_printer_wizard()) {
1675 close_printer_handle(p, handle);
1676 return WERR_ACCESS_DENIED;
1679 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1680 and not a printer admin, then fail */
1683 && !user_has_privileges( user.nt_user_token, &se_printop )
1684 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1686 close_printer_handle(p, handle);
1687 return WERR_ACCESS_DENIED;
1690 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1694 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1697 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1698 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1700 /* We fall through to return WERR_OK */
1705 /* NT doesn't let us connect to a printer if the connecting user
1706 doesn't have print permission. */
1708 if (!get_printer_snum(p, handle, &snum)) {
1709 close_printer_handle(p, handle);
1713 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1715 /* map an empty access mask to the minimum access mask */
1716 if (printer_default->access_required == 0x0)
1717 printer_default->access_required = PRINTER_ACCESS_USE;
1720 * If we are not serving the printer driver for this printer,
1721 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1722 * will keep NT clients happy --jerry
1725 if (lp_use_client_driver(snum)
1726 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1728 printer_default->access_required = PRINTER_ACCESS_USE;
1731 /* check smb.conf parameters and the the sec_desc */
1733 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1734 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1735 return WERR_ACCESS_DENIED;
1738 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1739 DEBUG(3, ("access DENIED for printer open\n"));
1740 close_printer_handle(p, handle);
1741 return WERR_ACCESS_DENIED;
1744 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1745 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1746 close_printer_handle(p, handle);
1747 return WERR_ACCESS_DENIED;
1750 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1751 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1753 printer_default->access_required = PRINTER_ACCESS_USE;
1755 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1756 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1760 Printer->access_granted = printer_default->access_required;
1763 * If the client sent a devmode in the OpenPrinter() call, then
1764 * save it here in case we get a job submission on this handle
1767 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1768 && q_u->printer_default.devmode_cont.devmode_ptr )
1770 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1771 &Printer->nt_devmode );
1774 #if 0 /* JERRY -- I'm doubtful this is really effective */
1775 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1776 optimization in Windows 2000 clients --jerry */
1778 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1779 && (RA_WIN2K == get_remote_arch()) )
1781 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1782 sys_usleep( 500000 );
1789 /****************************************************************************
1790 ****************************************************************************/
1792 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1793 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1799 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1808 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1809 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1815 printer->info_3=NULL;
1816 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1820 printer->info_6=NULL;
1821 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1831 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1832 NT_DEVICEMODE **pp_nt_devmode)
1834 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1837 * Ensure nt_devmode is a valid pointer
1838 * as we will be overwriting it.
1841 if (nt_devmode == NULL) {
1842 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1843 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1847 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1848 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1850 nt_devmode->specversion=devmode->specversion;
1851 nt_devmode->driverversion=devmode->driverversion;
1852 nt_devmode->size=devmode->size;
1853 nt_devmode->fields=devmode->fields;
1854 nt_devmode->orientation=devmode->orientation;
1855 nt_devmode->papersize=devmode->papersize;
1856 nt_devmode->paperlength=devmode->paperlength;
1857 nt_devmode->paperwidth=devmode->paperwidth;
1858 nt_devmode->scale=devmode->scale;
1859 nt_devmode->copies=devmode->copies;
1860 nt_devmode->defaultsource=devmode->defaultsource;
1861 nt_devmode->printquality=devmode->printquality;
1862 nt_devmode->color=devmode->color;
1863 nt_devmode->duplex=devmode->duplex;
1864 nt_devmode->yresolution=devmode->yresolution;
1865 nt_devmode->ttoption=devmode->ttoption;
1866 nt_devmode->collate=devmode->collate;
1868 nt_devmode->logpixels=devmode->logpixels;
1869 nt_devmode->bitsperpel=devmode->bitsperpel;
1870 nt_devmode->pelswidth=devmode->pelswidth;
1871 nt_devmode->pelsheight=devmode->pelsheight;
1872 nt_devmode->displayflags=devmode->displayflags;
1873 nt_devmode->displayfrequency=devmode->displayfrequency;
1874 nt_devmode->icmmethod=devmode->icmmethod;
1875 nt_devmode->icmintent=devmode->icmintent;
1876 nt_devmode->mediatype=devmode->mediatype;
1877 nt_devmode->dithertype=devmode->dithertype;
1878 nt_devmode->reserved1=devmode->reserved1;
1879 nt_devmode->reserved2=devmode->reserved2;
1880 nt_devmode->panningwidth=devmode->panningwidth;
1881 nt_devmode->panningheight=devmode->panningheight;
1884 * Only change private and driverextra if the incoming devmode
1885 * has a new one. JRA.
1888 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1889 SAFE_FREE(nt_devmode->private);
1890 nt_devmode->driverextra=devmode->driverextra;
1891 if((nt_devmode->private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1893 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1896 *pp_nt_devmode = nt_devmode;
1901 /********************************************************************
1902 * _spoolss_enddocprinter_internal.
1903 ********************************************************************/
1905 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1907 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1911 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1915 if (!get_printer_snum(p, handle, &snum))
1918 Printer->document_started=False;
1919 print_job_end(snum, Printer->jobid,True);
1920 /* error codes unhandled so far ... */
1925 /********************************************************************
1926 * api_spoolss_closeprinter
1927 ********************************************************************/
1929 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1931 POLICY_HND *handle = &q_u->handle;
1933 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1935 if (Printer && Printer->document_started)
1936 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1938 if (!close_printer_handle(p, handle))
1941 /* clear the returned printer handle. Observed behavior
1942 from Win2k server. Don't think this really matters.
1943 Previous code just copied the value of the closed
1946 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1951 /********************************************************************
1952 * api_spoolss_deleteprinter
1954 ********************************************************************/
1956 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1958 POLICY_HND *handle = &q_u->handle;
1959 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1962 if (Printer && Printer->document_started)
1963 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1965 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1967 result = delete_printer_handle(p, handle);
1969 update_c_setprinter(False);
1974 /*******************************************************************
1975 * static function to lookup the version id corresponding to an
1976 * long architecture string
1977 ******************************************************************/
1979 static int get_version_id (char * arch)
1982 struct table_node archi_table[]= {
1984 {"Windows 4.0", "WIN40", 0 },
1985 {"Windows NT x86", "W32X86", 2 },
1986 {"Windows NT R4000", "W32MIPS", 2 },
1987 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1988 {"Windows NT PowerPC", "W32PPC", 2 },
1989 {"Windows IA64", "IA64", 3 },
1990 {"Windows x64", "x64", 3 },
1994 for (i=0; archi_table[i].long_archi != NULL; i++)
1996 if (strcmp(arch, archi_table[i].long_archi) == 0)
1997 return (archi_table[i].version);
2003 /********************************************************************
2004 * _spoolss_deleteprinterdriver
2005 ********************************************************************/
2007 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2011 NT_PRINTER_DRIVER_INFO_LEVEL info;
2012 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2014 struct current_user user;
2016 WERROR status_win2k = WERR_ACCESS_DENIED;
2018 get_current_user(&user, p);
2020 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2021 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2023 /* check that we have a valid driver name first */
2025 if ((version=get_version_id(arch)) == -1)
2026 return WERR_INVALID_ENVIRONMENT;
2029 ZERO_STRUCT(info_win2k);
2031 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2033 /* try for Win2k driver if "Windows NT x86" */
2035 if ( version == 2 ) {
2037 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2038 status = WERR_UNKNOWN_PRINTER_DRIVER;
2042 /* otherwise it was a failure */
2044 status = WERR_UNKNOWN_PRINTER_DRIVER;
2050 if (printer_driver_in_use(info.info_3)) {
2051 status = WERR_PRINTER_DRIVER_IN_USE;
2057 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2059 /* if we get to here, we now have 2 driver info structures to remove */
2060 /* remove the Win2k driver first*/
2062 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2063 free_a_printer_driver( info_win2k, 3 );
2065 /* this should not have failed---if it did, report to client */
2066 if ( !W_ERROR_IS_OK(status_win2k) )
2071 status = delete_printer_driver(info.info_3, &user, version, False);
2073 /* if at least one of the deletes succeeded return OK */
2075 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2079 free_a_printer_driver( info, 3 );
2084 /********************************************************************
2085 * spoolss_deleteprinterdriverex
2086 ********************************************************************/
2088 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2092 NT_PRINTER_DRIVER_INFO_LEVEL info;
2093 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2095 uint32 flags = q_u->delete_flags;
2097 struct current_user user;
2099 WERROR status_win2k = WERR_ACCESS_DENIED;
2101 get_current_user(&user, p);
2103 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2104 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2106 /* check that we have a valid driver name first */
2107 if ((version=get_version_id(arch)) == -1) {
2108 /* this is what NT returns */
2109 return WERR_INVALID_ENVIRONMENT;
2112 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2113 version = q_u->version;
2116 ZERO_STRUCT(info_win2k);
2118 status = get_a_printer_driver(&info, 3, driver, arch, version);
2120 if ( !W_ERROR_IS_OK(status) )
2123 * if the client asked for a specific version,
2124 * or this is something other than Windows NT x86,
2128 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2131 /* try for Win2k driver if "Windows NT x86" */
2134 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2135 status = WERR_UNKNOWN_PRINTER_DRIVER;
2140 if ( printer_driver_in_use(info.info_3) ) {
2141 status = WERR_PRINTER_DRIVER_IN_USE;
2146 * we have a couple of cases to consider.
2147 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2148 * then the delete should fail if **any** files overlap with
2150 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2151 * non-overlapping files
2152 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2153 * is set, the do not delete any files
2154 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2157 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2159 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2161 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2162 /* no idea of the correct error here */
2163 status = WERR_ACCESS_DENIED;
2168 /* also check for W32X86/3 if necessary; maybe we already have? */
2170 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2171 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2174 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2175 /* no idea of the correct error here */
2176 free_a_printer_driver( info_win2k, 3 );
2177 status = WERR_ACCESS_DENIED;
2181 /* if we get to here, we now have 2 driver info structures to remove */
2182 /* remove the Win2k driver first*/
2184 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2185 free_a_printer_driver( info_win2k, 3 );
2187 /* this should not have failed---if it did, report to client */
2189 if ( !W_ERROR_IS_OK(status_win2k) )
2194 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2196 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2199 free_a_printer_driver( info, 3 );
2205 /****************************************************************************
2206 Internal routine for retreiving printerdata
2207 ***************************************************************************/
2209 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2210 const char *key, const char *value, uint32 *type, uint8 **data,
2211 uint32 *needed, uint32 in_size )
2213 REGISTRY_VALUE *val;
2216 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2217 return WERR_BADFILE;
2219 *type = regval_type( val );
2221 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2223 size = regval_size( val );
2225 /* copy the min(in_size, len) */
2228 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2230 /* special case for 0 length values */
2232 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2236 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2245 DEBUG(5,("get_printer_dataex: copy done\n"));
2250 /****************************************************************************
2251 Internal routine for removing printerdata
2252 ***************************************************************************/
2254 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2256 return delete_printer_data( printer->info_2, key, value );
2259 /****************************************************************************
2260 Internal routine for storing printerdata
2261 ***************************************************************************/
2263 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2264 uint32 type, uint8 *data, int real_len )
2266 delete_printer_data( printer->info_2, key, value );
2268 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2271 /********************************************************************
2272 GetPrinterData on a printer server Handle.
2273 ********************************************************************/
2275 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2279 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2281 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2283 if((*data = (uint8 *)TALLOC_ZERO(ctx, 4*sizeof(uint8) )) == NULL)
2289 if (!StrCaseCmp(value, "BeepEnabled")) {
2291 if((*data = (uint8 *)TALLOC(ctx, 4*sizeof(uint8) )) == NULL)
2293 SIVAL(*data, 0, 0x00);
2298 if (!StrCaseCmp(value, "EventLog")) {
2300 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2302 /* formally was 0x1b */
2303 SIVAL(*data, 0, 0x0);
2308 if (!StrCaseCmp(value, "NetPopup")) {
2310 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2312 SIVAL(*data, 0, 0x00);
2317 if (!StrCaseCmp(value, "MajorVersion")) {
2319 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2322 /* Windows NT 4.0 seems to not allow uploading of drivers
2323 to a server that reports 0x3 as the MajorVersion.
2324 need to investigate more how Win2k gets around this .
2327 if ( RA_WINNT == get_remote_arch() )
2336 if (!StrCaseCmp(value, "MinorVersion")) {
2338 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2346 * uint32 size = 0x114
2348 * uint32 minor = [0|1]
2349 * uint32 build = [2195|2600]
2350 * extra unicode string = e.g. "Service Pack 3"
2352 if (!StrCaseCmp(value, "OSVersion")) {
2356 if((*data = (uint8 *)TALLOC(ctx, *needed)) == NULL)
2358 ZERO_STRUCTP( *data );
2360 SIVAL(*data, 0, *needed); /* size */
2361 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2363 SIVAL(*data, 12, 2195); /* build */
2365 /* leave extra string empty */
2371 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2372 const char *string="C:\\PRINTERS";
2374 *needed = 2*(strlen(string)+1);
2375 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2377 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2379 /* it's done by hand ready to go on the wire */
2380 for (i=0; i<strlen(string); i++) {
2381 (*data)[2*i]=string[i];
2382 (*data)[2*i+1]='\0';
2387 if (!StrCaseCmp(value, "Architecture")) {
2388 const char *string="Windows NT x86";
2390 *needed = 2*(strlen(string)+1);
2391 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2393 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2394 for (i=0; i<strlen(string); i++) {
2395 (*data)[2*i]=string[i];
2396 (*data)[2*i+1]='\0';
2401 if (!StrCaseCmp(value, "DsPresent")) {
2403 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2406 /* only show the publish check box if we are a
2407 memeber of a AD domain */
2409 if ( lp_security() == SEC_ADS )
2410 SIVAL(*data, 0, 0x01);
2412 SIVAL(*data, 0, 0x00);
2418 if (!StrCaseCmp(value, "DNSMachineName")) {
2421 if (!get_mydnsfullname(hostname))
2422 return WERR_BADFILE;
2424 *needed = 2*(strlen(hostname)+1);
2425 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2427 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2428 for (i=0; i<strlen(hostname); i++) {
2429 (*data)[2*i]=hostname[i];
2430 (*data)[2*i+1]='\0';
2436 return WERR_BADFILE;
2439 /********************************************************************
2440 * spoolss_getprinterdata
2441 ********************************************************************/
2443 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2445 POLICY_HND *handle = &q_u->handle;
2446 UNISTR2 *valuename = &q_u->valuename;
2447 uint32 in_size = q_u->size;
2448 uint32 *type = &r_u->type;
2449 uint32 *out_size = &r_u->size;
2450 uint8 **data = &r_u->data;
2451 uint32 *needed = &r_u->needed;
2454 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2455 NT_PRINTER_INFO_LEVEL *printer = NULL;
2459 * Reminder: when it's a string, the length is in BYTES
2460 * even if UNICODE is negociated.
2465 *out_size = in_size;
2467 /* in case of problem, return some default values */
2472 DEBUG(4,("_spoolss_getprinterdata\n"));
2475 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2476 status = WERR_BADFID;
2480 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2482 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2483 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2486 if ( !get_printer_snum(p,handle, &snum) ) {
2487 status = WERR_BADFID;
2491 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2492 if ( !W_ERROR_IS_OK(status) )
2495 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2497 if ( strequal(value, "ChangeId") ) {
2499 *needed = sizeof(uint32);
2500 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2501 status = WERR_NOMEM;
2504 SIVAL( *data, 0, printer->info_2->changeid );
2508 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2511 if (*needed > *out_size)
2512 status = WERR_MORE_DATA;
2515 if ( !W_ERROR_IS_OK(status) )
2517 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2519 /* reply this param doesn't exist */
2522 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2524 free_a_printer( &printer, 2 );
2533 /* cleanup & exit */
2536 free_a_printer( &printer, 2 );
2541 /*********************************************************
2542 Connect to the client machine.
2543 **********************************************************/
2545 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2546 struct in_addr *client_ip, const char *remote_machine)
2548 ZERO_STRUCTP(the_cli);
2550 if(cli_initialise(the_cli) == NULL) {
2551 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2555 if ( is_zero_ip(*client_ip) ) {
2556 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2557 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2558 cli_shutdown(the_cli);
2562 if (ismyip(the_cli->dest_ip)) {
2563 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2564 cli_shutdown(the_cli);
2569 the_cli->dest_ip.s_addr = client_ip->s_addr;
2570 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2571 inet_ntoa(*client_ip) ));
2574 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2575 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) ));
2576 cli_shutdown(the_cli);
2580 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2581 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2583 cli_shutdown(the_cli);
2587 the_cli->protocol = PROTOCOL_NT1;
2588 cli_setup_signing_state(the_cli, lp_client_signing());
2590 if (!cli_negprot(the_cli)) {
2591 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2592 cli_shutdown(the_cli);
2596 if (the_cli->protocol != PROTOCOL_NT1) {
2597 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2598 cli_shutdown(the_cli);
2603 * Do an anonymous session setup.
2606 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2607 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2608 cli_shutdown(the_cli);
2612 if (!(the_cli->sec_mode & 1)) {
2613 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2614 cli_shutdown(the_cli);
2618 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2619 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) ));
2620 cli_shutdown(the_cli);
2625 * Ok - we have an anonymous connection to the IPC$ share.
2626 * Now start the NT Domain stuff :-).
2629 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2630 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)));
2631 cli_nt_session_close(the_cli);
2632 cli_ulogoff(the_cli);
2633 cli_shutdown(the_cli);
2640 /***************************************************************************
2641 Connect to the client.
2642 ****************************************************************************/
2644 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2645 uint32 localprinter, uint32 type,
2646 POLICY_HND *handle, struct in_addr *client_ip)
2651 * If it's the first connection, contact the client
2652 * and connect to the IPC$ share anonymously
2654 if (smb_connections==0) {
2655 fstring unix_printer;
2657 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2659 ZERO_STRUCT(notify_cli);
2661 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2664 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2665 /* Tell the connections db we're now interested in printer
2666 * notify messages. */
2667 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2671 * Tell the specific printing tdb we want messages for this printer
2672 * by registering our PID.
2675 if (!print_notify_register_pid(snum))
2676 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2680 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2683 if (!W_ERROR_IS_OK(result))
2684 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2685 dos_errstr(result)));
2687 return (W_ERROR_IS_OK(result));
2690 /********************************************************************
2692 * ReplyFindFirstPrinterChangeNotifyEx
2694 * before replying OK: status=0 a rpc call is made to the workstation
2695 * asking ReplyOpenPrinter
2697 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2698 * called from api_spoolss_rffpcnex
2699 ********************************************************************/
2701 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2703 POLICY_HND *handle = &q_u->handle;
2704 uint32 flags = q_u->flags;
2705 uint32 options = q_u->options;
2706 UNISTR2 *localmachine = &q_u->localmachine;
2707 uint32 printerlocal = q_u->printerlocal;
2709 SPOOL_NOTIFY_OPTION *option = q_u->option;
2710 struct in_addr client_ip;
2712 /* store the notify value in the printer struct */
2714 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2717 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2721 Printer->notify.flags=flags;
2722 Printer->notify.options=options;
2723 Printer->notify.printerlocal=printerlocal;
2725 if (Printer->notify.option)
2726 free_spool_notify_option(&Printer->notify.option);
2728 Printer->notify.option=dup_spool_notify_option(option);
2730 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2731 sizeof(Printer->notify.localmachine)-1);
2733 /* Connect to the client machine and send a ReplyOpenPrinter */
2735 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2737 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2738 !get_printer_snum(p, handle, &snum) )
2741 client_ip.s_addr = inet_addr(p->conn->client_address);
2743 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2744 Printer->notify.printerlocal, 1,
2745 &Printer->notify.client_hnd, &client_ip))
2746 return WERR_SERVER_UNAVAILABLE;
2748 Printer->notify.client_connected=True;
2753 /*******************************************************************
2754 * fill a notify_info_data with the servername
2755 ********************************************************************/
2757 void spoolss_notify_server_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 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2768 data->notify_data.data.length = len;
2769 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2771 if (!data->notify_data.data.string) {
2772 data->notify_data.data.length = 0;
2776 memcpy(data->notify_data.data.string, temp, len);
2779 /*******************************************************************
2780 * fill a notify_info_data with the printername (not including the servername).
2781 ********************************************************************/
2783 void spoolss_notify_printer_name(int snum,
2784 SPOOL_NOTIFY_INFO_DATA *data,
2785 print_queue_struct *queue,
2786 NT_PRINTER_INFO_LEVEL *printer,
2787 TALLOC_CTX *mem_ctx)
2792 /* the notify name should not contain the \\server\ part */
2793 char *p = strrchr(printer->info_2->printername, '\\');
2796 p = printer->info_2->printername;
2801 len = rpcstr_push(temp, p, 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 servicename
2816 ********************************************************************/
2818 void spoolss_notify_share_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 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2829 data->notify_data.data.length = len;
2830 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2832 if (!data->notify_data.data.string) {
2833 data->notify_data.data.length = 0;
2837 memcpy(data->notify_data.data.string, temp, len);
2840 /*******************************************************************
2841 * fill a notify_info_data with the port name
2842 ********************************************************************/
2844 void spoolss_notify_port_name(int snum,
2845 SPOOL_NOTIFY_INFO_DATA *data,
2846 print_queue_struct *queue,
2847 NT_PRINTER_INFO_LEVEL *printer,
2848 TALLOC_CTX *mem_ctx)
2853 /* even if it's strange, that's consistant in all the code */
2855 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2857 data->notify_data.data.length = len;
2858 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2860 if (!data->notify_data.data.string) {
2861 data->notify_data.data.length = 0;
2865 memcpy(data->notify_data.data.string, temp, len);
2868 /*******************************************************************
2869 * fill a notify_info_data with the printername
2870 * but it doesn't exist, have to see what to do
2871 ********************************************************************/
2873 void spoolss_notify_driver_name(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 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2884 data->notify_data.data.length = len;
2885 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2887 if (!data->notify_data.data.string) {
2888 data->notify_data.data.length = 0;
2892 memcpy(data->notify_data.data.string, temp, len);
2895 /*******************************************************************
2896 * fill a notify_info_data with the comment
2897 ********************************************************************/
2899 void spoolss_notify_comment(int snum,
2900 SPOOL_NOTIFY_INFO_DATA *data,
2901 print_queue_struct *queue,
2902 NT_PRINTER_INFO_LEVEL *printer,
2903 TALLOC_CTX *mem_ctx)
2908 if (*printer->info_2->comment == '\0')
2909 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2911 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2913 data->notify_data.data.length = len;
2914 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2916 if (!data->notify_data.data.string) {
2917 data->notify_data.data.length = 0;
2921 memcpy(data->notify_data.data.string, temp, len);
2924 /*******************************************************************
2925 * fill a notify_info_data with the comment
2926 * location = "Room 1, floor 2, building 3"
2927 ********************************************************************/
2929 void spoolss_notify_location(int snum,
2930 SPOOL_NOTIFY_INFO_DATA *data,
2931 print_queue_struct *queue,
2932 NT_PRINTER_INFO_LEVEL *printer,
2933 TALLOC_CTX *mem_ctx)
2938 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2940 data->notify_data.data.length = len;
2941 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2943 if (!data->notify_data.data.string) {
2944 data->notify_data.data.length = 0;
2948 memcpy(data->notify_data.data.string, temp, len);
2951 /*******************************************************************
2952 * fill a notify_info_data with the device mode
2953 * jfm:xxxx don't to it for know but that's a real problem !!!
2954 ********************************************************************/
2956 static void spoolss_notify_devmode(int snum,
2957 SPOOL_NOTIFY_INFO_DATA *data,
2958 print_queue_struct *queue,
2959 NT_PRINTER_INFO_LEVEL *printer,
2960 TALLOC_CTX *mem_ctx)
2964 /*******************************************************************
2965 * fill a notify_info_data with the separator file name
2966 ********************************************************************/
2968 void spoolss_notify_sepfile(int snum,
2969 SPOOL_NOTIFY_INFO_DATA *data,
2970 print_queue_struct *queue,
2971 NT_PRINTER_INFO_LEVEL *printer,
2972 TALLOC_CTX *mem_ctx)
2977 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2979 data->notify_data.data.length = len;
2980 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2982 if (!data->notify_data.data.string) {
2983 data->notify_data.data.length = 0;
2987 memcpy(data->notify_data.data.string, temp, len);
2990 /*******************************************************************
2991 * fill a notify_info_data with the print processor
2992 * jfm:xxxx return always winprint to indicate we don't do anything to it
2993 ********************************************************************/
2995 void spoolss_notify_print_processor(int snum,
2996 SPOOL_NOTIFY_INFO_DATA *data,
2997 print_queue_struct *queue,
2998 NT_PRINTER_INFO_LEVEL *printer,
2999 TALLOC_CTX *mem_ctx)
3004 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3006 data->notify_data.data.length = len;
3007 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3009 if (!data->notify_data.data.string) {
3010 data->notify_data.data.length = 0;
3014 memcpy(data->notify_data.data.string, temp, len);
3017 /*******************************************************************
3018 * fill a notify_info_data with the print processor options
3019 * jfm:xxxx send an empty string
3020 ********************************************************************/
3022 void spoolss_notify_parameters(int snum,
3023 SPOOL_NOTIFY_INFO_DATA *data,
3024 print_queue_struct *queue,
3025 NT_PRINTER_INFO_LEVEL *printer,
3026 TALLOC_CTX *mem_ctx)
3031 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3033 data->notify_data.data.length = len;
3034 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3036 if (!data->notify_data.data.string) {
3037 data->notify_data.data.length = 0;
3041 memcpy(data->notify_data.data.string, temp, len);
3044 /*******************************************************************
3045 * fill a notify_info_data with the data type
3046 * jfm:xxxx always send RAW as data type
3047 ********************************************************************/
3049 void spoolss_notify_datatype(int snum,
3050 SPOOL_NOTIFY_INFO_DATA *data,
3051 print_queue_struct *queue,
3052 NT_PRINTER_INFO_LEVEL *printer,
3053 TALLOC_CTX *mem_ctx)
3058 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3060 data->notify_data.data.length = len;
3061 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3063 if (!data->notify_data.data.string) {
3064 data->notify_data.data.length = 0;
3068 memcpy(data->notify_data.data.string, temp, len);
3071 /*******************************************************************
3072 * fill a notify_info_data with the security descriptor
3073 * jfm:xxxx send an null pointer to say no security desc
3074 * have to implement security before !
3075 ********************************************************************/
3077 static void spoolss_notify_security_desc(int snum,
3078 SPOOL_NOTIFY_INFO_DATA *data,
3079 print_queue_struct *queue,
3080 NT_PRINTER_INFO_LEVEL *printer,
3081 TALLOC_CTX *mem_ctx)
3083 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3084 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3087 /*******************************************************************
3088 * fill a notify_info_data with the attributes
3089 * jfm:xxxx a samba printer is always shared
3090 ********************************************************************/
3092 void spoolss_notify_attributes(int snum,
3093 SPOOL_NOTIFY_INFO_DATA *data,
3094 print_queue_struct *queue,
3095 NT_PRINTER_INFO_LEVEL *printer,
3096 TALLOC_CTX *mem_ctx)
3098 data->notify_data.value[0] = printer->info_2->attributes;
3099 data->notify_data.value[1] = 0;
3102 /*******************************************************************
3103 * fill a notify_info_data with the priority
3104 ********************************************************************/
3106 static void spoolss_notify_priority(int snum,
3107 SPOOL_NOTIFY_INFO_DATA *data,
3108 print_queue_struct *queue,
3109 NT_PRINTER_INFO_LEVEL *printer,
3110 TALLOC_CTX *mem_ctx)
3112 data->notify_data.value[0] = printer->info_2->priority;
3113 data->notify_data.value[1] = 0;
3116 /*******************************************************************
3117 * fill a notify_info_data with the default priority
3118 ********************************************************************/
3120 static void spoolss_notify_default_priority(int snum,
3121 SPOOL_NOTIFY_INFO_DATA *data,
3122 print_queue_struct *queue,
3123 NT_PRINTER_INFO_LEVEL *printer,
3124 TALLOC_CTX *mem_ctx)
3126 data->notify_data.value[0] = printer->info_2->default_priority;
3127 data->notify_data.value[1] = 0;
3130 /*******************************************************************
3131 * fill a notify_info_data with the start time
3132 ********************************************************************/
3134 static void spoolss_notify_start_time(int snum,
3135 SPOOL_NOTIFY_INFO_DATA *data,
3136 print_queue_struct *queue,
3137 NT_PRINTER_INFO_LEVEL *printer,
3138 TALLOC_CTX *mem_ctx)
3140 data->notify_data.value[0] = printer->info_2->starttime;
3141 data->notify_data.value[1] = 0;
3144 /*******************************************************************
3145 * fill a notify_info_data with the until time
3146 ********************************************************************/
3148 static void spoolss_notify_until_time(int snum,
3149 SPOOL_NOTIFY_INFO_DATA *data,
3150 print_queue_struct *queue,
3151 NT_PRINTER_INFO_LEVEL *printer,
3152 TALLOC_CTX *mem_ctx)
3154 data->notify_data.value[0] = printer->info_2->untiltime;
3155 data->notify_data.value[1] = 0;
3158 /*******************************************************************
3159 * fill a notify_info_data with the status
3160 ********************************************************************/
3162 static void spoolss_notify_status(int snum,
3163 SPOOL_NOTIFY_INFO_DATA *data,
3164 print_queue_struct *queue,
3165 NT_PRINTER_INFO_LEVEL *printer,
3166 TALLOC_CTX *mem_ctx)
3168 print_status_struct status;
3170 print_queue_length(snum, &status);
3171 data->notify_data.value[0]=(uint32) status.status;
3172 data->notify_data.value[1] = 0;
3175 /*******************************************************************
3176 * fill a notify_info_data with the number of jobs queued
3177 ********************************************************************/
3179 void spoolss_notify_cjobs(int snum,
3180 SPOOL_NOTIFY_INFO_DATA *data,
3181 print_queue_struct *queue,
3182 NT_PRINTER_INFO_LEVEL *printer,
3183 TALLOC_CTX *mem_ctx)
3185 data->notify_data.value[0] = print_queue_length(snum, NULL);
3186 data->notify_data.value[1] = 0;
3189 /*******************************************************************
3190 * fill a notify_info_data with the average ppm
3191 ********************************************************************/
3193 static void spoolss_notify_average_ppm(int snum,
3194 SPOOL_NOTIFY_INFO_DATA *data,
3195 print_queue_struct *queue,
3196 NT_PRINTER_INFO_LEVEL *printer,
3197 TALLOC_CTX *mem_ctx)
3199 /* always respond 8 pages per minutes */
3200 /* a little hard ! */
3201 data->notify_data.value[0] = printer->info_2->averageppm;
3202 data->notify_data.value[1] = 0;
3205 /*******************************************************************
3206 * fill a notify_info_data with username
3207 ********************************************************************/
3209 static void spoolss_notify_username(int snum,
3210 SPOOL_NOTIFY_INFO_DATA *data,
3211 print_queue_struct *queue,
3212 NT_PRINTER_INFO_LEVEL *printer,
3213 TALLOC_CTX *mem_ctx)
3218 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3220 data->notify_data.data.length = len;
3221 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3223 if (!data->notify_data.data.string) {
3224 data->notify_data.data.length = 0;
3228 memcpy(data->notify_data.data.string, temp, len);
3231 /*******************************************************************
3232 * fill a notify_info_data with job status
3233 ********************************************************************/
3235 static void spoolss_notify_job_status(int snum,
3236 SPOOL_NOTIFY_INFO_DATA *data,
3237 print_queue_struct *queue,
3238 NT_PRINTER_INFO_LEVEL *printer,
3239 TALLOC_CTX *mem_ctx)
3241 data->notify_data.value[0]=nt_printj_status(queue->status);
3242 data->notify_data.value[1] = 0;
3245 /*******************************************************************
3246 * fill a notify_info_data with job name
3247 ********************************************************************/
3249 static void spoolss_notify_job_name(int snum,
3250 SPOOL_NOTIFY_INFO_DATA *data,
3251 print_queue_struct *queue,
3252 NT_PRINTER_INFO_LEVEL *printer,
3253 TALLOC_CTX *mem_ctx)
3258 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3260 data->notify_data.data.length = len;
3261 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3263 if (!data->notify_data.data.string) {
3264 data->notify_data.data.length = 0;
3268 memcpy(data->notify_data.data.string, temp, len);
3271 /*******************************************************************
3272 * fill a notify_info_data with job status
3273 ********************************************************************/
3275 static void spoolss_notify_job_status_string(int snum,
3276 SPOOL_NOTIFY_INFO_DATA *data,
3277 print_queue_struct *queue,
3278 NT_PRINTER_INFO_LEVEL *printer,
3279 TALLOC_CTX *mem_ctx)
3282 * Now we're returning job status codes we just return a "" here. JRA.
3289 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3292 switch (queue->status) {
3297 p = ""; /* NT provides the paused string */
3306 #endif /* NO LONGER NEEDED. */
3308 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3310 data->notify_data.data.length = len;
3311 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3313 if (!data->notify_data.data.string) {
3314 data->notify_data.data.length = 0;
3318 memcpy(data->notify_data.data.string, temp, len);
3321 /*******************************************************************
3322 * fill a notify_info_data with job time
3323 ********************************************************************/
3325 static void spoolss_notify_job_time(int snum,
3326 SPOOL_NOTIFY_INFO_DATA *data,
3327 print_queue_struct *queue,
3328 NT_PRINTER_INFO_LEVEL *printer,
3329 TALLOC_CTX *mem_ctx)
3331 data->notify_data.value[0]=0x0;
3332 data->notify_data.value[1]=0;
3335 /*******************************************************************
3336 * fill a notify_info_data with job size
3337 ********************************************************************/
3339 static void spoolss_notify_job_size(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]=queue->size;
3346 data->notify_data.value[1]=0;
3349 /*******************************************************************
3350 * fill a notify_info_data with page info
3351 ********************************************************************/
3352 static void spoolss_notify_total_pages(int snum,
3353 SPOOL_NOTIFY_INFO_DATA *data,
3354 print_queue_struct *queue,
3355 NT_PRINTER_INFO_LEVEL *printer,
3356 TALLOC_CTX *mem_ctx)
3358 data->notify_data.value[0]=queue->page_count;
3359 data->notify_data.value[1]=0;
3362 /*******************************************************************
3363 * fill a notify_info_data with pages printed info.
3364 ********************************************************************/
3365 static void spoolss_notify_pages_printed(int snum,
3366 SPOOL_NOTIFY_INFO_DATA *data,
3367 print_queue_struct *queue,
3368 NT_PRINTER_INFO_LEVEL *printer,
3369 TALLOC_CTX *mem_ctx)
3371 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3372 data->notify_data.value[1]=0;
3375 /*******************************************************************
3376 Fill a notify_info_data with job position.
3377 ********************************************************************/
3379 static void spoolss_notify_job_position(int snum,
3380 SPOOL_NOTIFY_INFO_DATA *data,
3381 print_queue_struct *queue,
3382 NT_PRINTER_INFO_LEVEL *printer,
3383 TALLOC_CTX *mem_ctx)
3385 data->notify_data.value[0]=queue->job;
3386 data->notify_data.value[1]=0;
3389 /*******************************************************************
3390 Fill a notify_info_data with submitted time.
3391 ********************************************************************/
3393 static void spoolss_notify_submitted_time(int snum,
3394 SPOOL_NOTIFY_INFO_DATA *data,
3395 print_queue_struct *queue,
3396 NT_PRINTER_INFO_LEVEL *printer,
3397 TALLOC_CTX *mem_ctx)
3404 t=gmtime(&queue->time);
3406 len = sizeof(SYSTEMTIME);
3408 data->notify_data.data.length = len;
3409 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3411 if (!data->notify_data.data.string) {
3412 data->notify_data.data.length = 0;
3416 make_systemtime(&st, t);
3419 * Systemtime must be linearized as a set of UINT16's.
3420 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3423 p = (char *)data->notify_data.data.string;
3424 SSVAL(p, 0, st.year);
3425 SSVAL(p, 2, st.month);
3426 SSVAL(p, 4, st.dayofweek);
3427 SSVAL(p, 6, st.day);
3428 SSVAL(p, 8, st.hour);
3429 SSVAL(p, 10, st.minute);
3430 SSVAL(p, 12, st.second);
3431 SSVAL(p, 14, st.milliseconds);
3434 struct s_notify_info_data_table
3440 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3441 print_queue_struct *queue,
3442 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3445 /* A table describing the various print notification constants and
3446 whether the notification data is a pointer to a variable sized
3447 buffer, a one value uint32 or a two value uint32. */
3449 static const struct s_notify_info_data_table notify_info_data_table[] =
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3500 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3503 /*******************************************************************
3504 Return the size of info_data structure.
3505 ********************************************************************/
3507 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3511 for (i = 0; i < sizeof(notify_info_data_table); i++)
3513 if ( (notify_info_data_table[i].type == type)
3514 && (notify_info_data_table[i].field == field) )
3516 switch(notify_info_data_table[i].size)
3518 case NOTIFY_ONE_VALUE:
3519 case NOTIFY_TWO_VALUE:
3524 /* The only pointer notify data I have seen on
3525 the wire is the submitted time and this has
3526 the notify size set to 4. -tpot */
3528 case NOTIFY_POINTER:
3531 case NOTIFY_SECDESC:
3537 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3542 /*******************************************************************
3543 Return the type of notify_info_data.
3544 ********************************************************************/
3546 static int type_of_notify_info_data(uint16 type, uint16 field)
3550 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3551 if (notify_info_data_table[i].type == type &&
3552 notify_info_data_table[i].field == field)
3553 return notify_info_data_table[i].size;
3559 /****************************************************************************
3560 ****************************************************************************/
3562 static int search_notify(uint16 type, uint16 field, int *value)
3566 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3567 if (notify_info_data_table[i].type == type &&
3568 notify_info_data_table[i].field == field &&
3569 notify_info_data_table[i].fn != NULL) {
3578 /****************************************************************************
3579 ****************************************************************************/
3581 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3583 info_data->type = type;
3584 info_data->field = field;
3585 info_data->reserved = 0;
3587 info_data->size = size_of_notify_info_data(type, field);
3588 info_data->enc_type = type_of_notify_info_data(type, field);
3595 /*******************************************************************
3597 * fill a notify_info struct with info asked
3599 ********************************************************************/
3601 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3602 snum, SPOOL_NOTIFY_OPTION_TYPE
3603 *option_type, uint32 id,
3604 TALLOC_CTX *mem_ctx)
3610 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3611 NT_PRINTER_INFO_LEVEL *printer = NULL;
3612 print_queue_struct *queue=NULL;
3614 type=option_type->type;
3616 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3617 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3618 option_type->count, lp_servicename(snum)));
3620 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3623 for(field_num=0; field_num<option_type->count; field_num++) {
3624 field = option_type->fields[field_num];
3626 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3628 if (!search_notify(type, field, &j) )
3631 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3632 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3637 current_data = &info->data[info->count];
3639 construct_info_data(current_data, type, field, id);
3641 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3642 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3644 notify_info_data_table[j].fn(snum, current_data, queue,
3650 free_a_printer(&printer, 2);
3654 /*******************************************************************
3656 * fill a notify_info struct with info asked
3658 ********************************************************************/
3660 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3661 SPOOL_NOTIFY_INFO *info,
3662 NT_PRINTER_INFO_LEVEL *printer,
3663 int snum, SPOOL_NOTIFY_OPTION_TYPE
3664 *option_type, uint32 id,
3665 TALLOC_CTX *mem_ctx)
3671 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3673 DEBUG(4,("construct_notify_jobs_info\n"));
3675 type = option_type->type;
3677 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3678 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3679 option_type->count));
3681 for(field_num=0; field_num<option_type->count; field_num++) {
3682 field = option_type->fields[field_num];
3684 if (!search_notify(type, field, &j) )
3687 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3688 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3691 else info->data = tid;
3693 current_data=&(info->data[info->count]);
3695 construct_info_data(current_data, type, field, id);
3696 notify_info_data_table[j].fn(snum, current_data, queue,
3705 * JFM: The enumeration is not that simple, it's even non obvious.
3707 * let's take an example: I want to monitor the PRINTER SERVER for
3708 * the printer's name and the number of jobs currently queued.
3709 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3710 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3712 * I have 3 printers on the back of my server.
3714 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3717 * 1 printer 1 name 1
3718 * 2 printer 1 cjob 1
3719 * 3 printer 2 name 2
3720 * 4 printer 2 cjob 2
3721 * 5 printer 3 name 3
3722 * 6 printer 3 name 3
3724 * that's the print server case, the printer case is even worse.
3727 /*******************************************************************
3729 * enumerate all printers on the printserver
3730 * fill a notify_info struct with info asked
3732 ********************************************************************/
3734 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3735 SPOOL_NOTIFY_INFO *info,
3736 TALLOC_CTX *mem_ctx)
3739 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3740 int n_services=lp_numservices();
3742 SPOOL_NOTIFY_OPTION *option;
3743 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3745 DEBUG(4,("printserver_notify_info\n"));
3750 option=Printer->notify.option;
3755 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3756 sending a ffpcn() request first */
3761 for (i=0; i<option->count; i++) {
3762 option_type=&(option->ctr.type[i]);
3764 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3767 for (snum=0; snum<n_services; snum++)
3769 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3770 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3776 * Debugging information, don't delete.
3779 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3780 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3781 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3783 for (i=0; i<info->count; i++) {
3784 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3785 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3786 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3793 /*******************************************************************
3795 * fill a notify_info struct with info asked
3797 ********************************************************************/
3799 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3800 TALLOC_CTX *mem_ctx)
3803 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3806 SPOOL_NOTIFY_OPTION *option;
3807 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3809 print_queue_struct *queue=NULL;
3810 print_status_struct status;
3812 DEBUG(4,("printer_notify_info\n"));
3817 option=Printer->notify.option;
3823 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3824 sending a ffpcn() request first */
3829 get_printer_snum(p, hnd, &snum);
3831 for (i=0; i<option->count; i++) {
3832 option_type=&option->ctr.type[i];
3834 switch ( option_type->type ) {
3835 case PRINTER_NOTIFY_TYPE:
3836 if(construct_notify_printer_info(Printer, info, snum,
3842 case JOB_NOTIFY_TYPE: {
3843 NT_PRINTER_INFO_LEVEL *printer = NULL;
3845 count = print_queue_status(snum, &queue, &status);
3847 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3850 for (j=0; j<count; j++) {
3851 construct_notify_jobs_info(&queue[j], info,
3858 free_a_printer(&printer, 2);
3868 * Debugging information, don't delete.
3871 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3872 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3873 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3875 for (i=0; i<info->count; i++) {
3876 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3877 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3878 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3884 /********************************************************************
3886 ********************************************************************/
3888 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3890 POLICY_HND *handle = &q_u->handle;
3891 SPOOL_NOTIFY_INFO *info = &r_u->info;
3893 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3894 WERROR result = WERR_BADFID;
3896 /* we always have a NOTIFY_INFO struct */
3900 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3901 OUR_HANDLE(handle)));
3905 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3908 * We are now using the change value, and
3909 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3910 * I don't have a global notification system, I'm sending back all the
3911 * informations even when _NOTHING_ has changed.
3914 /* We need to keep track of the change value to send back in
3915 RRPCN replies otherwise our updates are ignored. */
3917 Printer->notify.fnpcn = True;
3919 if (Printer->notify.client_connected) {
3920 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3921 Printer->notify.change = q_u->change;
3924 /* just ignore the SPOOL_NOTIFY_OPTION */
3926 switch (Printer->printer_type) {
3927 case PRINTER_HANDLE_IS_PRINTSERVER:
3928 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3931 case PRINTER_HANDLE_IS_PRINTER:
3932 result = printer_notify_info(p, handle, info, p->mem_ctx);
3936 Printer->notify.fnpcn = False;
3942 /********************************************************************
3943 * construct_printer_info_0
3944 * fill a printer_info_0 struct
3945 ********************************************************************/
3947 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3951 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3952 counter_printer_0 *session_counter;
3953 uint32 global_counter;
3956 print_status_struct status;
3958 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3961 count = print_queue_length(snum, &status);
3963 /* check if we already have a counter for this printer */
3964 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3965 if (session_counter->snum == snum)
3969 /* it's the first time, add it to the list */
3970 if (session_counter==NULL) {
3971 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3972 free_a_printer(&ntprinter, 2);
3975 ZERO_STRUCTP(session_counter);
3976 session_counter->snum=snum;
3977 session_counter->counter=0;
3978 DLIST_ADD(counter_list, session_counter);
3982 session_counter->counter++;
3985 * the global_counter should be stored in a TDB as it's common to all the clients
3986 * and should be zeroed on samba startup
3988 global_counter=session_counter->counter;
3990 pstrcpy(chaine,ntprinter->info_2->printername);
3992 init_unistr(&printer->printername, chaine);
3994 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3995 init_unistr(&printer->servername, chaine);
3997 printer->cjobs = count;
3998 printer->total_jobs = 0;
3999 printer->total_bytes = 0;
4001 setuptime = (time_t)ntprinter->info_2->setuptime;
4002 t=gmtime(&setuptime);
4004 printer->year = t->tm_year+1900;
4005 printer->month = t->tm_mon+1;
4006 printer->dayofweek = t->tm_wday;
4007 printer->day = t->tm_mday;
4008 printer->hour = t->tm_hour;
4009 printer->minute = t->tm_min;
4010 printer->second = t->tm_sec;
4011 printer->milliseconds = 0;
4013 printer->global_counter = global_counter;
4014 printer->total_pages = 0;
4016 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4017 printer->major_version = 0x0005; /* NT 5 */
4018 printer->build_version = 0x0893; /* build 2195 */
4020 printer->unknown7 = 0x1;
4021 printer->unknown8 = 0x0;
4022 printer->unknown9 = 0x0;
4023 printer->session_counter = session_counter->counter;
4024 printer->unknown11 = 0x0;
4025 printer->printer_errors = 0x0; /* number of print failure */
4026 printer->unknown13 = 0x0;
4027 printer->unknown14 = 0x1;
4028 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4029 printer->unknown16 = 0x0;
4030 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4031 printer->unknown18 = 0x0;
4032 printer->status = nt_printq_status(status.status);
4033 printer->unknown20 = 0x0;
4034 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4035 printer->unknown22 = 0x0;
4036 printer->unknown23 = 0x6; /* 6 ???*/
4037 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4038 printer->unknown25 = 0;
4039 printer->unknown26 = 0;
4040 printer->unknown27 = 0;
4041 printer->unknown28 = 0;
4042 printer->unknown29 = 0;
4044 free_a_printer(&ntprinter,2);
4048 /********************************************************************
4049 * construct_printer_info_1
4050 * fill a printer_info_1 struct
4051 ********************************************************************/
4052 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4056 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4058 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4061 printer->flags=flags;
4063 if (*ntprinter->info_2->comment == '\0') {
4064 init_unistr(&printer->comment, lp_comment(snum));
4065 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4066 ntprinter->info_2->drivername, lp_comment(snum));
4069 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4070 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4071 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4074 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4076 init_unistr(&printer->description, chaine);
4077 init_unistr(&printer->name, chaine2);
4079 free_a_printer(&ntprinter,2);
4084 /****************************************************************************
4085 Free a DEVMODE struct.
4086 ****************************************************************************/
4088 static void free_dev_mode(DEVICEMODE *dev)
4093 SAFE_FREE(dev->private);
4098 /****************************************************************************
4099 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4100 should be valid upon entry
4101 ****************************************************************************/
4103 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4105 if ( !devmode || !ntdevmode )
4108 init_unistr(&devmode->devicename, ntdevmode->devicename);
4110 init_unistr(&devmode->formname, ntdevmode->formname);
4112 devmode->specversion = ntdevmode->specversion;
4113 devmode->driverversion = ntdevmode->driverversion;
4114 devmode->size = ntdevmode->size;
4115 devmode->driverextra = ntdevmode->driverextra;
4116 devmode->fields = ntdevmode->fields;
4118 devmode->orientation = ntdevmode->orientation;
4119 devmode->papersize = ntdevmode->papersize;
4120 devmode->paperlength = ntdevmode->paperlength;
4121 devmode->paperwidth = ntdevmode->paperwidth;
4122 devmode->scale = ntdevmode->scale;
4123 devmode->copies = ntdevmode->copies;
4124 devmode->defaultsource = ntdevmode->defaultsource;
4125 devmode->printquality = ntdevmode->printquality;
4126 devmode->color = ntdevmode->color;
4127 devmode->duplex = ntdevmode->duplex;
4128 devmode->yresolution = ntdevmode->yresolution;
4129 devmode->ttoption = ntdevmode->ttoption;
4130 devmode->collate = ntdevmode->collate;
4131 devmode->icmmethod = ntdevmode->icmmethod;
4132 devmode->icmintent = ntdevmode->icmintent;
4133 devmode->mediatype = ntdevmode->mediatype;
4134 devmode->dithertype = ntdevmode->dithertype;
4136 if (ntdevmode->private != NULL) {
4137 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4144 /****************************************************************************
4145 Create a DEVMODE struct. Returns malloced memory.
4146 ****************************************************************************/
4148 DEVICEMODE *construct_dev_mode(int snum)
4150 NT_PRINTER_INFO_LEVEL *printer = NULL;
4151 DEVICEMODE *devmode = NULL;
4153 DEBUG(7,("construct_dev_mode\n"));
4155 DEBUGADD(8,("getting printer characteristics\n"));
4157 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4160 if ( !printer->info_2->devmode ) {
4161 DEBUG(5, ("BONG! There was no device mode!\n"));
4165 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4166 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4170 ZERO_STRUCTP(devmode);
4172 DEBUGADD(8,("loading DEVICEMODE\n"));
4174 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4175 free_dev_mode( devmode );
4180 free_a_printer(&printer,2);
4185 /********************************************************************
4186 * construct_printer_info_2
4187 * fill a printer_info_2 struct
4188 ********************************************************************/
4190 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4193 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4195 print_status_struct status;
4197 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4200 count = print_queue_length(snum, &status);
4202 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4203 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4204 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4205 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4206 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4208 if (*ntprinter->info_2->comment == '\0')
4209 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4211 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4213 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4214 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4215 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4216 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4217 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4219 printer->attributes = ntprinter->info_2->attributes;
4221 printer->priority = ntprinter->info_2->priority; /* priority */
4222 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4223 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4224 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4225 printer->status = nt_printq_status(status.status); /* status */
4226 printer->cjobs = count; /* jobs */
4227 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4229 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4230 DEBUG(8, ("Returning NULL Devicemode!\n"));
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;
4236 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4237 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4238 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4241 printer->secdesc = NULL;
4244 free_a_printer(&ntprinter, 2);
4248 /********************************************************************
4249 * construct_printer_info_3
4250 * fill a printer_info_3 struct
4251 ********************************************************************/
4253 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4255 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4256 PRINTER_INFO_3 *printer = NULL;
4258 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4262 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4263 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4267 ZERO_STRUCTP(printer);
4269 printer->flags = 4; /* These are the components of the SD we are returning. */
4270 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4271 /* steal the printer info sec_desc structure. [badly done]. */
4272 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4276 * Set the flags for the components we are returning.
4279 if (printer->secdesc->owner_sid)
4280 printer->flags |= OWNER_SECURITY_INFORMATION;
4282 if (printer->secdesc->grp_sid)
4283 printer->flags |= GROUP_SECURITY_INFORMATION;
4285 if (printer->secdesc->dacl)
4286 printer->flags |= DACL_SECURITY_INFORMATION;
4288 if (printer->secdesc->sacl)
4289 printer->flags |= SACL_SECURITY_INFORMATION;
4292 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4293 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4294 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4297 free_a_printer(&ntprinter, 2);
4299 *pp_printer = printer;
4303 /********************************************************************
4304 * construct_printer_info_4
4305 * fill a printer_info_4 struct
4306 ********************************************************************/
4308 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4310 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4312 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4315 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4316 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4317 printer->attributes = ntprinter->info_2->attributes;
4319 free_a_printer(&ntprinter, 2);
4323 /********************************************************************
4324 * construct_printer_info_5
4325 * fill a printer_info_5 struct
4326 ********************************************************************/
4328 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4330 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4332 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4335 init_unistr(&printer->printername, ntprinter->info_2->printername);
4336 init_unistr(&printer->portname, ntprinter->info_2->portname);
4337 printer->attributes = ntprinter->info_2->attributes;
4339 /* these two are not used by NT+ according to MSDN */
4341 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4342 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4344 free_a_printer(&ntprinter, 2);
4349 /********************************************************************
4350 * construct_printer_info_7
4351 * fill a printer_info_7 struct
4352 ********************************************************************/
4354 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4356 char *guid_str = NULL;
4359 if (is_printer_published(print_hnd, snum, &guid)) {
4360 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4361 strupper_m(guid_str);
4362 init_unistr(&printer->guid, guid_str);
4363 printer->action = SPOOL_DS_PUBLISH;
4365 init_unistr(&printer->guid, "");
4366 printer->action = SPOOL_DS_UNPUBLISH;
4372 /********************************************************************
4373 Spoolss_enumprinters.
4374 ********************************************************************/
4376 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4380 int n_services=lp_numservices();
4381 PRINTER_INFO_1 *tp, *printers=NULL;
4382 PRINTER_INFO_1 current_prt;
4383 WERROR result = WERR_OK;
4385 DEBUG(4,("enum_all_printers_info_1\n"));
4387 for (snum=0; snum<n_services; snum++) {
4388 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4389 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4391 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4392 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4393 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4394 SAFE_FREE(printers);
4399 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4401 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4407 /* check the required size. */
4408 for (i=0; i<*returned; i++)
4409 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4411 if (*needed > offered) {
4412 result = WERR_INSUFFICIENT_BUFFER;
4416 if (!rpcbuf_alloc_size(buffer, *needed)) {
4417 result = WERR_NOMEM;
4421 /* fill the buffer with the structures */
4422 for (i=0; i<*returned; i++)
4423 smb_io_printer_info_1("", buffer, &printers[i], 0);
4428 SAFE_FREE(printers);
4430 if ( !W_ERROR_IS_OK(result) )
4436 /********************************************************************
4437 enum_all_printers_info_1_local.
4438 *********************************************************************/
4440 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4442 DEBUG(4,("enum_all_printers_info_1_local\n"));
4444 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4447 /********************************************************************
4448 enum_all_printers_info_1_name.
4449 *********************************************************************/
4451 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4455 DEBUG(4,("enum_all_printers_info_1_name\n"));
4457 if ((name[0] == '\\') && (name[1] == '\\'))
4460 if (is_myname_or_ipaddr(s)) {
4461 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4464 return WERR_INVALID_NAME;
4467 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4468 /********************************************************************
4469 enum_all_printers_info_1_remote.
4470 *********************************************************************/
4472 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4474 PRINTER_INFO_1 *printer;
4475 fstring printername;
4478 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4479 WERROR result = WERR_OK;
4481 /* JFM: currently it's more a place holder than anything else.
4482 * In the spooler world there is a notion of server registration.
4483 * the print servers are registered on the PDC (in the same domain)
4485 * We should have a TDB here. The registration is done thru an
4486 * undocumented RPC call.
4489 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4494 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4495 slprintf(desc, sizeof(desc)-1,"%s", name);
4496 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4498 init_unistr(&printer->description, desc);
4499 init_unistr(&printer->name, printername);
4500 init_unistr(&printer->comment, comment);
4501 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4503 /* check the required size. */
4504 *needed += spoolss_size_printer_info_1(printer);
4506 if (*needed > offered) {
4507 result = WERR_INSUFFICIENT_BUFFER;
4511 if (!rpcbuf_alloc_size(buffer, *needed)) {
4512 result = WERR_NOMEM;
4516 /* fill the buffer with the structures */
4517 smb_io_printer_info_1("", buffer, printer, 0);
4523 if ( !W_ERROR_IS_OK(result) )
4531 /********************************************************************
4532 enum_all_printers_info_1_network.
4533 *********************************************************************/
4535 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4539 DEBUG(4,("enum_all_printers_info_1_network\n"));
4541 /* If we respond to a enum_printers level 1 on our name with flags
4542 set to PRINTER_ENUM_REMOTE with a list of printers then these
4543 printers incorrectly appear in the APW browse list.
4544 Specifically the printers for the server appear at the workgroup
4545 level where all the other servers in the domain are
4546 listed. Windows responds to this call with a
4547 WERR_CAN_NOT_COMPLETE so we should do the same. */
4549 if (name[0] == '\\' && name[1] == '\\')
4552 if (is_myname_or_ipaddr(s))
4553 return WERR_CAN_NOT_COMPLETE;
4555 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4558 /********************************************************************
4559 * api_spoolss_enumprinters
4561 * called from api_spoolss_enumprinters (see this to understand)
4562 ********************************************************************/
4564 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4568 int n_services=lp_numservices();
4569 PRINTER_INFO_2 *tp, *printers=NULL;
4570 PRINTER_INFO_2 current_prt;
4571 WERROR result = WERR_OK;
4573 for (snum=0; snum<n_services; snum++) {
4574 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4575 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4577 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4578 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) == NULL) {
4579 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4580 SAFE_FREE(printers);
4585 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4586 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4592 /* check the required size. */
4593 for (i=0; i<*returned; i++)
4594 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4596 if (*needed > offered) {
4597 result = WERR_INSUFFICIENT_BUFFER;
4601 if (!rpcbuf_alloc_size(buffer, *needed)) {
4602 result = WERR_NOMEM;
4606 /* fill the buffer with the structures */
4607 for (i=0; i<*returned; i++)
4608 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4612 for (i=0; i<*returned; i++) {
4613 free_devmode(printers[i].devmode);
4615 SAFE_FREE(printers);
4617 if ( !W_ERROR_IS_OK(result) )
4623 /********************************************************************
4624 * handle enumeration of printers at level 1
4625 ********************************************************************/
4627 static WERROR enumprinters_level1( uint32 flags, fstring name,
4628 RPC_BUFFER *buffer, uint32 offered,
4629 uint32 *needed, uint32 *returned)
4631 /* Not all the flags are equals */
4633 if (flags & PRINTER_ENUM_LOCAL)
4634 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4636 if (flags & PRINTER_ENUM_NAME)
4637 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4639 #if 0 /* JERRY - disabled for now */
4640 if (flags & PRINTER_ENUM_REMOTE)
4641 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4644 if (flags & PRINTER_ENUM_NETWORK)
4645 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4647 return WERR_OK; /* NT4sp5 does that */
4650 /********************************************************************
4651 * handle enumeration of printers at level 2
4652 ********************************************************************/
4654 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4655 RPC_BUFFER *buffer, uint32 offered,
4656 uint32 *needed, uint32 *returned)
4658 char *s = servername;
4660 if (flags & PRINTER_ENUM_LOCAL) {
4661 return enum_all_printers_info_2(buffer, offered, needed, returned);
4664 if (flags & PRINTER_ENUM_NAME) {
4665 if ((servername[0] == '\\') && (servername[1] == '\\'))
4667 if (is_myname_or_ipaddr(s))
4668 return enum_all_printers_info_2(buffer, offered, needed, returned);
4670 return WERR_INVALID_NAME;
4673 if (flags & PRINTER_ENUM_REMOTE)
4674 return WERR_UNKNOWN_LEVEL;
4679 /********************************************************************
4680 * handle enumeration of printers at level 5
4681 ********************************************************************/
4683 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4684 RPC_BUFFER *buffer, uint32 offered,
4685 uint32 *needed, uint32 *returned)
4687 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4691 /********************************************************************
4692 * api_spoolss_enumprinters
4694 * called from api_spoolss_enumprinters (see this to understand)
4695 ********************************************************************/
4697 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4699 uint32 flags = q_u->flags;
4700 UNISTR2 *servername = &q_u->servername;
4701 uint32 level = q_u->level;
4702 RPC_BUFFER *buffer = NULL;
4703 uint32 offered = q_u->offered;
4704 uint32 *needed = &r_u->needed;
4705 uint32 *returned = &r_u->returned;
4709 /* that's an [in out] buffer */
4711 if ( q_u->buffer ) {
4712 rpcbuf_move(q_u->buffer, &r_u->buffer);
4713 buffer = r_u->buffer;
4716 DEBUG(4,("_spoolss_enumprinters\n"));
4723 * flags==PRINTER_ENUM_NAME
4724 * if name=="" then enumerates all printers
4725 * if name!="" then enumerate the printer
4726 * flags==PRINTER_ENUM_REMOTE
4727 * name is NULL, enumerate printers
4728 * Level 2: name!="" enumerates printers, name can't be NULL
4729 * Level 3: doesn't exist
4730 * Level 4: does a local registry lookup
4731 * Level 5: same as Level 2
4734 unistr2_to_ascii(name, servername, sizeof(name)-1);
4739 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4741 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4743 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4748 return WERR_UNKNOWN_LEVEL;
4751 /****************************************************************************
4752 ****************************************************************************/
4754 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4756 PRINTER_INFO_0 *printer=NULL;
4757 WERROR result = WERR_OK;
4759 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4762 construct_printer_info_0(print_hnd, printer, snum);
4764 /* check the required size. */
4765 *needed += spoolss_size_printer_info_0(printer);
4767 if (*needed > offered) {
4768 result = WERR_INSUFFICIENT_BUFFER;
4772 if (!rpcbuf_alloc_size(buffer, *needed)) {
4773 result = WERR_NOMEM;
4777 /* fill the buffer with the structures */
4778 smb_io_printer_info_0("", buffer, printer, 0);
4788 /****************************************************************************
4789 ****************************************************************************/
4791 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4793 PRINTER_INFO_1 *printer=NULL;
4794 WERROR result = WERR_OK;
4796 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4799 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4801 /* check the required size. */
4802 *needed += spoolss_size_printer_info_1(printer);
4804 if (*needed > offered) {
4805 result = WERR_INSUFFICIENT_BUFFER;
4809 if (!rpcbuf_alloc_size(buffer, *needed)) {
4810 result = WERR_NOMEM;
4814 /* fill the buffer with the structures */
4815 smb_io_printer_info_1("", buffer, printer, 0);
4824 /****************************************************************************
4825 ****************************************************************************/
4827 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4829 PRINTER_INFO_2 *printer=NULL;
4830 WERROR result = WERR_OK;
4832 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4835 construct_printer_info_2(print_hnd, printer, snum);
4837 /* check the required size. */
4838 *needed += spoolss_size_printer_info_2(printer);
4840 if (*needed > offered) {
4841 result = WERR_INSUFFICIENT_BUFFER;
4845 if (!rpcbuf_alloc_size(buffer, *needed)) {
4846 result = WERR_NOMEM;
4850 /* fill the buffer with the structures */
4851 if (!smb_io_printer_info_2("", buffer, printer, 0))
4852 result = WERR_NOMEM;
4856 free_printer_info_2(printer);
4861 /****************************************************************************
4862 ****************************************************************************/
4864 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4866 PRINTER_INFO_3 *printer=NULL;
4867 WERROR result = WERR_OK;
4869 if (!construct_printer_info_3(print_hnd, &printer, snum))
4872 /* check the required size. */
4873 *needed += spoolss_size_printer_info_3(printer);
4875 if (*needed > offered) {
4876 result = WERR_INSUFFICIENT_BUFFER;
4880 if (!rpcbuf_alloc_size(buffer, *needed)) {
4881 result = WERR_NOMEM;
4885 /* fill the buffer with the structures */
4886 smb_io_printer_info_3("", buffer, printer, 0);
4890 free_printer_info_3(printer);
4895 /****************************************************************************
4896 ****************************************************************************/
4898 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4900 PRINTER_INFO_4 *printer=NULL;
4901 WERROR result = WERR_OK;
4903 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4906 if (!construct_printer_info_4(print_hnd, printer, snum))
4909 /* check the required size. */
4910 *needed += spoolss_size_printer_info_4(printer);
4912 if (*needed > offered) {
4913 result = WERR_INSUFFICIENT_BUFFER;
4917 if (!rpcbuf_alloc_size(buffer, *needed)) {
4918 result = WERR_NOMEM;
4922 /* fill the buffer with the structures */
4923 smb_io_printer_info_4("", buffer, printer, 0);
4927 free_printer_info_4(printer);
4932 /****************************************************************************
4933 ****************************************************************************/
4935 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4937 PRINTER_INFO_5 *printer=NULL;
4938 WERROR result = WERR_OK;
4940 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4943 if (!construct_printer_info_5(print_hnd, printer, snum))
4946 /* check the required size. */
4947 *needed += spoolss_size_printer_info_5(printer);
4949 if (*needed > offered) {
4950 result = WERR_INSUFFICIENT_BUFFER;
4954 if (!rpcbuf_alloc_size(buffer, *needed)) {
4955 result = WERR_NOMEM;
4959 /* fill the buffer with the structures */
4960 smb_io_printer_info_5("", buffer, printer, 0);
4964 free_printer_info_5(printer);
4969 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4971 PRINTER_INFO_7 *printer=NULL;
4972 WERROR result = WERR_OK;
4974 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4977 if (!construct_printer_info_7(print_hnd, printer, snum))
4980 /* check the required size. */
4981 *needed += spoolss_size_printer_info_7(printer);
4983 if (*needed > offered) {
4984 result = WERR_INSUFFICIENT_BUFFER;
4988 if (!rpcbuf_alloc_size(buffer, *needed)) {
4989 result = WERR_NOMEM;
4994 /* fill the buffer with the structures */
4995 smb_io_printer_info_7("", buffer, printer, 0);
4999 free_printer_info_7(printer);
5004 /****************************************************************************
5005 ****************************************************************************/
5007 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5009 POLICY_HND *handle = &q_u->handle;
5010 uint32 level = q_u->level;
5011 RPC_BUFFER *buffer = NULL;
5012 uint32 offered = q_u->offered;
5013 uint32 *needed = &r_u->needed;
5014 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5018 /* that's an [in out] buffer */
5020 if ( q_u->buffer ) {
5021 rpcbuf_move(q_u->buffer, &r_u->buffer);
5022 buffer = r_u->buffer;
5027 if (!get_printer_snum(p, handle, &snum))
5032 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5034 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5036 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5038 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5040 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5042 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5044 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5046 return WERR_UNKNOWN_LEVEL;
5049 /********************************************************************
5050 * fill a DRIVER_INFO_1 struct
5051 ********************************************************************/
5053 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5055 init_unistr( &info->name, driver.info_3->name);
5058 /********************************************************************
5059 * construct_printer_driver_info_1
5060 ********************************************************************/
5062 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5064 NT_PRINTER_INFO_LEVEL *printer = NULL;
5065 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5067 ZERO_STRUCT(driver);
5069 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5070 return WERR_INVALID_PRINTER_NAME;
5072 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5073 return WERR_UNKNOWN_PRINTER_DRIVER;
5075 fill_printer_driver_info_1(info, driver, servername, architecture);
5077 free_a_printer(&printer,2);
5082 /********************************************************************
5083 * construct_printer_driver_info_2
5084 * fill a printer_info_2 struct
5085 ********************************************************************/
5087 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5091 info->version=driver.info_3->cversion;
5093 init_unistr( &info->name, driver.info_3->name );
5094 init_unistr( &info->architecture, driver.info_3->environment );
5097 if (strlen(driver.info_3->driverpath)) {
5098 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5099 init_unistr( &info->driverpath, temp );
5101 init_unistr( &info->driverpath, "" );
5103 if (strlen(driver.info_3->datafile)) {
5104 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5105 init_unistr( &info->datafile, temp );
5107 init_unistr( &info->datafile, "" );
5109 if (strlen(driver.info_3->configfile)) {
5110 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5111 init_unistr( &info->configfile, temp );
5113 init_unistr( &info->configfile, "" );
5116 /********************************************************************
5117 * construct_printer_driver_info_2
5118 * fill a printer_info_2 struct
5119 ********************************************************************/
5121 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5123 NT_PRINTER_INFO_LEVEL *printer = NULL;
5124 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5126 ZERO_STRUCT(printer);
5127 ZERO_STRUCT(driver);
5129 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5130 return WERR_INVALID_PRINTER_NAME;
5132 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5133 return WERR_UNKNOWN_PRINTER_DRIVER;
5135 fill_printer_driver_info_2(info, driver, servername);
5137 free_a_printer(&printer,2);
5142 /********************************************************************
5143 * copy a strings array and convert to UNICODE
5145 * convert an array of ascii string to a UNICODE string
5146 ********************************************************************/
5148 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5156 DEBUG(6,("init_unistr_array\n"));
5167 v = ""; /* hack to handle null lists */
5170 /* hack to allow this to be used in places other than when generating
5171 the list of dependent files */
5174 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5178 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5180 /* add one extra unit16 for the second terminating NULL */
5182 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5183 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5191 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5196 /* special case for ""; we need to add both NULL's here */
5198 (*uni_array)[j++]=0x0000;
5199 (*uni_array)[j]=0x0000;
5202 DEBUGADD(6,("last one:done\n"));
5204 /* return size of array in uint16's */
5209 /********************************************************************
5210 * construct_printer_info_3
5211 * fill a printer_info_3 struct
5212 ********************************************************************/
5214 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5220 info->version=driver.info_3->cversion;
5222 init_unistr( &info->name, driver.info_3->name );
5223 init_unistr( &info->architecture, driver.info_3->environment );
5225 if (strlen(driver.info_3->driverpath)) {
5226 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5227 init_unistr( &info->driverpath, temp );
5229 init_unistr( &info->driverpath, "" );
5231 if (strlen(driver.info_3->datafile)) {
5232 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5233 init_unistr( &info->datafile, temp );
5235 init_unistr( &info->datafile, "" );
5237 if (strlen(driver.info_3->configfile)) {
5238 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5239 init_unistr( &info->configfile, temp );
5241 init_unistr( &info->configfile, "" );
5243 if (strlen(driver.info_3->helpfile)) {
5244 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5245 init_unistr( &info->helpfile, temp );
5247 init_unistr( &info->helpfile, "" );
5249 init_unistr( &info->monitorname, driver.info_3->monitorname );
5250 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5252 info->dependentfiles=NULL;
5253 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5256 /********************************************************************
5257 * construct_printer_info_3
5258 * fill a printer_info_3 struct
5259 ********************************************************************/
5261 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5263 NT_PRINTER_INFO_LEVEL *printer = NULL;
5264 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5266 ZERO_STRUCT(driver);
5268 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5269 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5270 if (!W_ERROR_IS_OK(status))
5271 return WERR_INVALID_PRINTER_NAME;
5273 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5274 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5279 * I put this code in during testing. Helpful when commenting out the
5280 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5281 * as win2k always queries the driver using an infor level of 6.
5282 * I've left it in (but ifdef'd out) because I'll probably
5283 * use it in experimentation again in the future. --jerry 22/01/2002
5286 if (!W_ERROR_IS_OK(status)) {
5288 * Is this a W2k client ?
5291 /* Yes - try again with a WinNT driver. */
5293 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5294 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5298 if (!W_ERROR_IS_OK(status)) {
5299 free_a_printer(&printer,2);
5300 return WERR_UNKNOWN_PRINTER_DRIVER;
5308 fill_printer_driver_info_3(info, driver, servername);
5310 free_a_printer(&printer,2);
5315 /********************************************************************
5316 * construct_printer_info_6
5317 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5318 ********************************************************************/
5320 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5326 memset(&nullstr, '\0', sizeof(fstring));
5328 info->version=driver.info_3->cversion;
5330 init_unistr( &info->name, driver.info_3->name );
5331 init_unistr( &info->architecture, driver.info_3->environment );
5333 if (strlen(driver.info_3->driverpath)) {
5334 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5335 init_unistr( &info->driverpath, temp );
5337 init_unistr( &info->driverpath, "" );
5339 if (strlen(driver.info_3->datafile)) {
5340 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5341 init_unistr( &info->datafile, temp );
5343 init_unistr( &info->datafile, "" );
5345 if (strlen(driver.info_3->configfile)) {
5346 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5347 init_unistr( &info->configfile, temp );
5349 init_unistr( &info->configfile, "" );
5351 if (strlen(driver.info_3->helpfile)) {
5352 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5353 init_unistr( &info->helpfile, temp );
5355 init_unistr( &info->helpfile, "" );
5357 init_unistr( &info->monitorname, driver.info_3->monitorname );
5358 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5360 info->dependentfiles = NULL;
5361 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5363 info->previousdrivernames=NULL;
5364 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5366 info->driver_date.low=0;
5367 info->driver_date.high=0;
5370 info->driver_version_low=0;
5371 info->driver_version_high=0;
5373 init_unistr( &info->mfgname, "");
5374 init_unistr( &info->oem_url, "");
5375 init_unistr( &info->hardware_id, "");
5376 init_unistr( &info->provider, "");
5379 /********************************************************************
5380 * construct_printer_info_6
5381 * fill a printer_info_6 struct
5382 ********************************************************************/
5384 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5385 fstring servername, fstring architecture, uint32 version)
5387 NT_PRINTER_INFO_LEVEL *printer = NULL;
5388 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5391 ZERO_STRUCT(driver);
5393 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5395 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5397 if (!W_ERROR_IS_OK(status))
5398 return WERR_INVALID_PRINTER_NAME;
5400 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5402 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5404 if (!W_ERROR_IS_OK(status))
5407 * Is this a W2k client ?
5411 free_a_printer(&printer,2);
5412 return WERR_UNKNOWN_PRINTER_DRIVER;
5415 /* Yes - try again with a WinNT driver. */
5417 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5418 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5419 if (!W_ERROR_IS_OK(status)) {
5420 free_a_printer(&printer,2);
5421 return WERR_UNKNOWN_PRINTER_DRIVER;
5425 fill_printer_driver_info_6(info, driver, servername);
5427 free_a_printer(&printer,2);
5428 free_a_printer_driver(driver, 3);
5433 /****************************************************************************
5434 ****************************************************************************/
5436 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5438 SAFE_FREE(info->dependentfiles);
5441 /****************************************************************************
5442 ****************************************************************************/
5444 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5446 SAFE_FREE(info->dependentfiles);
5449 /****************************************************************************
5450 ****************************************************************************/
5452 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5454 DRIVER_INFO_1 *info=NULL;
5457 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5460 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5461 if (!W_ERROR_IS_OK(result))
5464 /* check the required size. */
5465 *needed += spoolss_size_printer_driver_info_1(info);
5467 if (*needed > offered) {
5468 result = WERR_INSUFFICIENT_BUFFER;
5472 if (!rpcbuf_alloc_size(buffer, *needed)) {
5473 result = WERR_NOMEM;
5477 /* fill the buffer with the structures */
5478 smb_io_printer_driver_info_1("", buffer, info, 0);
5487 /****************************************************************************
5488 ****************************************************************************/
5490 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5492 DRIVER_INFO_2 *info=NULL;
5495 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5498 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5499 if (!W_ERROR_IS_OK(result))
5502 /* check the required size. */
5503 *needed += spoolss_size_printer_driver_info_2(info);
5505 if (*needed > offered) {
5506 result = WERR_INSUFFICIENT_BUFFER;
5510 if (!rpcbuf_alloc_size(buffer, *needed)) {
5511 result = WERR_NOMEM;
5515 /* fill the buffer with the structures */
5516 smb_io_printer_driver_info_2("", buffer, info, 0);
5525 /****************************************************************************
5526 ****************************************************************************/
5528 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5535 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5536 if (!W_ERROR_IS_OK(result))
5539 /* check the required size. */
5540 *needed += spoolss_size_printer_driver_info_3(&info);
5542 if (*needed > offered) {
5543 result = WERR_INSUFFICIENT_BUFFER;
5547 if (!rpcbuf_alloc_size(buffer, *needed)) {
5548 result = WERR_NOMEM;
5552 /* fill the buffer with the structures */
5553 smb_io_printer_driver_info_3("", buffer, &info, 0);
5556 free_printer_driver_info_3(&info);
5561 /****************************************************************************
5562 ****************************************************************************/
5564 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5571 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5572 if (!W_ERROR_IS_OK(result))
5575 /* check the required size. */
5576 *needed += spoolss_size_printer_driver_info_6(&info);
5578 if (*needed > offered) {
5579 result = WERR_INSUFFICIENT_BUFFER;
5583 if (!rpcbuf_alloc_size(buffer, *needed)) {
5584 result = WERR_NOMEM;
5588 /* fill the buffer with the structures */
5589 smb_io_printer_driver_info_6("", buffer, &info, 0);
5592 free_printer_driver_info_6(&info);
5597 /****************************************************************************
5598 ****************************************************************************/
5600 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5602 POLICY_HND *handle = &q_u->handle;
5603 UNISTR2 *uni_arch = &q_u->architecture;
5604 uint32 level = q_u->level;
5605 uint32 clientmajorversion = q_u->clientmajorversion;
5606 RPC_BUFFER *buffer = NULL;
5607 uint32 offered = q_u->offered;
5608 uint32 *needed = &r_u->needed;
5609 uint32 *servermajorversion = &r_u->servermajorversion;
5610 uint32 *serverminorversion = &r_u->serverminorversion;
5611 Printer_entry *printer;
5614 fstring architecture;
5617 /* that's an [in out] buffer */
5619 if ( q_u->buffer ) {
5620 rpcbuf_move(q_u->buffer, &r_u->buffer);
5621 buffer = r_u->buffer;
5624 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5626 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5627 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5628 return WERR_INVALID_PRINTER_NAME;
5632 *servermajorversion = 0;
5633 *serverminorversion = 0;
5635 fstrcpy(servername, get_server_name( printer ));
5636 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5638 if (!get_printer_snum(p, handle, &snum))
5643 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5645 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5647 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5649 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5652 /* apparently this call is the equivalent of
5653 EnumPrinterDataEx() for the DsDriver key */
5658 return WERR_UNKNOWN_LEVEL;
5661 /****************************************************************************
5662 ****************************************************************************/
5664 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5666 POLICY_HND *handle = &q_u->handle;
5668 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5671 DEBUG(3,("Error in startpageprinter printer handle\n"));
5675 Printer->page_started=True;
5679 /****************************************************************************
5680 ****************************************************************************/
5682 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5684 POLICY_HND *handle = &q_u->handle;
5687 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5690 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5694 if (!get_printer_snum(p, handle, &snum))
5697 Printer->page_started=False;
5698 print_job_endpage(snum, Printer->jobid);
5703 /********************************************************************
5704 * api_spoolss_getprinter
5705 * called from the spoolss dispatcher
5707 ********************************************************************/
5709 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5711 POLICY_HND *handle = &q_u->handle;
5712 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5713 uint32 *jobid = &r_u->jobid;
5715 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5719 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5720 struct current_user user;
5723 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5727 get_current_user(&user, p);
5730 * a nice thing with NT is it doesn't listen to what you tell it.
5731 * when asked to send _only_ RAW datas, it tries to send datas
5734 * So I add checks like in NT Server ...
5737 if (info_1->p_datatype != 0) {
5738 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5739 if (strcmp(datatype, "RAW") != 0) {
5741 return WERR_INVALID_DATATYPE;
5745 /* get the share number of the printer */
5746 if (!get_printer_snum(p, handle, &snum)) {
5750 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5752 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5754 /* An error occured in print_job_start() so return an appropriate
5757 if (Printer->jobid == -1) {
5758 return map_werror_from_unix(errno);
5761 Printer->document_started=True;
5762 (*jobid) = Printer->jobid;
5767 /********************************************************************
5768 * api_spoolss_getprinter
5769 * called from the spoolss dispatcher
5771 ********************************************************************/
5773 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5775 POLICY_HND *handle = &q_u->handle;
5777 return _spoolss_enddocprinter_internal(p, handle);
5780 /****************************************************************************
5781 ****************************************************************************/
5783 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5785 POLICY_HND *handle = &q_u->handle;
5786 uint32 buffer_size = q_u->buffer_size;
5787 uint8 *buffer = q_u->buffer;
5788 uint32 *buffer_written = &q_u->buffer_size2;
5790 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5793 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5794 r_u->buffer_written = q_u->buffer_size2;
5798 if (!get_printer_snum(p, handle, &snum))
5801 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5802 (SMB_OFF_T)-1, (size_t)buffer_size);
5803 if (*buffer_written == (uint32)-1) {
5804 r_u->buffer_written = 0;
5805 if (errno == ENOSPC)
5806 return WERR_NO_SPOOL_SPACE;
5808 return WERR_ACCESS_DENIED;
5811 r_u->buffer_written = q_u->buffer_size2;
5816 /********************************************************************
5817 * api_spoolss_getprinter
5818 * called from the spoolss dispatcher
5820 ********************************************************************/
5822 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5825 struct current_user user;
5827 WERROR errcode = WERR_BADFUNC;
5828 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5830 get_current_user(&user, p);
5833 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5837 if (!get_printer_snum(p, handle, &snum))
5841 case PRINTER_CONTROL_PAUSE:
5842 if (print_queue_pause(&user, snum, &errcode)) {
5846 case PRINTER_CONTROL_RESUME:
5847 case PRINTER_CONTROL_UNPAUSE:
5848 if (print_queue_resume(&user, snum, &errcode)) {
5852 case PRINTER_CONTROL_PURGE:
5853 if (print_queue_purge(&user, snum, &errcode)) {
5858 return WERR_UNKNOWN_LEVEL;
5864 /********************************************************************
5865 * api_spoolss_abortprinter
5866 * From MSDN: "Deletes printer's spool file if printer is configured
5868 ********************************************************************/
5870 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5872 POLICY_HND *handle = &q_u->handle;
5873 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5875 struct current_user user;
5876 WERROR errcode = WERR_OK;
5879 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5883 if (!get_printer_snum(p, handle, &snum))
5886 get_current_user( &user, p );
5888 print_job_delete( &user, snum, Printer->jobid, &errcode );
5893 /********************************************************************
5894 * called by spoolss_api_setprinter
5895 * when updating a printer description
5896 ********************************************************************/
5898 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5899 const SPOOL_PRINTER_INFO_LEVEL *info,
5900 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5902 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5906 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5908 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5909 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5910 OUR_HANDLE(handle)));
5912 result = WERR_BADFID;
5916 /* Check the user has permissions to change the security
5917 descriptor. By experimentation with two NT machines, the user
5918 requires Full Access to the printer to change security
5921 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5922 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5923 result = WERR_ACCESS_DENIED;
5927 /* NT seems to like setting the security descriptor even though
5928 nothing may have actually changed. */
5930 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5932 if (DEBUGLEVEL >= 10) {
5936 the_acl = old_secdesc_ctr->sec->dacl;
5937 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5938 PRINTERNAME(snum), the_acl->num_aces));
5940 for (i = 0; i < the_acl->num_aces; i++) {
5943 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5945 DEBUG(10, ("%s 0x%08x\n", sid_str,
5946 the_acl->ace[i].info.mask));
5949 the_acl = secdesc_ctr->sec->dacl;
5952 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5953 PRINTERNAME(snum), the_acl->num_aces));
5955 for (i = 0; i < the_acl->num_aces; i++) {
5958 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5960 DEBUG(10, ("%s 0x%08x\n", sid_str,
5961 the_acl->ace[i].info.mask));
5964 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5968 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5970 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5975 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5982 /********************************************************************
5983 Canonicalize printer info from a client
5985 ATTN: It does not matter what we set the servername to hear
5986 since we do the necessary work in get_a_printer() to set it to
5987 the correct value based on what the client sent in the
5988 _spoolss_open_printer_ex().
5989 ********************************************************************/
5991 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5993 fstring printername;
5996 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5997 "portname=%s drivername=%s comment=%s location=%s\n",
5998 info->servername, info->printername, info->sharename,
5999 info->portname, info->drivername, info->comment, info->location));
6001 /* we force some elements to "correct" values */
6002 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6003 fstrcpy(info->sharename, lp_servicename(snum));
6005 /* check to see if we allow printername != sharename */
6007 if ( lp_force_printername(snum) ) {
6008 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6009 global_myname(), info->sharename );
6012 /* make sure printername is in \\server\printername format */
6014 fstrcpy( printername, info->printername );
6016 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6017 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6021 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6022 global_myname(), p );
6025 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6026 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6033 /****************************************************************************
6034 ****************************************************************************/
6036 static BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6038 char *cmd = lp_addprinter_cmd();
6044 fstring remote_machine = "%m";
6045 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6048 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6050 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6051 cmd, printer->info_2->printername, printer->info_2->sharename,
6052 printer->info_2->portname, printer->info_2->drivername,
6053 printer->info_2->location, printer->info_2->comment, remote_machine);
6055 is_print_op = user_has_privileges( token, &se_printop );
6057 DEBUG(10,("Running [%s]\n", command));
6059 /********* BEGIN SePrintOperatorPrivilege **********/
6064 if ( (ret = smbrun(command, &fd)) == 0 ) {
6065 /* Tell everyone we updated smb.conf. */
6066 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6072 /********* END SePrintOperatorPrivilege **********/
6074 DEBUGADD(10,("returned [%d]\n", ret));
6082 /* reload our services immediately */
6083 reload_services( False );
6086 /* Get lines and convert them back to dos-codepage */
6087 qlines = fd_lines_load(fd, &numlines);
6088 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6091 /* Set the portname to what the script says the portname should be. */
6092 /* but don't require anything to be return from the script exit a good error code */
6095 /* Set the portname to what the script says the portname should be. */
6096 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6097 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6100 file_lines_free(qlines);
6104 /********************************************************************
6105 * Called by spoolss_api_setprinter
6106 * when updating a printer description.
6107 ********************************************************************/
6109 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6110 const SPOOL_PRINTER_INFO_LEVEL *info,
6111 DEVICEMODE *devmode)
6114 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6115 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6120 DEBUG(8,("update_printer\n"));
6125 result = WERR_BADFID;
6129 if (!get_printer_snum(p, handle, &snum)) {
6130 result = WERR_BADFID;
6134 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6135 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6136 result = WERR_BADFID;
6140 DEBUGADD(8,("Converting info_2 struct\n"));
6143 * convert_printer_info converts the incoming
6144 * info from the client and overwrites the info
6145 * just read from the tdb in the pointer 'printer'.
6148 if (!convert_printer_info(info, printer, level)) {
6149 result = WERR_NOMEM;
6154 /* we have a valid devmode
6155 convert it and link it*/
6157 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6158 if (!convert_devicemode(printer->info_2->printername, devmode,
6159 &printer->info_2->devmode)) {
6160 result = WERR_NOMEM;
6165 /* Do sanity check on the requested changes for Samba */
6167 if (!check_printer_ok(printer->info_2, snum)) {
6168 result = WERR_INVALID_PARAM;
6172 /* FIXME!!! If the driver has changed we really should verify that
6173 it is installed before doing much else --jerry */
6175 /* Check calling user has permission to update printer description */
6177 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6178 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6179 result = WERR_ACCESS_DENIED;
6183 /* Call addprinter hook */
6184 /* Check changes to see if this is really needed */
6186 if ( *lp_addprinter_cmd()
6187 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6188 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6189 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6190 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6192 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6193 result = WERR_ACCESS_DENIED;
6198 * make sure we actually reload the services after
6199 * this as smb.conf could have a new section in it
6200 * .... shouldn't .... but could
6202 reload_services(False);
6206 * When a *new* driver is bound to a printer, the drivername is used to
6207 * lookup previously saved driver initialization info, which is then
6208 * bound to the printer, simulating what happens in the Windows arch.
6210 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6212 if (!set_driver_init(printer, 2))
6214 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6215 printer->info_2->drivername));
6218 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6219 printer->info_2->drivername));
6221 notify_printer_driver(snum, printer->info_2->drivername);
6225 * flag which changes actually occured. This is a small subset of
6226 * all the possible changes. We also have to update things in the
6230 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6231 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6232 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6233 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6235 notify_printer_comment(snum, printer->info_2->comment);
6238 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6239 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6240 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6241 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6243 notify_printer_sharename(snum, printer->info_2->sharename);
6246 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6249 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6252 pname = printer->info_2->printername;
6255 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6256 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6257 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6259 notify_printer_printername( snum, pname );
6262 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6263 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6264 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6265 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6267 notify_printer_port(snum, printer->info_2->portname);
6270 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6271 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6272 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6273 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6275 notify_printer_location(snum, printer->info_2->location);
6278 /* here we need to update some more DsSpooler keys */
6279 /* uNCName, serverName, shortServerName */
6281 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6282 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6283 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6284 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6285 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6287 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6288 global_myname(), printer->info_2->sharename );
6289 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6290 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6291 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6293 /* Update printer info */
6294 result = mod_a_printer(printer, 2);
6297 free_a_printer(&printer, 2);
6298 free_a_printer(&old_printer, 2);
6304 /****************************************************************************
6305 ****************************************************************************/
6306 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6307 const SPOOL_PRINTER_INFO_LEVEL *info)
6310 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6312 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6314 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6319 if (!get_printer_snum(p, handle, &snum))
6322 nt_printer_publish(Printer, snum, info7->action);
6326 return WERR_UNKNOWN_LEVEL;
6329 /****************************************************************************
6330 ****************************************************************************/
6332 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6334 POLICY_HND *handle = &q_u->handle;
6335 uint32 level = q_u->level;
6336 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6337 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6338 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6339 uint32 command = q_u->command;
6342 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6345 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6349 /* check the level */
6352 return control_printer(handle, command, p);
6354 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6355 if (!W_ERROR_IS_OK(result))
6358 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6361 return update_printer_sec(handle, level, info, p,
6364 return publish_or_unpublish_printer(p, handle, info);
6366 return WERR_UNKNOWN_LEVEL;
6370 /****************************************************************************
6371 ****************************************************************************/
6373 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6375 POLICY_HND *handle = &q_u->handle;
6376 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6379 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6383 if (Printer->notify.client_connected==True) {
6386 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6388 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6389 !get_printer_snum(p, handle, &snum) )
6392 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6395 Printer->notify.flags=0;
6396 Printer->notify.options=0;
6397 Printer->notify.localmachine[0]='\0';
6398 Printer->notify.printerlocal=0;
6399 if (Printer->notify.option)
6400 free_spool_notify_option(&Printer->notify.option);
6401 Printer->notify.client_connected=False;
6406 /****************************************************************************
6407 ****************************************************************************/
6409 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6411 /* that's an [in out] buffer */
6414 rpcbuf_move(q_u->buffer, &r_u->buffer);
6417 return WERR_INVALID_PARAM; /* this is what a NT server
6418 returns for AddJob. AddJob
6419 must fail on non-local
6423 /****************************************************************************
6424 ****************************************************************************/
6426 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6427 int position, int snum,
6428 NT_PRINTER_INFO_LEVEL *ntprinter)
6432 t=gmtime(&queue->time);
6434 job_info->jobid=queue->job;
6435 init_unistr(&job_info->printername, lp_servicename(snum));
6436 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6437 init_unistr(&job_info->username, queue->fs_user);
6438 init_unistr(&job_info->document, queue->fs_file);
6439 init_unistr(&job_info->datatype, "RAW");
6440 init_unistr(&job_info->text_status, "");
6441 job_info->status=nt_printj_status(queue->status);
6442 job_info->priority=queue->priority;
6443 job_info->position=position;
6444 job_info->totalpages=queue->page_count;
6445 job_info->pagesprinted=0;
6447 make_systemtime(&job_info->submitted, t);
6450 /****************************************************************************
6451 ****************************************************************************/
6453 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6454 int position, int snum,
6455 NT_PRINTER_INFO_LEVEL *ntprinter,
6456 DEVICEMODE *devmode)
6460 t=gmtime(&queue->time);
6462 job_info->jobid=queue->job;
6464 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6466 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6467 init_unistr(&job_info->username, queue->fs_user);
6468 init_unistr(&job_info->document, queue->fs_file);
6469 init_unistr(&job_info->notifyname, queue->fs_user);
6470 init_unistr(&job_info->datatype, "RAW");
6471 init_unistr(&job_info->printprocessor, "winprint");
6472 init_unistr(&job_info->parameters, "");
6473 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6474 init_unistr(&job_info->text_status, "");
6476 /* and here the security descriptor */
6478 job_info->status=nt_printj_status(queue->status);
6479 job_info->priority=queue->priority;
6480 job_info->position=position;
6481 job_info->starttime=0;
6482 job_info->untiltime=0;
6483 job_info->totalpages=queue->page_count;
6484 job_info->size=queue->size;
6485 make_systemtime(&(job_info->submitted), t);
6486 job_info->timeelapsed=0;
6487 job_info->pagesprinted=0;
6489 job_info->devmode = devmode;
6494 /****************************************************************************
6495 Enumjobs at level 1.
6496 ****************************************************************************/
6498 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6499 NT_PRINTER_INFO_LEVEL *ntprinter,
6500 RPC_BUFFER *buffer, uint32 offered,
6501 uint32 *needed, uint32 *returned)
6505 WERROR result = WERR_OK;
6507 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6514 for (i=0; i<*returned; i++)
6515 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6519 /* check the required size. */
6520 for (i=0; i<*returned; i++)
6521 (*needed) += spoolss_size_job_info_1(&info[i]);
6523 if (*needed > offered) {
6524 result = WERR_INSUFFICIENT_BUFFER;
6528 if (!rpcbuf_alloc_size(buffer, *needed)) {
6529 result = WERR_NOMEM;
6533 /* fill the buffer with the structures */
6534 for (i=0; i<*returned; i++)
6535 smb_io_job_info_1("", buffer, &info[i], 0);
6541 if ( !W_ERROR_IS_OK(result) )
6547 /****************************************************************************
6548 Enumjobs at level 2.
6549 ****************************************************************************/
6551 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6552 NT_PRINTER_INFO_LEVEL *ntprinter,
6553 RPC_BUFFER *buffer, uint32 offered,
6554 uint32 *needed, uint32 *returned)
6556 JOB_INFO_2 *info = NULL;
6558 WERROR result = WERR_OK;
6559 DEVICEMODE *devmode = NULL;
6561 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6566 /* this should not be a failure condition if the devmode is NULL */
6568 devmode = construct_dev_mode(snum);
6570 for (i=0; i<*returned; i++)
6571 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6573 free_a_printer(&ntprinter, 2);
6576 /* check the required size. */
6577 for (i=0; i<*returned; i++)
6578 (*needed) += spoolss_size_job_info_2(&info[i]);
6580 if (*needed > offered) {
6581 result = WERR_INSUFFICIENT_BUFFER;
6585 if (!rpcbuf_alloc_size(buffer, *needed)) {
6586 result = WERR_NOMEM;
6590 /* fill the buffer with the structures */
6591 for (i=0; i<*returned; i++)
6592 smb_io_job_info_2("", buffer, &info[i], 0);
6595 free_devmode(devmode);
6598 if ( !W_ERROR_IS_OK(result) )
6605 /****************************************************************************
6607 ****************************************************************************/
6609 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6611 POLICY_HND *handle = &q_u->handle;
6612 uint32 level = q_u->level;
6613 RPC_BUFFER *buffer = NULL;
6614 uint32 offered = q_u->offered;
6615 uint32 *needed = &r_u->needed;
6616 uint32 *returned = &r_u->returned;
6618 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6620 print_status_struct prt_status;
6621 print_queue_struct *queue=NULL;
6623 /* that's an [in out] buffer */
6625 if ( q_u->buffer ) {
6626 rpcbuf_move(q_u->buffer, &r_u->buffer);
6627 buffer = r_u->buffer;
6630 DEBUG(4,("_spoolss_enumjobs\n"));
6635 /* lookup the printer snum and tdb entry */
6637 if (!get_printer_snum(p, handle, &snum))
6640 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6641 if ( !W_ERROR_IS_OK(wret) )
6644 *returned = print_queue_status(snum, &queue, &prt_status);
6645 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6647 if (*returned == 0) {
6654 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6657 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6662 wret = WERR_UNKNOWN_LEVEL;
6665 free_a_printer( &ntprinter, 2 );
6669 /****************************************************************************
6670 ****************************************************************************/
6672 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6677 /****************************************************************************
6678 ****************************************************************************/
6680 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6682 POLICY_HND *handle = &q_u->handle;
6683 uint32 jobid = q_u->jobid;
6684 uint32 command = q_u->command;
6686 struct current_user user;
6688 WERROR errcode = WERR_BADFUNC;
6690 if (!get_printer_snum(p, handle, &snum)) {
6694 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6695 return WERR_INVALID_PRINTER_NAME;
6698 get_current_user(&user, p);
6701 case JOB_CONTROL_CANCEL:
6702 case JOB_CONTROL_DELETE:
6703 if (print_job_delete(&user, snum, jobid, &errcode)) {
6707 case JOB_CONTROL_PAUSE:
6708 if (print_job_pause(&user, snum, jobid, &errcode)) {
6712 case JOB_CONTROL_RESTART:
6713 case JOB_CONTROL_RESUME:
6714 if (print_job_resume(&user, snum, jobid, &errcode)) {
6719 return WERR_UNKNOWN_LEVEL;
6725 /****************************************************************************
6726 Enumerates all printer drivers at level 1.
6727 ****************************************************************************/
6729 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6734 fstring *list = NULL;
6735 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6736 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6737 WERROR result = WERR_OK;
6741 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6743 ndrivers=get_ntdrivers(&list, architecture, version);
6744 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6750 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6751 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6752 SAFE_FREE(driver_info_1);
6756 else driver_info_1 = tdi1;
6759 for (i=0; i<ndrivers; i++) {
6761 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6762 ZERO_STRUCT(driver);
6763 status = get_a_printer_driver(&driver, 3, list[i],
6764 architecture, version);
6765 if (!W_ERROR_IS_OK(status)) {
6769 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6770 free_a_printer_driver(driver, 3);
6773 *returned+=ndrivers;
6777 /* check the required size. */
6778 for (i=0; i<*returned; i++) {
6779 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6780 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6783 if (*needed > offered) {
6784 result = WERR_INSUFFICIENT_BUFFER;
6788 if (!rpcbuf_alloc_size(buffer, *needed)) {
6789 result = WERR_NOMEM;
6793 /* fill the buffer with the driver structures */
6794 for (i=0; i<*returned; i++) {
6795 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6796 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6800 SAFE_FREE(driver_info_1);
6802 if ( !W_ERROR_IS_OK(result) )
6808 /****************************************************************************
6809 Enumerates all printer drivers at level 2.
6810 ****************************************************************************/
6812 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6817 fstring *list = NULL;
6818 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6819 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6820 WERROR result = WERR_OK;
6824 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6826 ndrivers=get_ntdrivers(&list, architecture, version);
6827 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6833 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6834 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6835 SAFE_FREE(driver_info_2);
6839 else driver_info_2 = tdi2;
6842 for (i=0; i<ndrivers; i++) {
6845 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6846 ZERO_STRUCT(driver);
6847 status = get_a_printer_driver(&driver, 3, list[i],
6848 architecture, version);
6849 if (!W_ERROR_IS_OK(status)) {
6853 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6854 free_a_printer_driver(driver, 3);
6857 *returned+=ndrivers;
6861 /* check the required size. */
6862 for (i=0; i<*returned; i++) {
6863 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6864 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6867 if (*needed > offered) {
6868 result = WERR_INSUFFICIENT_BUFFER;
6872 if (!rpcbuf_alloc_size(buffer, *needed)) {
6873 result = WERR_NOMEM;
6877 /* fill the buffer with the form structures */
6878 for (i=0; i<*returned; i++) {
6879 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6880 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6884 SAFE_FREE(driver_info_2);
6886 if ( !W_ERROR_IS_OK(result) )
6892 /****************************************************************************
6893 Enumerates all printer drivers at level 3.
6894 ****************************************************************************/
6896 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6901 fstring *list = NULL;
6902 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6903 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6904 WERROR result = WERR_OK;
6908 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6910 ndrivers=get_ntdrivers(&list, architecture, version);
6911 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6917 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6918 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6919 SAFE_FREE(driver_info_3);
6923 else driver_info_3 = tdi3;
6926 for (i=0; i<ndrivers; i++) {
6929 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6930 ZERO_STRUCT(driver);
6931 status = get_a_printer_driver(&driver, 3, list[i],
6932 architecture, version);
6933 if (!W_ERROR_IS_OK(status)) {
6937 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6938 free_a_printer_driver(driver, 3);
6941 *returned+=ndrivers;
6945 /* check the required size. */
6946 for (i=0; i<*returned; i++) {
6947 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6948 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6951 if (*needed > offered) {
6952 result = WERR_INSUFFICIENT_BUFFER;
6956 if (!rpcbuf_alloc_size(buffer, *needed)) {
6957 result = WERR_NOMEM;
6961 /* fill the buffer with the driver structures */
6962 for (i=0; i<*returned; i++) {
6963 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6964 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6968 for (i=0; i<*returned; i++)
6969 SAFE_FREE(driver_info_3[i].dependentfiles);
6971 SAFE_FREE(driver_info_3);
6973 if ( !W_ERROR_IS_OK(result) )
6979 /****************************************************************************
6980 Enumerates all printer drivers.
6981 ****************************************************************************/
6983 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6985 uint32 level = q_u->level;
6986 RPC_BUFFER *buffer = NULL;
6987 uint32 offered = q_u->offered;
6988 uint32 *needed = &r_u->needed;
6989 uint32 *returned = &r_u->returned;
6992 fstring architecture;
6994 /* that's an [in out] buffer */
6996 if ( q_u->buffer ) {
6997 rpcbuf_move(q_u->buffer, &r_u->buffer);
6998 buffer = r_u->buffer;
7001 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7006 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7007 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7009 if ( !is_myname_or_ipaddr( servername ) )
7010 return WERR_UNKNOWN_PRINTER_DRIVER;
7014 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7016 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7018 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7020 return WERR_UNKNOWN_LEVEL;
7024 /****************************************************************************
7025 ****************************************************************************/
7027 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7029 form->flag=list->flag;
7030 init_unistr(&form->name, list->name);
7031 form->width=list->width;
7032 form->length=list->length;
7033 form->left=list->left;
7034 form->top=list->top;
7035 form->right=list->right;
7036 form->bottom=list->bottom;
7039 /****************************************************************************
7040 ****************************************************************************/
7042 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7044 uint32 level = q_u->level;
7045 RPC_BUFFER *buffer = NULL;
7046 uint32 offered = q_u->offered;
7047 uint32 *needed = &r_u->needed;
7048 uint32 *numofforms = &r_u->numofforms;
7049 uint32 numbuiltinforms;
7051 nt_forms_struct *list=NULL;
7052 nt_forms_struct *builtinlist=NULL;
7057 /* that's an [in out] buffer */
7059 if ( q_u->buffer ) {
7060 rpcbuf_move(q_u->buffer, &r_u->buffer);
7061 buffer = r_u->buffer;
7064 DEBUG(4,("_spoolss_enumforms\n"));
7065 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7066 DEBUGADD(5,("Info level [%d]\n", level));
7068 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7069 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7070 *numofforms = get_ntforms(&list);
7071 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7072 *numofforms += numbuiltinforms;
7074 if (*numofforms == 0)
7075 return WERR_NO_MORE_ITEMS;
7079 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7084 /* construct the list of form structures */
7085 for (i=0; i<numbuiltinforms; i++) {
7086 DEBUGADD(6,("Filling form number [%d]\n",i));
7087 fill_form_1(&forms_1[i], &builtinlist[i]);
7090 SAFE_FREE(builtinlist);
7092 for (; i<*numofforms; i++) {
7093 DEBUGADD(6,("Filling form number [%d]\n",i));
7094 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7099 /* check the required size. */
7100 for (i=0; i<numbuiltinforms; i++) {
7101 DEBUGADD(6,("adding form [%d]'s size\n",i));
7102 buffer_size += spoolss_size_form_1(&forms_1[i]);
7104 for (; i<*numofforms; i++) {
7105 DEBUGADD(6,("adding form [%d]'s size\n",i));
7106 buffer_size += spoolss_size_form_1(&forms_1[i]);
7109 *needed=buffer_size;
7111 if (*needed > offered) {
7114 return WERR_INSUFFICIENT_BUFFER;
7117 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7123 /* fill the buffer with the form structures */
7124 for (i=0; i<numbuiltinforms; i++) {
7125 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7126 smb_io_form_1("", buffer, &forms_1[i], 0);
7128 for (; i<*numofforms; i++) {
7129 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7130 smb_io_form_1("", buffer, &forms_1[i], 0);
7139 SAFE_FREE(builtinlist);
7140 return WERR_UNKNOWN_LEVEL;
7145 /****************************************************************************
7146 ****************************************************************************/
7148 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7150 uint32 level = q_u->level;
7151 UNISTR2 *uni_formname = &q_u->formname;
7152 RPC_BUFFER *buffer = NULL;
7153 uint32 offered = q_u->offered;
7154 uint32 *needed = &r_u->needed;
7156 nt_forms_struct *list=NULL;
7157 nt_forms_struct builtin_form;
7162 int numofforms=0, i=0;
7164 /* that's an [in out] buffer */
7166 if ( q_u->buffer ) {
7167 rpcbuf_move(q_u->buffer, &r_u->buffer);
7168 buffer = r_u->buffer;
7171 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7173 DEBUG(4,("_spoolss_getform\n"));
7174 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7175 DEBUGADD(5,("Info level [%d]\n", level));
7177 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7178 if (!foundBuiltin) {
7179 numofforms = get_ntforms(&list);
7180 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7182 if (numofforms == 0)
7189 fill_form_1(&form_1, &builtin_form);
7192 /* Check if the requested name is in the list of form structures */
7193 for (i=0; i<numofforms; i++) {
7195 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7197 if (strequal(form_name, list[i].name)) {
7198 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7199 fill_form_1(&form_1, &list[i]);
7205 if (i == numofforms) {
7209 /* check the required size. */
7211 *needed=spoolss_size_form_1(&form_1);
7213 if (*needed > offered)
7214 return WERR_INSUFFICIENT_BUFFER;
7216 if (!rpcbuf_alloc_size(buffer, buffer_size))
7219 /* fill the buffer with the form structures */
7220 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7221 smb_io_form_1("", buffer, &form_1, 0);
7227 return WERR_UNKNOWN_LEVEL;
7231 /****************************************************************************
7232 ****************************************************************************/
7234 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7236 init_unistr(&port->port_name, name);
7239 /****************************************************************************
7240 ****************************************************************************/
7242 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7244 init_unistr(&port->port_name, name);
7245 init_unistr(&port->monitor_name, "Local Monitor");
7246 init_unistr(&port->description, "Local Port");
7247 port->port_type=PORT_TYPE_WRITE;
7251 /****************************************************************************
7253 ****************************************************************************/
7255 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7257 PORT_INFO_1 *ports=NULL;
7259 WERROR result = WERR_OK;
7261 if (*lp_enumports_cmd()) {
7262 char *cmd = lp_enumports_cmd();
7269 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7271 DEBUG(10,("Running [%s]\n", command));
7272 ret = smbrun(command, &fd);
7273 DEBUG(10,("Returned [%d]\n", ret));
7277 /* Is this the best error to return here? */
7278 return WERR_ACCESS_DENIED;
7282 qlines = fd_lines_load(fd, &numlines);
7283 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7287 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7288 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7289 dos_errstr(WERR_NOMEM)));
7290 file_lines_free(qlines);
7294 for (i=0; i<numlines; i++) {
7295 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7296 fill_port_1(&ports[i], qlines[i]);
7299 file_lines_free(qlines);
7302 *returned = numlines;
7305 *returned = 1; /* Sole Samba port returned. */
7307 if((ports=SMB_MALLOC_P(PORT_INFO_1)) == NULL)
7310 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7312 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7315 /* check the required size. */
7316 for (i=0; i<*returned; i++) {
7317 DEBUGADD(6,("adding port [%d]'s size\n", i));
7318 *needed += spoolss_size_port_info_1(&ports[i]);
7321 if (*needed > offered) {
7322 result = WERR_INSUFFICIENT_BUFFER;
7326 if (!rpcbuf_alloc_size(buffer, *needed)) {
7327 result = WERR_NOMEM;
7331 /* fill the buffer with the ports structures */
7332 for (i=0; i<*returned; i++) {
7333 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7334 smb_io_port_1("", buffer, &ports[i], 0);
7340 if ( !W_ERROR_IS_OK(result) )
7346 /****************************************************************************
7348 ****************************************************************************/
7350 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7352 PORT_INFO_2 *ports=NULL;
7354 WERROR result = WERR_OK;
7356 if (*lp_enumports_cmd()) {
7357 char *cmd = lp_enumports_cmd();
7366 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7367 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7369 path = lp_lockdir();
7371 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7372 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7375 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7376 ret = smbrun(command, &fd);
7377 DEBUGADD(10,("returned [%d]\n", ret));
7381 /* Is this the best error to return here? */
7382 return WERR_ACCESS_DENIED;
7386 qlines = fd_lines_load(fd, &numlines);
7387 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7391 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7392 file_lines_free(qlines);
7396 for (i=0; i<numlines; i++) {
7397 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7398 fill_port_2(&(ports[i]), qlines[i]);
7401 file_lines_free(qlines);
7404 *returned = numlines;
7410 if((ports=SMB_MALLOC_P(PORT_INFO_2)) == NULL)
7413 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7415 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7418 /* check the required size. */
7419 for (i=0; i<*returned; i++) {
7420 DEBUGADD(6,("adding port [%d]'s size\n", i));
7421 *needed += spoolss_size_port_info_2(&ports[i]);
7424 if (*needed > offered) {
7425 result = WERR_INSUFFICIENT_BUFFER;
7429 if (!rpcbuf_alloc_size(buffer, *needed)) {
7430 result = WERR_NOMEM;
7434 /* fill the buffer with the ports structures */
7435 for (i=0; i<*returned; i++) {
7436 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7437 smb_io_port_2("", buffer, &ports[i], 0);
7443 if ( !W_ERROR_IS_OK(result) )
7449 /****************************************************************************
7451 ****************************************************************************/
7453 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7455 uint32 level = q_u->level;
7456 RPC_BUFFER *buffer = NULL;
7457 uint32 offered = q_u->offered;
7458 uint32 *needed = &r_u->needed;
7459 uint32 *returned = &r_u->returned;
7461 /* that's an [in out] buffer */
7463 if ( q_u->buffer ) {
7464 rpcbuf_move(q_u->buffer, &r_u->buffer);
7465 buffer = r_u->buffer;
7468 DEBUG(4,("_spoolss_enumports\n"));
7475 return enumports_level_1(buffer, offered, needed, returned);
7477 return enumports_level_2(buffer, offered, needed, returned);
7479 return WERR_UNKNOWN_LEVEL;
7483 /****************************************************************************
7484 ****************************************************************************/
7486 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7487 const SPOOL_PRINTER_INFO_LEVEL *info,
7488 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7489 uint32 user_switch, const SPOOL_USER_CTR *user,
7492 NT_PRINTER_INFO_LEVEL *printer = NULL;
7495 WERROR err = WERR_OK;
7497 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7498 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7502 ZERO_STRUCTP(printer);
7504 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7505 if (!convert_printer_info(info, printer, 2)) {
7506 free_a_printer(&printer, 2);
7510 /* check to see if the printer already exists */
7512 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7513 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7514 printer->info_2->sharename));
7515 free_a_printer(&printer, 2);
7516 return WERR_PRINTER_ALREADY_EXISTS;
7519 /* FIXME!!! smbd should check to see if the driver is installed before
7520 trying to add a printer like this --jerry */
7522 if (*lp_addprinter_cmd() ) {
7523 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7524 free_a_printer(&printer,2);
7525 return WERR_ACCESS_DENIED;
7529 /* use our primary netbios name since get_a_printer() will convert
7530 it to what the client expects on a case by case basis */
7532 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7533 printer->info_2->sharename);
7536 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7537 free_a_printer(&printer,2);
7538 return WERR_ACCESS_DENIED;
7541 /* you must be a printer admin to add a new printer */
7542 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7543 free_a_printer(&printer,2);
7544 return WERR_ACCESS_DENIED;
7548 * Do sanity check on the requested changes for Samba.
7551 if (!check_printer_ok(printer->info_2, snum)) {
7552 free_a_printer(&printer,2);
7553 return WERR_INVALID_PARAM;
7557 * When a printer is created, the drivername bound to the printer is used
7558 * to lookup previously saved driver initialization info, which is then
7559 * bound to the new printer, simulating what happens in the Windows arch.
7564 set_driver_init(printer, 2);
7568 /* A valid devmode was included, convert and link it
7570 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7572 if (!convert_devicemode(printer->info_2->printername, devmode,
7573 &printer->info_2->devmode))
7577 /* write the ASCII on disk */
7578 err = mod_a_printer(printer, 2);
7579 if (!W_ERROR_IS_OK(err)) {
7580 free_a_printer(&printer,2);
7584 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7585 /* Handle open failed - remove addition. */
7586 del_a_printer(printer->info_2->sharename);
7587 free_a_printer(&printer,2);
7588 return WERR_ACCESS_DENIED;
7591 update_c_setprinter(False);
7592 free_a_printer(&printer,2);
7597 /****************************************************************************
7598 ****************************************************************************/
7600 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7602 UNISTR2 *uni_srv_name = q_u->server_name;
7603 uint32 level = q_u->level;
7604 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7605 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7606 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7607 uint32 user_switch = q_u->user_switch;
7608 SPOOL_USER_CTR *user = &q_u->user_ctr;
7609 POLICY_HND *handle = &r_u->handle;
7613 /* we don't handle yet */
7614 /* but I know what to do ... */
7615 return WERR_UNKNOWN_LEVEL;
7617 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7619 user_switch, user, handle);
7621 return WERR_UNKNOWN_LEVEL;
7625 /****************************************************************************
7626 ****************************************************************************/
7628 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7630 uint32 level = q_u->level;
7631 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7632 WERROR err = WERR_OK;
7633 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7634 struct current_user user;
7635 fstring driver_name;
7638 ZERO_STRUCT(driver);
7640 get_current_user(&user, p);
7642 if (!convert_printer_driver_info(info, &driver, level)) {
7647 DEBUG(5,("Cleaning driver's information\n"));
7648 err = clean_up_driver_struct(driver, level, &user);
7649 if (!W_ERROR_IS_OK(err))
7652 DEBUG(5,("Moving driver to final destination\n"));
7653 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7654 if (W_ERROR_IS_OK(err))
7655 err = WERR_ACCESS_DENIED;
7659 if (add_a_printer_driver(driver, level)!=0) {
7660 err = WERR_ACCESS_DENIED;
7664 /* BEGIN_ADMIN_LOG */
7667 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7668 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7669 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7672 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7673 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7674 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7680 * I think this is where he DrvUpgradePrinter() hook would be
7681 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7682 * server. Right now, we just need to send ourselves a message
7683 * to update each printer bound to this driver. --jerry
7686 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7687 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7692 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7693 * decide if the driver init data should be deleted. The rules are:
7694 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7695 * 2) delete init data only if there is no 2k/Xp driver
7696 * 3) always delete init data
7697 * The generalized rule is always use init data from the highest order driver.
7698 * It is necessary to follow the driver install by an initialization step to
7699 * finish off this process.
7702 version = driver.info_3->cversion;
7703 else if (level == 6)
7704 version = driver.info_6->version;
7709 * 9x printer driver - never delete init data
7712 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7717 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7718 * there is no 2k/Xp driver init data for this driver name.
7722 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7724 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7726 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7728 if (!del_driver_init(driver_name))
7729 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7732 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7734 free_a_printer_driver(driver1,3);
7735 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7742 * 2k or Xp printer driver - always delete init data
7745 if (!del_driver_init(driver_name))
7746 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7750 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7756 free_a_printer_driver(driver, level);
7760 /********************************************************************
7761 * spoolss_addprinterdriverex
7762 ********************************************************************/
7764 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7766 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7767 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7770 * we only support the semantics of AddPrinterDriver()
7771 * i.e. only copy files that are newer than existing ones
7774 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7775 return WERR_ACCESS_DENIED;
7777 ZERO_STRUCT(q_u_local);
7778 ZERO_STRUCT(r_u_local);
7780 /* just pass the information off to _spoolss_addprinterdriver() */
7781 q_u_local.server_name_ptr = q_u->server_name_ptr;
7782 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7783 q_u_local.level = q_u->level;
7784 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7786 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7789 /****************************************************************************
7790 ****************************************************************************/
7792 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7794 init_unistr(&info->name, name);
7797 /****************************************************************************
7798 ****************************************************************************/
7800 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7806 const char *short_archi;
7807 DRIVER_DIRECTORY_1 *info=NULL;
7808 WERROR result = WERR_OK;
7810 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7811 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7813 /* check for beginning double '\'s and that the server
7816 pservername = servername;
7817 if ( *pservername == '\\' && strlen(servername)>2 ) {
7821 if ( !is_myname_or_ipaddr( pservername ) )
7822 return WERR_INVALID_PARAM;
7824 if (!(short_archi = get_short_archi(long_archi)))
7825 return WERR_INVALID_ENVIRONMENT;
7827 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7830 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7832 DEBUG(4,("printer driver directory: [%s]\n", path));
7834 fill_driverdir_1(info, path);
7836 *needed += spoolss_size_driverdir_info_1(info);
7838 if (*needed > offered) {
7839 result = WERR_INSUFFICIENT_BUFFER;
7843 if (!rpcbuf_alloc_size(buffer, *needed)) {
7844 result = WERR_NOMEM;
7848 smb_io_driverdir_1("", buffer, info, 0);
7856 /****************************************************************************
7857 ****************************************************************************/
7859 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7861 UNISTR2 *name = &q_u->name;
7862 UNISTR2 *uni_environment = &q_u->environment;
7863 uint32 level = q_u->level;
7864 RPC_BUFFER *buffer = NULL;
7865 uint32 offered = q_u->offered;
7866 uint32 *needed = &r_u->needed;
7868 /* that's an [in out] buffer */
7870 if ( q_u->buffer ) {
7871 rpcbuf_move(q_u->buffer, &r_u->buffer);
7872 buffer = r_u->buffer;
7875 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7881 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7883 return WERR_UNKNOWN_LEVEL;
7887 /****************************************************************************
7888 ****************************************************************************/
7890 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7892 POLICY_HND *handle = &q_u->handle;
7893 uint32 idx = q_u->index;
7894 uint32 in_value_len = q_u->valuesize;
7895 uint32 in_data_len = q_u->datasize;
7896 uint32 *out_max_value_len = &r_u->valuesize;
7897 uint16 **out_value = &r_u->value;
7898 uint32 *out_value_len = &r_u->realvaluesize;
7899 uint32 *out_type = &r_u->type;
7900 uint32 *out_max_data_len = &r_u->datasize;
7901 uint8 **data_out = &r_u->data;
7902 uint32 *out_data_len = &r_u->realdatasize;
7904 NT_PRINTER_INFO_LEVEL *printer = NULL;
7906 uint32 biggest_valuesize;
7907 uint32 biggest_datasize;
7909 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7912 REGISTRY_VALUE *val = NULL;
7913 NT_PRINTER_DATA *p_data;
7914 int i, key_index, num_values;
7917 ZERO_STRUCT( printer );
7921 *out_max_data_len = 0;
7925 DEBUG(5,("spoolss_enumprinterdata\n"));
7928 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7932 if (!get_printer_snum(p,handle, &snum))
7935 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7936 if (!W_ERROR_IS_OK(result))
7939 p_data = &printer->info_2->data;
7940 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7945 * The NT machine wants to know the biggest size of value and data
7947 * cf: MSDN EnumPrinterData remark section
7950 if ( !in_value_len && !in_data_len && (key_index != -1) )
7952 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7954 biggest_valuesize = 0;
7955 biggest_datasize = 0;
7957 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7959 for ( i=0; i<num_values; i++ )
7961 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7963 name_length = strlen(val->valuename);
7964 if ( strlen(val->valuename) > biggest_valuesize )
7965 biggest_valuesize = name_length;
7967 if ( val->size > biggest_datasize )
7968 biggest_datasize = val->size;
7970 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7974 /* the value is an UNICODE string but real_value_size is the length
7975 in bytes including the trailing 0 */
7977 *out_value_len = 2 * (1+biggest_valuesize);
7978 *out_data_len = biggest_datasize;
7980 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7986 * the value len is wrong in NT sp3
7987 * that's the number of bytes not the number of unicode chars
7990 if ( key_index != -1 )
7991 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7996 /* out_value should default to "" or else NT4 has
7997 problems unmarshalling the response */
7999 *out_max_value_len=(in_value_len/sizeof(uint16));
8001 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8003 result = WERR_NOMEM;
8007 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8009 /* the data is counted in bytes */
8011 *out_max_data_len = in_data_len;
8012 *out_data_len = in_data_len;
8014 /* only allocate when given a non-zero data_len */
8016 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8018 result = WERR_NOMEM;
8022 result = WERR_NO_MORE_ITEMS;
8028 * - counted in bytes in the request
8029 * - counted in UNICODE chars in the max reply
8030 * - counted in bytes in the real size
8032 * take a pause *before* coding not *during* coding
8036 *out_max_value_len=(in_value_len/sizeof(uint16));
8037 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8039 result = WERR_NOMEM;
8043 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
8047 *out_type = regval_type( val );
8049 /* data - counted in bytes */
8051 *out_max_data_len = in_data_len;
8052 if ( (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8054 result = WERR_NOMEM;
8057 data_len = (size_t)regval_size(val);
8058 memcpy( *data_out, regval_data_p(val), data_len );
8059 *out_data_len = data_len;
8063 free_a_printer(&printer, 2);
8067 /****************************************************************************
8068 ****************************************************************************/
8070 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8072 POLICY_HND *handle = &q_u->handle;
8073 UNISTR2 *value = &q_u->value;
8074 uint32 type = q_u->type;
8075 uint8 *data = q_u->data;
8076 uint32 real_len = q_u->real_len;
8078 NT_PRINTER_INFO_LEVEL *printer = NULL;
8080 WERROR status = WERR_OK;
8081 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8084 DEBUG(5,("spoolss_setprinterdata\n"));
8087 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8091 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8092 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8093 return WERR_INVALID_PARAM;
8096 if (!get_printer_snum(p,handle, &snum))
8100 * Access check : NT returns "access denied" if you make a
8101 * SetPrinterData call without the necessary privildge.
8102 * we were originally returning OK if nothing changed
8103 * which made Win2k issue **a lot** of SetPrinterData
8104 * when connecting to a printer --jerry
8107 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8109 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8110 status = WERR_ACCESS_DENIED;
8114 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8115 if (!W_ERROR_IS_OK(status))
8118 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8121 * When client side code sets a magic printer data key, detect it and save
8122 * the current printer data and the magic key's data (its the DEVMODE) for
8123 * future printer/driver initializations.
8125 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8127 /* Set devmode and printer initialization info */
8128 status = save_driver_init( printer, 2, data, real_len );
8130 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8134 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8135 type, data, real_len );
8136 if ( W_ERROR_IS_OK(status) )
8137 status = mod_a_printer(printer, 2);
8141 free_a_printer(&printer, 2);
8146 /****************************************************************************
8147 ****************************************************************************/
8149 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8151 POLICY_HND *handle = &q_u->handle;
8152 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8155 DEBUG(5,("_spoolss_resetprinter\n"));
8158 * All we do is to check to see if the handle and queue is valid.
8159 * This call really doesn't mean anything to us because we only
8160 * support RAW printing. --jerry
8164 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8168 if (!get_printer_snum(p,handle, &snum))
8172 /* blindly return success */
8177 /****************************************************************************
8178 ****************************************************************************/
8180 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8182 POLICY_HND *handle = &q_u->handle;
8183 UNISTR2 *value = &q_u->valuename;
8185 NT_PRINTER_INFO_LEVEL *printer = NULL;
8187 WERROR status = WERR_OK;
8188 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8191 DEBUG(5,("spoolss_deleteprinterdata\n"));
8194 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8198 if (!get_printer_snum(p, handle, &snum))
8201 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8202 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8203 return WERR_ACCESS_DENIED;
8206 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8207 if (!W_ERROR_IS_OK(status))
8210 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8212 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8214 if ( W_ERROR_IS_OK(status) )
8215 mod_a_printer( printer, 2 );
8217 free_a_printer(&printer, 2);
8222 /****************************************************************************
8223 ****************************************************************************/
8225 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8227 POLICY_HND *handle = &q_u->handle;
8228 FORM *form = &q_u->form;
8229 nt_forms_struct tmpForm;
8231 WERROR status = WERR_OK;
8232 NT_PRINTER_INFO_LEVEL *printer = NULL;
8235 nt_forms_struct *list=NULL;
8236 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8238 DEBUG(5,("spoolss_addform\n"));
8241 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8246 /* forms can be added on printer of on the print server handle */
8248 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8250 if (!get_printer_snum(p,handle, &snum))
8253 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8254 if (!W_ERROR_IS_OK(status))
8258 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8259 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8260 status = WERR_ACCESS_DENIED;
8264 /* can't add if builtin */
8266 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8267 status = WERR_ALREADY_EXISTS;
8271 count = get_ntforms(&list);
8273 if(!add_a_form(&list, form, &count)) {
8274 status = WERR_NOMEM;
8278 write_ntforms(&list, count);
8281 * ChangeID must always be set if this is a printer
8284 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8285 status = mod_a_printer(printer, 2);
8289 free_a_printer(&printer, 2);
8295 /****************************************************************************
8296 ****************************************************************************/
8298 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8300 POLICY_HND *handle = &q_u->handle;
8301 UNISTR2 *form_name = &q_u->name;
8302 nt_forms_struct tmpForm;
8304 nt_forms_struct *list=NULL;
8305 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8307 WERROR status = WERR_OK;
8308 NT_PRINTER_INFO_LEVEL *printer = NULL;
8310 DEBUG(5,("spoolss_deleteform\n"));
8313 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8317 /* forms can be deleted on printer of on the print server handle */
8319 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8321 if (!get_printer_snum(p,handle, &snum))
8324 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8325 if (!W_ERROR_IS_OK(status))
8329 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8330 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8331 status = WERR_ACCESS_DENIED;
8335 /* can't delete if builtin */
8337 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8338 status = WERR_INVALID_PARAM;
8342 count = get_ntforms(&list);
8344 if ( !delete_a_form(&list, form_name, &count, &status ))
8348 * ChangeID must always be set if this is a printer
8351 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8352 status = mod_a_printer(printer, 2);
8356 free_a_printer(&printer, 2);
8362 /****************************************************************************
8363 ****************************************************************************/
8365 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8367 POLICY_HND *handle = &q_u->handle;
8368 FORM *form = &q_u->form;
8369 nt_forms_struct tmpForm;
8371 WERROR status = WERR_OK;
8372 NT_PRINTER_INFO_LEVEL *printer = NULL;
8375 nt_forms_struct *list=NULL;
8376 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8378 DEBUG(5,("spoolss_setform\n"));
8381 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8385 /* forms can be modified on printer of on the print server handle */
8387 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8389 if (!get_printer_snum(p,handle, &snum))
8392 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8393 if (!W_ERROR_IS_OK(status))
8397 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8398 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8399 status = WERR_ACCESS_DENIED;
8403 /* can't set if builtin */
8404 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8405 status = WERR_INVALID_PARAM;
8409 count = get_ntforms(&list);
8410 update_a_form(&list, form, count);
8411 write_ntforms(&list, count);
8414 * ChangeID must always be set if this is a printer
8417 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8418 status = mod_a_printer(printer, 2);
8423 free_a_printer(&printer, 2);
8429 /****************************************************************************
8430 enumprintprocessors level 1.
8431 ****************************************************************************/
8433 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8435 PRINTPROCESSOR_1 *info_1=NULL;
8436 WERROR result = WERR_OK;
8438 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8443 init_unistr(&info_1->name, "winprint");
8445 *needed += spoolss_size_printprocessor_info_1(info_1);
8447 if (*needed > offered) {
8448 result = WERR_INSUFFICIENT_BUFFER;
8452 if (!rpcbuf_alloc_size(buffer, *needed)) {
8453 result = WERR_NOMEM;
8457 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8462 if ( !W_ERROR_IS_OK(result) )
8468 /****************************************************************************
8469 ****************************************************************************/
8471 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8473 uint32 level = q_u->level;
8474 RPC_BUFFER *buffer = NULL;
8475 uint32 offered = q_u->offered;
8476 uint32 *needed = &r_u->needed;
8477 uint32 *returned = &r_u->returned;
8479 /* that's an [in out] buffer */
8481 if ( q_u->buffer ) {
8482 rpcbuf_move(q_u->buffer, &r_u->buffer);
8483 buffer = r_u->buffer;
8486 DEBUG(5,("spoolss_enumprintprocessors\n"));
8489 * Enumerate the print processors ...
8491 * Just reply with "winprint", to keep NT happy
8492 * and I can use my nice printer checker.
8500 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8502 return WERR_UNKNOWN_LEVEL;
8506 /****************************************************************************
8507 enumprintprocdatatypes level 1.
8508 ****************************************************************************/
8510 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8512 PRINTPROCDATATYPE_1 *info_1=NULL;
8513 WERROR result = WERR_NOMEM;
8515 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8520 init_unistr(&info_1->name, "RAW");
8522 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8524 if (*needed > offered) {
8525 result = WERR_INSUFFICIENT_BUFFER;
8529 if (!rpcbuf_alloc_size(buffer, *needed)) {
8530 result = WERR_NOMEM;
8534 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8539 if ( !W_ERROR_IS_OK(result) )
8545 /****************************************************************************
8546 ****************************************************************************/
8548 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8550 uint32 level = q_u->level;
8551 RPC_BUFFER *buffer = NULL;
8552 uint32 offered = q_u->offered;
8553 uint32 *needed = &r_u->needed;
8554 uint32 *returned = &r_u->returned;
8556 /* that's an [in out] buffer */
8558 if ( q_u->buffer ) {
8559 rpcbuf_move(q_u->buffer, &r_u->buffer);
8560 buffer = r_u->buffer;
8563 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8570 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8572 return WERR_UNKNOWN_LEVEL;
8576 /****************************************************************************
8577 enumprintmonitors level 1.
8578 ****************************************************************************/
8580 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8582 PRINTMONITOR_1 *info_1=NULL;
8583 WERROR result = WERR_OK;
8585 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8590 init_unistr(&info_1->name, "Local Port");
8592 *needed += spoolss_size_printmonitor_info_1(info_1);
8594 if (*needed > offered) {
8595 result = WERR_INSUFFICIENT_BUFFER;
8599 if (!rpcbuf_alloc_size(buffer, *needed)) {
8600 result = WERR_NOMEM;
8604 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8609 if ( !W_ERROR_IS_OK(result) )
8615 /****************************************************************************
8616 enumprintmonitors level 2.
8617 ****************************************************************************/
8619 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8621 PRINTMONITOR_2 *info_2=NULL;
8622 WERROR result = WERR_OK;
8624 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8629 init_unistr(&info_2->name, "Local Port");
8630 init_unistr(&info_2->environment, "Windows NT X86");
8631 init_unistr(&info_2->dll_name, "localmon.dll");
8633 *needed += spoolss_size_printmonitor_info_2(info_2);
8635 if (*needed > offered) {
8636 result = WERR_INSUFFICIENT_BUFFER;
8640 if (!rpcbuf_alloc_size(buffer, *needed)) {
8641 result = WERR_NOMEM;
8645 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8650 if ( !W_ERROR_IS_OK(result) )
8656 /****************************************************************************
8657 ****************************************************************************/
8659 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8661 uint32 level = q_u->level;
8662 RPC_BUFFER *buffer = NULL;
8663 uint32 offered = q_u->offered;
8664 uint32 *needed = &r_u->needed;
8665 uint32 *returned = &r_u->returned;
8667 /* that's an [in out] buffer */
8669 if ( q_u->buffer ) {
8670 rpcbuf_move(q_u->buffer, &r_u->buffer);
8671 buffer = r_u->buffer;
8674 DEBUG(5,("spoolss_enumprintmonitors\n"));
8677 * Enumerate the print monitors ...
8679 * Just reply with "Local Port", to keep NT happy
8680 * and I can use my nice printer checker.
8688 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8690 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8692 return WERR_UNKNOWN_LEVEL;
8696 /****************************************************************************
8697 ****************************************************************************/
8699 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8700 NT_PRINTER_INFO_LEVEL *ntprinter,
8701 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8706 JOB_INFO_1 *info_1=NULL;
8707 WERROR result = WERR_OK;
8709 info_1=SMB_MALLOC_P(JOB_INFO_1);
8711 if (info_1 == NULL) {
8715 for (i=0; i<count && found==False; i++) {
8716 if ((*queue)[i].job==(int)jobid)
8722 /* NT treats not found as bad param... yet another bad choice */
8723 return WERR_INVALID_PARAM;
8726 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8728 *needed += spoolss_size_job_info_1(info_1);
8730 if (*needed > offered) {
8731 result = WERR_INSUFFICIENT_BUFFER;
8735 if (!rpcbuf_alloc_size(buffer, *needed)) {
8736 result = WERR_NOMEM;
8740 smb_io_job_info_1("", buffer, info_1, 0);
8748 /****************************************************************************
8749 ****************************************************************************/
8751 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8752 NT_PRINTER_INFO_LEVEL *ntprinter,
8753 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8760 DEVICEMODE *devmode = NULL;
8761 NT_DEVICEMODE *nt_devmode = NULL;
8763 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8766 ZERO_STRUCTP(info_2);
8768 for ( i=0; i<count && found==False; i++ )
8770 if ((*queue)[i].job == (int)jobid)
8775 /* NT treats not found as bad param... yet another bad
8777 result = WERR_INVALID_PARAM;
8782 * if the print job does not have a DEVMODE associated with it,
8783 * just use the one for the printer. A NULL devicemode is not
8784 * a failure condition
8787 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8788 devmode = construct_dev_mode(snum);
8790 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8791 ZERO_STRUCTP( devmode );
8792 convert_nt_devicemode( devmode, nt_devmode );
8796 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8798 *needed += spoolss_size_job_info_2(info_2);
8800 if (*needed > offered) {
8801 result = WERR_INSUFFICIENT_BUFFER;
8805 if (!rpcbuf_alloc_size(buffer, *needed)) {
8806 result = WERR_NOMEM;
8810 smb_io_job_info_2("", buffer, info_2, 0);
8815 /* Cleanup allocated memory */
8817 free_job_info_2(info_2); /* Also frees devmode */
8823 /****************************************************************************
8824 ****************************************************************************/
8826 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8828 POLICY_HND *handle = &q_u->handle;
8829 uint32 jobid = q_u->jobid;
8830 uint32 level = q_u->level;
8831 RPC_BUFFER *buffer = NULL;
8832 uint32 offered = q_u->offered;
8833 uint32 *needed = &r_u->needed;
8834 WERROR wstatus = WERR_OK;
8835 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8838 print_queue_struct *queue = NULL;
8839 print_status_struct prt_status;
8841 /* that's an [in out] buffer */
8843 if ( q_u->buffer ) {
8844 rpcbuf_move(q_u->buffer, &r_u->buffer);
8845 buffer = r_u->buffer;
8848 DEBUG(5,("spoolss_getjob\n"));
8852 if (!get_printer_snum(p, handle, &snum))
8855 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8856 if ( !W_ERROR_IS_OK(wstatus) )
8859 count = print_queue_status(snum, &queue, &prt_status);
8861 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8862 count, prt_status.status, prt_status.message));
8866 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8867 buffer, offered, needed);
8870 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8871 buffer, offered, needed);
8874 wstatus = WERR_UNKNOWN_LEVEL;
8879 free_a_printer( &ntprinter, 2 );
8884 /********************************************************************
8885 spoolss_getprinterdataex
8887 From MSDN documentation of GetPrinterDataEx: pass request
8888 to GetPrinterData if key is "PrinterDriverData".
8889 ********************************************************************/
8891 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8893 POLICY_HND *handle = &q_u->handle;
8894 uint32 in_size = q_u->size;
8895 uint32 *type = &r_u->type;
8896 uint32 *out_size = &r_u->size;
8897 uint8 **data = &r_u->data;
8898 uint32 *needed = &r_u->needed;
8899 fstring keyname, valuename;
8901 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8903 NT_PRINTER_INFO_LEVEL *printer = NULL;
8905 WERROR status = WERR_OK;
8907 DEBUG(4,("_spoolss_getprinterdataex\n"));
8909 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8910 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8912 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8913 keyname, valuename));
8915 /* in case of problem, return some default values */
8919 *out_size = in_size;
8922 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8923 status = WERR_BADFID;
8927 /* Is the handle to a printer or to the server? */
8929 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8930 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8931 status = WERR_INVALID_PARAM;
8935 if ( !get_printer_snum(p,handle, &snum) )
8938 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8939 if ( !W_ERROR_IS_OK(status) )
8942 /* check to see if the keyname is valid */
8943 if ( !strlen(keyname) ) {
8944 status = WERR_INVALID_PARAM;
8948 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8949 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8950 free_a_printer( &printer, 2 );
8951 status = WERR_BADFILE;
8955 /* When given a new keyname, we should just create it */
8957 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8959 if (*needed > *out_size)
8960 status = WERR_MORE_DATA;
8963 if ( !W_ERROR_IS_OK(status) )
8965 DEBUG(5, ("error: allocating %d\n", *out_size));
8967 /* reply this param doesn't exist */
8971 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8972 status = WERR_NOMEM;
8982 free_a_printer( &printer, 2 );
8987 /********************************************************************
8988 * spoolss_setprinterdataex
8989 ********************************************************************/
8991 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8993 POLICY_HND *handle = &q_u->handle;
8994 uint32 type = q_u->type;
8995 uint8 *data = q_u->data;
8996 uint32 real_len = q_u->real_len;
8998 NT_PRINTER_INFO_LEVEL *printer = NULL;
9000 WERROR status = WERR_OK;
9001 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9006 DEBUG(4,("_spoolss_setprinterdataex\n"));
9008 /* From MSDN documentation of SetPrinterDataEx: pass request to
9009 SetPrinterData if key is "PrinterDriverData" */
9012 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9016 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
9017 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9018 return WERR_INVALID_PARAM;
9021 if ( !get_printer_snum(p,handle, &snum) )
9025 * Access check : NT returns "access denied" if you make a
9026 * SetPrinterData call without the necessary privildge.
9027 * we were originally returning OK if nothing changed
9028 * which made Win2k issue **a lot** of SetPrinterData
9029 * when connecting to a printer --jerry
9032 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9034 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9035 return WERR_ACCESS_DENIED;
9038 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9039 if (!W_ERROR_IS_OK(status))
9042 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9043 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9045 /* check for OID in valuename */
9047 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9053 /* save the registry data */
9055 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9057 if ( W_ERROR_IS_OK(status) )
9059 /* save the OID if one was specified */
9061 fstrcat( keyname, "\\" );
9062 fstrcat( keyname, SPOOL_OID_KEY );
9065 * I'm not checking the status here on purpose. Don't know
9066 * if this is right, but I'm returning the status from the
9067 * previous set_printer_dataex() call. I have no idea if
9068 * this is right. --jerry
9071 set_printer_dataex( printer, keyname, valuename,
9072 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9075 status = mod_a_printer(printer, 2);
9078 free_a_printer(&printer, 2);
9084 /********************************************************************
9085 * spoolss_deleteprinterdataex
9086 ********************************************************************/
9088 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9090 POLICY_HND *handle = &q_u->handle;
9091 UNISTR2 *value = &q_u->valuename;
9092 UNISTR2 *key = &q_u->keyname;
9094 NT_PRINTER_INFO_LEVEL *printer = NULL;
9096 WERROR status = WERR_OK;
9097 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9098 pstring valuename, keyname;
9100 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9103 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9107 if (!get_printer_snum(p, handle, &snum))
9110 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9111 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9112 return WERR_ACCESS_DENIED;
9115 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9116 if (!W_ERROR_IS_OK(status))
9119 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9120 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9122 status = delete_printer_dataex( printer, keyname, valuename );
9124 if ( W_ERROR_IS_OK(status) )
9125 mod_a_printer( printer, 2 );
9127 free_a_printer(&printer, 2);
9132 /********************************************************************
9133 * spoolss_enumprinterkey
9134 ********************************************************************/
9137 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9140 fstring *keynames = NULL;
9141 uint16 *enumkeys = NULL;
9144 POLICY_HND *handle = &q_u->handle;
9145 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9146 NT_PRINTER_DATA *data;
9147 NT_PRINTER_INFO_LEVEL *printer = NULL;
9149 WERROR status = WERR_BADFILE;
9152 DEBUG(4,("_spoolss_enumprinterkey\n"));
9155 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9159 if ( !get_printer_snum(p,handle, &snum) )
9162 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9163 if (!W_ERROR_IS_OK(status))
9166 /* get the list of subkey names */
9168 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9169 data = &printer->info_2->data;
9171 num_keys = get_printer_subkeys( data, key, &keynames );
9173 if ( num_keys == -1 ) {
9174 status = WERR_BADFILE;
9178 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9180 r_u->needed = printerkey_len*2;
9182 if ( q_u->size < r_u->needed ) {
9183 status = WERR_MORE_DATA;
9187 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9188 status = WERR_NOMEM;
9194 if ( q_u->size < r_u->needed )
9195 status = WERR_MORE_DATA;
9198 free_a_printer( &printer, 2 );
9199 SAFE_FREE( keynames );
9204 /********************************************************************
9205 * spoolss_deleteprinterkey
9206 ********************************************************************/
9208 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9210 POLICY_HND *handle = &q_u->handle;
9211 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9213 NT_PRINTER_INFO_LEVEL *printer = NULL;
9217 DEBUG(5,("spoolss_deleteprinterkey\n"));
9220 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9224 /* if keyname == NULL, return error */
9226 if ( !q_u->keyname.buffer )
9227 return WERR_INVALID_PARAM;
9229 if (!get_printer_snum(p, handle, &snum))
9232 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9233 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9234 return WERR_ACCESS_DENIED;
9237 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9238 if (!W_ERROR_IS_OK(status))
9241 /* delete the key and all subneys */
9243 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9245 status = delete_all_printer_data( printer->info_2, key );
9247 if ( W_ERROR_IS_OK(status) )
9248 status = mod_a_printer(printer, 2);
9250 free_a_printer( &printer, 2 );
9256 /********************************************************************
9257 * spoolss_enumprinterdataex
9258 ********************************************************************/
9260 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9262 POLICY_HND *handle = &q_u->handle;
9263 uint32 in_size = q_u->size;
9266 NT_PRINTER_INFO_LEVEL *printer = NULL;
9267 PRINTER_ENUM_VALUES *enum_values = NULL;
9268 NT_PRINTER_DATA *p_data;
9270 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9275 REGISTRY_VALUE *val;
9280 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9283 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9288 * first check for a keyname of NULL or "". Win2k seems to send
9289 * this a lot and we should send back WERR_INVALID_PARAM
9290 * no need to spend time looking up the printer in this case.
9294 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9295 if ( !strlen(key) ) {
9296 result = WERR_INVALID_PARAM;
9300 /* get the printer off of disk */
9302 if (!get_printer_snum(p,handle, &snum))
9305 ZERO_STRUCT(printer);
9306 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9307 if (!W_ERROR_IS_OK(result))
9310 /* now look for a match on the key name */
9312 p_data = &printer->info_2->data;
9314 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9315 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9317 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9318 result = WERR_INVALID_PARAM;
9325 /* allocate the memory for the array of pointers -- if necessary */
9327 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9330 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9332 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9333 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9334 result = WERR_NOMEM;
9338 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9342 * loop through all params and build the array to pass
9343 * back to the client
9346 for ( i=0; i<num_entries; i++ )
9348 /* lookup the registry value */
9350 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9351 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9355 value_name = regval_name( val );
9356 init_unistr( &enum_values[i].valuename, value_name );
9357 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9358 enum_values[i].type = regval_type( val );
9360 data_len = regval_size( val );
9362 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9364 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9366 result = WERR_NOMEM;
9370 enum_values[i].data_len = data_len;
9372 /* keep track of the size of the array in bytes */
9374 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9377 /* housekeeping information in the reply */
9379 r_u->needed = needed;
9380 r_u->returned = num_entries;
9382 if (needed > in_size) {
9383 result = WERR_MORE_DATA;
9387 /* copy data into the reply */
9389 r_u->ctr.size = r_u->needed;
9390 r_u->ctr.size_of_array = r_u->returned;
9391 r_u->ctr.values = enum_values;
9397 free_a_printer(&printer, 2);
9402 /****************************************************************************
9403 ****************************************************************************/
9405 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9407 init_unistr(&info->name, name);
9410 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9411 UNISTR2 *environment,
9418 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9419 WERROR result = WERR_OK;
9421 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9423 if (!get_short_archi(long_archi))
9424 return WERR_INVALID_ENVIRONMENT;
9426 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9429 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9431 fill_printprocessordirectory_1(info, path);
9433 *needed += spoolss_size_printprocessordirectory_info_1(info);
9435 if (*needed > offered) {
9436 result = WERR_INSUFFICIENT_BUFFER;
9440 if (!rpcbuf_alloc_size(buffer, *needed)) {
9441 result = WERR_INSUFFICIENT_BUFFER;
9445 smb_io_printprocessordirectory_1("", buffer, info, 0);
9453 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9455 uint32 level = q_u->level;
9456 RPC_BUFFER *buffer = NULL;
9457 uint32 offered = q_u->offered;
9458 uint32 *needed = &r_u->needed;
9461 /* that's an [in out] buffer */
9463 if ( q_u->buffer ) {
9464 rpcbuf_move(q_u->buffer, &r_u->buffer);
9465 buffer = r_u->buffer;
9468 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9474 result = getprintprocessordirectory_level_1
9475 (&q_u->name, &q_u->environment, buffer, offered, needed);
9478 result = WERR_UNKNOWN_LEVEL;
9486 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9487 SPOOL_R_REPLYOPENPRINTER *r_u)
9489 DEBUG(5,("_spoolss_replyopenprinter\n"));
9491 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9496 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9497 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9499 DEBUG(5,("_spoolss_replycloseprinter\n"));