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-2002,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
40 #define PRINTER_HANDLE_IS_PRINTER 0
41 #define PRINTER_HANDLE_IS_PRINTSERVER 1
43 /* Table to map the driver version */
45 static const char * drv_ver_to_os[] = {
46 "WIN9X", /* driver version/cversion 0 */
48 "WINNT", /* driver version/cversion 2 */
49 "WIN2K", /* driver version/cversion 3 */
53 const char *long_archi;
54 const char *short_archi;
59 /* structure to store the printer handles */
60 /* and a reference to what it's pointing to */
61 /* and the notify info asked about */
62 /* that's the central struct */
63 typedef struct _Printer{
64 struct _Printer *prev, *next;
65 BOOL document_started;
67 uint32 jobid; /* jobid in printing backend */
71 fstring printerservername;
74 uint32 access_granted;
80 SPOOL_NOTIFY_OPTION *option;
81 POLICY_HND client_hnd;
82 BOOL client_connected;
84 /* are we in a FindNextPrinterChangeNotify() call? */
92 /* devmode sent in the OpenPrinter() call */
93 NT_DEVICEMODE *nt_devmode;
98 static Printer_entry *printers_list;
100 typedef struct _counter_printer_0 {
108 static ubi_dlList counter_list;
110 static struct cli_state notify_cli; /* print notify back-channel */
111 static uint32 smb_connections=0;
114 /* in printing/nt_printing.c */
116 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
118 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
119 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
121 /* translate between internal status numbers and NT status numbers */
122 static int nt_printj_status(int v)
128 return JOB_STATUS_PAUSED;
130 return JOB_STATUS_SPOOLING;
132 return JOB_STATUS_PRINTING;
134 return JOB_STATUS_ERROR;
136 return JOB_STATUS_DELETING;
138 return JOB_STATUS_OFFLINE;
140 return JOB_STATUS_PAPEROUT;
142 return JOB_STATUS_PRINTED;
144 return JOB_STATUS_DELETED;
146 return JOB_STATUS_BLOCKED;
147 case LPQ_USER_INTERVENTION:
148 return JOB_STATUS_USER_INTERVENTION;
153 static int nt_printq_status(int v)
157 return PRINTER_STATUS_PAUSED;
166 /****************************************************************************
167 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
168 ****************************************************************************/
170 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
175 SAFE_FREE((*pp)->ctr.type);
179 /***************************************************************************
180 Disconnect from the client
181 ****************************************************************************/
183 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
188 * Tell the specific printing tdb we no longer want messages for this printer
189 * by deregistering our PID.
192 if (!print_notify_deregister_pid(snum))
193 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
195 /* weird if the test succeds !!! */
196 if (smb_connections==0) {
197 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
201 result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle);
203 if (!W_ERROR_IS_OK(result))
204 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
205 dos_errstr(result)));
207 /* if it's the last connection, deconnect the IPC$ share */
208 if (smb_connections==1) {
209 cli_nt_session_close(¬ify_cli);
210 cli_ulogoff(¬ify_cli);
211 cli_shutdown(¬ify_cli);
212 message_deregister(MSG_PRINTER_NOTIFY2);
214 /* Tell the connections db we're no longer interested in
215 * printer notify messages. */
217 register_message_flags( False, FLAG_MSG_PRINTING );
223 /****************************************************************************
224 Functions to free a printer entry datastruct.
225 ****************************************************************************/
227 static void free_printer_entry(void *ptr)
229 Printer_entry *Printer = (Printer_entry *)ptr;
231 if (Printer->notify.client_connected==True) {
234 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
236 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
237 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
238 snum = print_queue_snum(Printer->dev.handlename);
240 srv_spoolss_replycloseprinter(snum,
241 &Printer->notify.client_hnd);
245 Printer->notify.flags=0;
246 Printer->notify.options=0;
247 Printer->notify.localmachine[0]='\0';
248 Printer->notify.printerlocal=0;
249 free_spool_notify_option(&Printer->notify.option);
250 Printer->notify.option=NULL;
251 Printer->notify.client_connected=False;
253 free_nt_devicemode( &Printer->nt_devmode );
255 /* Remove from the internal list. */
256 DLIST_REMOVE(printers_list, Printer);
261 /****************************************************************************
262 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
263 ****************************************************************************/
265 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
267 SPOOL_NOTIFY_OPTION *new_sp = NULL;
272 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
279 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
281 if (!new_sp->ctr.type) {
290 /****************************************************************************
291 find printer index by handle
292 ****************************************************************************/
294 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
296 Printer_entry *find_printer = NULL;
298 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
299 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
306 /****************************************************************************
307 Close printer index by handle.
308 ****************************************************************************/
310 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
312 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
315 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
319 close_policy_hnd(p, hnd);
324 /****************************************************************************
325 Delete a printer given a handle.
326 ****************************************************************************/
328 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
330 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
333 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
338 * It turns out that Windows allows delete printer on a handle
339 * opened by an admin user, then used on a pipe handle created
340 * by an anonymous user..... but they're working on security.... riiight !
344 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
345 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
346 return WERR_ACCESS_DENIED;
350 /* Check calling user has permission to delete printer. Note that
351 since we set the snum parameter to -1 only administrators can
352 delete the printer. This stops people with the Full Control
353 permission from deleting the printer. */
355 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
356 DEBUG(3, ("printer delete denied by security descriptor\n"));
357 return WERR_ACCESS_DENIED;
361 if (del_a_printer(Printer->dev.handlename) != 0) {
362 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
366 if (*lp_deleteprinter_cmd()) {
368 char *cmd = lp_deleteprinter_cmd();
373 /* Printer->dev.handlename equals portname equals sharename */
374 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
375 Printer->dev.handlename);
377 DEBUG(10,("Running [%s]\n", command));
378 ret = smbrun(command, NULL);
380 return WERR_BADFID; /* What to return here? */
382 DEBUGADD(10,("returned [%d]\n", ret));
384 /* Send SIGHUP to process group... is there a better way? */
387 /* go ahead and re-read the services immediately */
388 reload_services( False );
390 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
391 return WERR_ACCESS_DENIED;
397 /****************************************************************************
398 Return the snum of a printer corresponding to an handle.
399 ****************************************************************************/
401 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
403 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
406 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
410 switch (Printer->printer_type) {
411 case PRINTER_HANDLE_IS_PRINTER:
412 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
413 *number = print_queue_snum(Printer->dev.handlename);
414 return (*number != -1);
415 case PRINTER_HANDLE_IS_PRINTSERVER:
422 /****************************************************************************
423 Set printer handle type.
424 Check if it's \\server or \\server\printer
425 ****************************************************************************/
427 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
429 DEBUG(3,("Setting printer type=%s\n", handlename));
431 if ( strlen(handlename) < 3 ) {
432 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
436 /* it's a print server */
437 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
438 DEBUGADD(4,("Printer is a print server\n"));
439 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
443 DEBUGADD(4,("Printer is a printer\n"));
444 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
450 /****************************************************************************
451 Set printer handle name.
452 ****************************************************************************/
454 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
457 int n_services=lp_numservices();
462 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
464 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
465 ZERO_STRUCT(Printer->dev.printerservername);
466 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
470 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
473 if (*handlename=='\\') {
474 aprinter=strchr_m(handlename+2, '\\');
481 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
484 * The original code allowed smbd to store a printer name that
485 * was different from the share name. This is not possible
486 * anymore, so I've simplified this loop greatly. Here
487 * we are just verifying that the printer name is a valid
488 * printer service defined in smb.conf
489 * --jerry [Fri Feb 15 11:17:46 CST 2002]
492 for (snum=0; snum<n_services; snum++) {
494 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
497 fstrcpy(sname, lp_servicename(snum));
499 DEBUGADD(5,("share:%s\n",sname));
501 if (! StrCaseCmp(sname, aprinter)) {
510 DEBUGADD(4,("Printer not found\n"));
514 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
516 ZERO_STRUCT(Printer->dev.handlename);
517 fstrcpy(Printer->dev.handlename, sname);
522 /****************************************************************************
523 Find first available printer slot. creates a printer handle for you.
524 ****************************************************************************/
526 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
528 Printer_entry *new_printer;
530 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
532 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
535 ZERO_STRUCTP(new_printer);
537 new_printer->notify.option=NULL;
539 /* Add to the internal list. */
540 DLIST_ADD(printers_list, new_printer);
542 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
543 SAFE_FREE(new_printer);
547 if (!set_printer_hnd_printertype(new_printer, name)) {
548 close_printer_handle(p, hnd);
552 if (!set_printer_hnd_name(new_printer, name)) {
553 close_printer_handle(p, hnd);
557 new_printer->access_granted = access_granted;
559 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
564 /****************************************************************************
565 Allocate more memory for a BUFFER.
566 ****************************************************************************/
568 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
576 /* damn, I'm doing the reverse operation of prs_grow() :) */
577 if (buffer_size < prs_data_size(ps))
580 extra_space = buffer_size - prs_data_size(ps);
583 * save the offset and move to the end of the buffer
584 * prs_grow() checks the extra_space against the offset
586 old_offset=prs_offset(ps);
587 prs_set_offset(ps, prs_data_size(ps));
589 if (!prs_grow(ps, extra_space))
592 prs_set_offset(ps, old_offset);
594 buffer->string_at_end=prs_data_size(ps);
599 /***************************************************************************
600 check to see if the client motify handle is monitoring the notification
601 given by (notify_type, notify_field).
602 **************************************************************************/
604 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
610 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
613 SPOOL_NOTIFY_OPTION *option = p->notify.option;
617 * Flags should always be zero when the change notify
618 * is registered by the cliebnt's spooler. A user Win32 app
619 * might use the flags though instead of the NOTIFY_OPTION_INFO
624 return is_monitoring_event_flags(
625 p->notify.flags, notify_type, notify_field);
627 for (i = 0; i < option->count; i++) {
629 /* Check match for notify_type */
631 if (option->ctr.type[i].type != notify_type)
634 /* Check match for field */
636 for (j = 0; j < option->ctr.type[i].count; j++) {
637 if (option->ctr.type[i].fields[j] == notify_field) {
643 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
644 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
645 p->dev.handlename : p->dev.printerservername,
646 notify_type, notify_field));
651 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
653 static void notify_one_value(struct spoolss_notify_msg *msg,
654 SPOOL_NOTIFY_INFO_DATA *data,
657 data->notify_data.value[0] = msg->notify.value[0];
658 data->notify_data.value[1] = 0;
661 static void notify_string(struct spoolss_notify_msg *msg,
662 SPOOL_NOTIFY_INFO_DATA *data,
667 /* The length of the message includes the trailing \0 */
669 init_unistr2(&unistr, msg->notify.data, msg->len);
671 data->notify_data.data.length = msg->len * 2;
672 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
674 if (!data->notify_data.data.string) {
675 data->notify_data.data.length = 0;
679 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
682 static void notify_system_time(struct spoolss_notify_msg *msg,
683 SPOOL_NOTIFY_INFO_DATA *data,
689 if (msg->len != sizeof(time_t)) {
690 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
695 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
696 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
700 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
701 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
705 if (!spoolss_io_system_time("", &ps, 0, &systime))
708 data->notify_data.data.length = prs_offset(&ps);
709 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
711 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
716 struct notify2_message_table {
718 void (*fn)(struct spoolss_notify_msg *msg,
719 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
722 static struct notify2_message_table printer_notify_table[] = {
723 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
724 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
725 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
726 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
727 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
728 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
729 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
730 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
731 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
732 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
733 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
734 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
735 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
736 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
737 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
738 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
739 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
740 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
741 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
744 static struct notify2_message_table job_notify_table[] = {
745 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
746 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
747 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
748 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
749 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
750 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
751 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
752 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
753 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
754 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
755 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
756 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
757 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
758 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
759 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
760 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
761 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
762 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
763 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
764 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
765 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
766 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
767 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
768 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
772 /***********************************************************************
773 Allocate talloc context for container object
774 **********************************************************************/
776 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
781 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
786 /***********************************************************************
787 release all allocated memory and zero out structure
788 **********************************************************************/
790 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
796 talloc_destroy(ctr->ctx);
803 /***********************************************************************
804 **********************************************************************/
806 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
814 /***********************************************************************
815 **********************************************************************/
817 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
819 if ( !ctr || !ctr->msg_groups )
822 if ( idx >= ctr->num_groups )
825 return &ctr->msg_groups[idx];
829 /***********************************************************************
830 How many groups of change messages do we have ?
831 **********************************************************************/
833 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
838 return ctr->num_groups;
841 /***********************************************************************
842 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
843 **********************************************************************/
845 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
847 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
848 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
849 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
855 /* loop over all groups looking for a matching printer name */
857 for ( i=0; i<ctr->num_groups; i++ ) {
858 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
862 /* add a new group? */
864 if ( i == ctr->num_groups )
868 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
869 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
872 ctr->msg_groups = groups;
874 /* clear the new entry and set the printer name */
876 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
877 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
880 /* add the change messages; 'i' is the correct index now regardless */
882 msg_grp = &ctr->msg_groups[i];
886 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
887 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
890 msg_grp->msgs = msg_list;
892 new_slot = msg_grp->num_msgs-1;
893 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
895 /* need to allocate own copy of data */
898 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
900 return ctr->num_groups;
903 /***********************************************************************
904 Send a change notication message on all handles which have a call
906 **********************************************************************/
908 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
911 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
912 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
913 SPOOLSS_NOTIFY_MSG *messages;
917 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
921 messages = msg_group->msgs;
924 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
928 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
930 /* loop over all printers */
932 for (p = printers_list; p; p = p->next)
934 SPOOL_NOTIFY_INFO_DATA *data;
939 /* Is there notification on this handle? */
941 if ( !p->notify.client_connected )
944 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
946 /* For this printer? Print servers always receive
949 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
950 ( !strequal(msg_group->printername, p->dev.handlename) ) )
953 DEBUG(10,("Our printer\n"));
955 /* allocate the max entries possible */
957 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
962 /* build the array of change notifications */
964 for ( i=0; i<msg_group->num_msgs; i++ )
966 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
968 /* Are we monitoring this event? */
970 if (!is_monitoring_event(p, msg->type, msg->field))
974 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
975 msg->type, msg->field, p->dev.handlename));
978 * if the is a printer notification handle and not a job notification
979 * type, then set the id to 0. Other wise just use what was specified
982 * When registering change notification on a print server handle
983 * we always need to send back the id (snum) matching the printer
984 * for which the change took place. For change notify registered
985 * on a printer handle, this does not matter and the id should be 0.
990 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
996 /* Convert unix jobid to smb jobid */
998 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID)
1000 id = sysjob_to_jobid(msg->id);
1003 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1008 construct_info_data( &data[data_len], msg->type, msg->field, id );
1011 case PRINTER_NOTIFY_TYPE:
1012 if ( printer_notify_table[msg->field].fn )
1013 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1016 case JOB_NOTIFY_TYPE:
1017 if ( job_notify_table[msg->field].fn )
1018 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1022 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1029 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1030 data_len, data, p->notify.change, 0 );
1034 DEBUG(8,("send_notify2_changes: Exit...\n"));
1038 /***********************************************************************
1039 **********************************************************************/
1041 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
1046 /* Unpack message */
1048 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1051 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
1052 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1055 tdb_unpack((char *)buf + offset, len - offset, "dd",
1056 &msg->notify.value[0], &msg->notify.value[1]);
1058 tdb_unpack((char *)buf + offset, len - offset, "B",
1059 &msg->len, &msg->notify.data);
1061 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1062 msg->type, msg->field, msg->flags));
1065 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1066 msg->notify.value[1]));
1068 dump_data(3, msg->notify.data, msg->len);
1073 /********************************************************************
1074 Receive a notify2 message list
1075 ********************************************************************/
1077 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1079 size_t msg_count, i;
1080 char *buf = (char *)msg;
1083 SPOOLSS_NOTIFY_MSG notify;
1084 SPOOLSS_NOTIFY_MSG_CTR messages;
1088 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1092 msg_count = IVAL(buf, 0);
1095 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1097 if (msg_count == 0) {
1098 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1102 /* initialize the container */
1104 ZERO_STRUCT( messages );
1105 notify_msg_ctr_init( &messages );
1108 * build message groups for each printer identified
1109 * in a change_notify msg. Remember that a PCN message
1110 * includes the handle returned for the srv_spoolss_replyopenprinter()
1111 * call. Therefore messages are grouped according to printer handle.
1114 for ( i=0; i<msg_count; i++ )
1116 if (msg_ptr + 4 - buf > len) {
1117 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1121 msg_len = IVAL(msg_ptr,0);
1124 if (msg_ptr + msg_len - buf > len) {
1125 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1129 /* unpack messages */
1131 ZERO_STRUCT( notify );
1132 notify2_unpack_msg( ¬ify, msg_ptr, msg_len );
1135 /* add to correct list in container */
1137 notify_msg_ctr_addmsg( &messages, ¬ify );
1139 /* free memory that might have been allocated by notify2_unpack_msg() */
1141 if ( notify.len != 0 )
1142 SAFE_FREE( notify.notify.data );
1145 /* process each group of messages */
1147 num_groups = notify_msg_ctr_numgroups( &messages );
1148 for ( i=0; i<num_groups; i++ )
1149 send_notify2_changes( &messages, i );
1154 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1156 notify_msg_ctr_destroy( &messages );
1161 /********************************************************************
1162 Send a message to ourself about new driver being installed
1163 so we can upgrade the information for each printer bound to this
1165 ********************************************************************/
1167 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1169 int len = strlen(drivername);
1174 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1177 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1182 /**********************************************************************
1183 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1184 over all printers, upgrading ones as neessary
1185 **********************************************************************/
1187 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1191 int n_services = lp_numservices();
1193 len = MIN(len,sizeof(drivername)-1);
1194 strncpy(drivername, buf, len);
1196 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1198 /* Iterate the printer list */
1200 for (snum=0; snum<n_services; snum++)
1202 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1205 NT_PRINTER_INFO_LEVEL *printer = NULL;
1207 result = get_a_printer(&printer, 2, lp_servicename(snum));
1208 if (!W_ERROR_IS_OK(result))
1211 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1213 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1215 /* all we care about currently is the change_id */
1217 result = mod_a_printer(*printer, 2);
1218 if (!W_ERROR_IS_OK(result)) {
1219 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1220 dos_errstr(result)));
1224 free_a_printer(&printer, 2);
1231 /********************************************************************
1232 Update the cahce for all printq's with a registered client
1234 ********************************************************************/
1236 void update_monitored_printq_cache( void )
1238 Printer_entry *printer = printers_list;
1241 /* loop through all printers and update the cache where
1242 client_connected == True */
1245 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1246 && printer->notify.client_connected )
1248 snum = print_queue_snum(printer->dev.handlename);
1249 print_queue_status( snum, NULL, NULL );
1252 printer = printer->next;
1257 /********************************************************************
1258 Send a message to ourself about new driver being installed
1259 so we can upgrade the information for each printer bound to this
1261 ********************************************************************/
1263 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1265 int len = strlen(drivername);
1270 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1273 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1278 /**********************************************************************
1279 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1280 over all printers, resetting printer data as neessary
1281 **********************************************************************/
1283 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1287 int n_services = lp_numservices();
1289 len = MIN( len, sizeof(drivername)-1 );
1290 strncpy( drivername, buf, len );
1292 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1294 /* Iterate the printer list */
1296 for ( snum=0; snum<n_services; snum++ )
1298 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1301 NT_PRINTER_INFO_LEVEL *printer = NULL;
1303 result = get_a_printer( &printer, 2, lp_servicename(snum) );
1304 if ( !W_ERROR_IS_OK(result) )
1308 * if the printer is bound to the driver,
1309 * then reset to the new driver initdata
1312 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1314 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1316 if ( !set_driver_init(printer, 2) ) {
1317 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1318 printer->info_2->printername, printer->info_2->drivername));
1321 result = mod_a_printer( *printer, 2 );
1322 if ( !W_ERROR_IS_OK(result) ) {
1323 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1324 get_dos_error_msg(result)));
1328 free_a_printer( &printer, 2 );
1337 /********************************************************************
1338 Copy routines used by convert_to_openprinterex()
1339 *******************************************************************/
1341 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1349 DEBUG (8,("dup_devmode\n"));
1351 /* bulk copy first */
1353 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1357 /* dup the pointer members separately */
1359 len = unistrlen(devmode->devicename.buffer);
1361 d->devicename.buffer = talloc(ctx, len*2);
1362 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1367 len = unistrlen(devmode->formname.buffer);
1369 d->devicename.buffer = talloc(ctx, len*2);
1370 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1374 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1379 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1381 if (!new_ctr || !ctr)
1384 DEBUG(8,("copy_devmode_ctr\n"));
1386 new_ctr->size = ctr->size;
1387 new_ctr->devmode_ptr = ctr->devmode_ptr;
1389 if(ctr->devmode_ptr)
1390 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1393 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1395 if (!new_def || !def)
1398 DEBUG(8,("copy_printer_defaults\n"));
1400 new_def->datatype_ptr = def->datatype_ptr;
1402 if (def->datatype_ptr)
1403 copy_unistr2(&new_def->datatype, &def->datatype);
1405 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1407 new_def->access_required = def->access_required;
1410 /********************************************************************
1411 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1412 * SPOOL_Q_OPEN_PRINTER_EX structure
1413 ********************************************************************/
1415 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1417 if (!q_u_ex || !q_u)
1420 DEBUG(8,("convert_to_openprinterex\n"));
1422 q_u_ex->printername_ptr = q_u->printername_ptr;
1424 if (q_u->printername_ptr)
1425 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1427 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1430 /********************************************************************
1431 * spoolss_open_printer
1433 * called from the spoolss dispatcher
1434 ********************************************************************/
1436 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1438 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1439 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1444 ZERO_STRUCT(q_u_ex);
1445 ZERO_STRUCT(r_u_ex);
1447 /* convert the OpenPrinter() call to OpenPrinterEx() */
1449 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1451 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1453 /* convert back to OpenPrinter() */
1455 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1460 /********************************************************************
1461 * spoolss_open_printer
1463 * If the openprinterex rpc call contains a devmode,
1464 * it's a per-user one. This per-user devmode is derivated
1465 * from the global devmode. Openprinterex() contains a per-user
1466 * devmode for when you do EMF printing and spooling.
1467 * In the EMF case, the NT workstation is only doing half the job
1468 * of rendering the page. The other half is done by running the printer
1469 * driver on the server.
1470 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1471 * The EMF file only contains what is to be printed on the page.
1472 * So in order for the server to know how to print, the NT client sends
1473 * a devicemode attached to the openprinterex call.
1474 * But this devicemode is short lived, it's only valid for the current print job.
1476 * If Samba would have supported EMF spooling, this devicemode would
1477 * have been attached to the handle, to sent it to the driver to correctly
1478 * rasterize the EMF file.
1480 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1481 * we just act as a pass-thru between windows and the printer.
1483 * In order to know that Samba supports only RAW spooling, NT has to call
1484 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1485 * and until NT sends a RAW job, we refuse it.
1487 * But to call getprinter() or startdoc(), you first need a valid handle,
1488 * and to get an handle you have to call openprintex(). Hence why you have
1489 * a devicemode in the openprinterex() call.
1492 * Differences between NT4 and NT 2000.
1495 * On NT4, you only have a global devicemode. This global devicemode can be changed
1496 * by the administrator (or by a user with enough privs). Everytime a user
1497 * wants to print, the devicemode is resetted to the default. In Word, everytime
1498 * you print, the printer's characteristics are always reset to the global devicemode.
1502 * In W2K, there is the notion of per-user devicemode. The first time you use
1503 * a printer, a per-user devicemode is build from the global devicemode.
1504 * If you change your per-user devicemode, it is saved in the registry, under the
1505 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1506 * printer preferences available.
1508 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1509 * on the General Tab of the printer properties windows.
1511 * To change the global devicemode: it's the "Printing Defaults..." button
1512 * on the Advanced Tab of the printer properties window.
1515 ********************************************************************/
1517 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1519 UNISTR2 *printername = NULL;
1520 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1521 POLICY_HND *handle = &r_u->handle;
1525 struct current_user user;
1526 Printer_entry *Printer=NULL;
1528 if (q_u->printername_ptr != 0)
1529 printername = &q_u->printername;
1531 if (printername == NULL)
1532 return WERR_INVALID_PRINTER_NAME;
1534 /* some sanity check because you can open a printer or a print server */
1535 /* aka: \\server\printer or \\server */
1536 unistr2_to_ascii(name, printername, sizeof(name)-1);
1538 DEBUGADD(3,("checking name: %s\n",name));
1540 if (!open_printer_hnd(p, handle, name, 0))
1541 return WERR_INVALID_PRINTER_NAME;
1543 Printer=find_printer_index_by_hnd(p, handle);
1545 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1546 Can't find printer handle we created for printer %s\n", name ));
1547 close_printer_handle(p,handle);
1548 return WERR_INVALID_PRINTER_NAME;
1551 get_current_user(&user, p);
1554 * First case: the user is opening the print server:
1556 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1557 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1559 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1560 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1561 * or if the user is listed in the smb.conf printer admin parameter.
1563 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1564 * client view printer folder, but does not show the MSAPW.
1566 * Note: this test needs code to check access rights here too. Jeremy
1567 * could you look at this?
1569 * Second case: the user is opening a printer:
1570 * NT doesn't let us connect to a printer if the connecting user
1571 * doesn't have print permission.
1574 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1576 /* Printserver handles use global struct... */
1580 /* Map standard access rights to object specific access rights */
1582 se_map_standard(&printer_default->access_required,
1583 &printserver_std_mapping);
1585 /* Deny any object specific bits that don't apply to print
1586 servers (i.e printer and job specific bits) */
1588 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1590 if (printer_default->access_required &
1591 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1592 DEBUG(3, ("access DENIED for non-printserver bits"));
1593 close_printer_handle(p, handle);
1594 return WERR_ACCESS_DENIED;
1597 /* Allow admin access */
1599 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1601 if (!lp_ms_add_printer_wizard()) {
1602 close_printer_handle(p, handle);
1603 return WERR_ACCESS_DENIED;
1606 /* if the user is not root and not a printer admin, then fail */
1609 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
1611 close_printer_handle(p, handle);
1612 return WERR_ACCESS_DENIED;
1615 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1619 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1622 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1623 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1625 /* We fall through to return WERR_OK */
1630 /* NT doesn't let us connect to a printer if the connecting user
1631 doesn't have print permission. */
1633 if (!get_printer_snum(p, handle, &snum))
1636 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1638 /* map an empty access mask to the minimum access mask */
1639 if (printer_default->access_required == 0x0)
1640 printer_default->access_required = PRINTER_ACCESS_USE;
1643 * If we are not serving the printer driver for this printer,
1644 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1645 * will keep NT clients happy --jerry
1648 if (lp_use_client_driver(snum)
1649 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1651 printer_default->access_required = PRINTER_ACCESS_USE;
1654 /* check smb.conf parameters and the the sec_desc */
1656 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1657 DEBUG(3, ("access DENIED for printer open\n"));
1658 close_printer_handle(p, handle);
1659 return WERR_ACCESS_DENIED;
1662 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1663 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1664 close_printer_handle(p, handle);
1665 return WERR_ACCESS_DENIED;
1668 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1669 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1671 printer_default->access_required = PRINTER_ACCESS_USE;
1673 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1674 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1678 Printer->access_granted = printer_default->access_required;
1681 * If the client sent a devmode in the OpenPrinter() call, then
1682 * save it here in case we get a job submission on this handle
1685 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1686 && q_u->printer_default.devmode_cont.devmode_ptr )
1688 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1689 &Printer->nt_devmode );
1695 /****************************************************************************
1696 ****************************************************************************/
1698 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1699 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1705 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1714 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1715 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1721 printer->info_3=NULL;
1722 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1726 printer->info_6=NULL;
1727 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1737 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1738 NT_DEVICEMODE **pp_nt_devmode)
1740 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1743 * Ensure nt_devmode is a valid pointer
1744 * as we will be overwriting it.
1747 if (nt_devmode == NULL) {
1748 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1749 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1753 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1754 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1756 nt_devmode->specversion=devmode->specversion;
1757 nt_devmode->driverversion=devmode->driverversion;
1758 nt_devmode->size=devmode->size;
1759 nt_devmode->fields=devmode->fields;
1760 nt_devmode->orientation=devmode->orientation;
1761 nt_devmode->papersize=devmode->papersize;
1762 nt_devmode->paperlength=devmode->paperlength;
1763 nt_devmode->paperwidth=devmode->paperwidth;
1764 nt_devmode->scale=devmode->scale;
1765 nt_devmode->copies=devmode->copies;
1766 nt_devmode->defaultsource=devmode->defaultsource;
1767 nt_devmode->printquality=devmode->printquality;
1768 nt_devmode->color=devmode->color;
1769 nt_devmode->duplex=devmode->duplex;
1770 nt_devmode->yresolution=devmode->yresolution;
1771 nt_devmode->ttoption=devmode->ttoption;
1772 nt_devmode->collate=devmode->collate;
1774 nt_devmode->logpixels=devmode->logpixels;
1775 nt_devmode->bitsperpel=devmode->bitsperpel;
1776 nt_devmode->pelswidth=devmode->pelswidth;
1777 nt_devmode->pelsheight=devmode->pelsheight;
1778 nt_devmode->displayflags=devmode->displayflags;
1779 nt_devmode->displayfrequency=devmode->displayfrequency;
1780 nt_devmode->icmmethod=devmode->icmmethod;
1781 nt_devmode->icmintent=devmode->icmintent;
1782 nt_devmode->mediatype=devmode->mediatype;
1783 nt_devmode->dithertype=devmode->dithertype;
1784 nt_devmode->reserved1=devmode->reserved1;
1785 nt_devmode->reserved2=devmode->reserved2;
1786 nt_devmode->panningwidth=devmode->panningwidth;
1787 nt_devmode->panningheight=devmode->panningheight;
1790 * Only change private and driverextra if the incoming devmode
1791 * has a new one. JRA.
1794 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1795 SAFE_FREE(nt_devmode->private);
1796 nt_devmode->driverextra=devmode->driverextra;
1797 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1799 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1802 *pp_nt_devmode = nt_devmode;
1807 /********************************************************************
1808 * _spoolss_enddocprinter_internal.
1809 ********************************************************************/
1811 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1813 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1817 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1821 if (!get_printer_snum(p, handle, &snum))
1824 Printer->document_started=False;
1825 print_job_end(snum, Printer->jobid,True);
1826 /* error codes unhandled so far ... */
1831 /********************************************************************
1832 * api_spoolss_closeprinter
1833 ********************************************************************/
1835 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1837 POLICY_HND *handle = &q_u->handle;
1839 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1841 if (Printer && Printer->document_started)
1842 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1844 if (!close_printer_handle(p, handle))
1847 /* clear the returned printer handle. Observed behavior
1848 from Win2k server. Don't think this really matters.
1849 Previous code just copied the value of the closed
1852 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1857 /********************************************************************
1858 * api_spoolss_deleteprinter
1860 ********************************************************************/
1862 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1864 POLICY_HND *handle = &q_u->handle;
1865 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1868 if (Printer && Printer->document_started)
1869 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1871 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1873 result = delete_printer_handle(p, handle);
1875 update_c_setprinter(False);
1880 /*******************************************************************
1881 * static function to lookup the version id corresponding to an
1882 * long architecture string
1883 ******************************************************************/
1885 static int get_version_id (char * arch)
1888 struct table_node archi_table[]= {
1890 {"Windows 4.0", "WIN40", 0 },
1891 {"Windows NT x86", "W32X86", 2 },
1892 {"Windows NT R4000", "W32MIPS", 2 },
1893 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1894 {"Windows NT PowerPC", "W32PPC", 2 },
1898 for (i=0; archi_table[i].long_archi != NULL; i++)
1900 if (strcmp(arch, archi_table[i].long_archi) == 0)
1901 return (archi_table[i].version);
1907 /********************************************************************
1908 * _spoolss_deleteprinterdriver
1909 ********************************************************************/
1911 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1915 NT_PRINTER_DRIVER_INFO_LEVEL info;
1916 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1918 struct current_user user;
1920 WERROR status_win2k = WERR_ACCESS_DENIED;
1922 get_current_user(&user, p);
1924 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1925 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1927 /* check that we have a valid driver name first */
1929 if ((version=get_version_id(arch)) == -1)
1930 return WERR_INVALID_ENVIRONMENT;
1933 ZERO_STRUCT(info_win2k);
1935 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1937 /* try for Win2k driver if "Windows NT x86" */
1939 if ( version == 2 ) {
1941 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1942 status = WERR_UNKNOWN_PRINTER_DRIVER;
1946 /* otherwise it was a failure */
1948 status = WERR_UNKNOWN_PRINTER_DRIVER;
1954 if (printer_driver_in_use(info.info_3)) {
1955 status = WERR_PRINTER_DRIVER_IN_USE;
1961 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1963 /* if we get to here, we now have 2 driver info structures to remove */
1964 /* remove the Win2k driver first*/
1966 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1967 free_a_printer_driver( info_win2k, 3 );
1969 /* this should not have failed---if it did, report to client */
1970 if ( !W_ERROR_IS_OK(status_win2k) )
1975 status = delete_printer_driver(info.info_3, &user, version, False);
1977 /* if at least one of the deletes succeeded return OK */
1979 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1983 free_a_printer_driver( info, 3 );
1988 /********************************************************************
1989 * spoolss_deleteprinterdriverex
1990 ********************************************************************/
1992 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1996 NT_PRINTER_DRIVER_INFO_LEVEL info;
1997 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1999 uint32 flags = q_u->delete_flags;
2001 struct current_user user;
2003 WERROR status_win2k = WERR_ACCESS_DENIED;
2005 get_current_user(&user, p);
2007 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2008 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2010 /* check that we have a valid driver name first */
2011 if ((version=get_version_id(arch)) == -1) {
2012 /* this is what NT returns */
2013 return WERR_INVALID_ENVIRONMENT;
2016 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2017 version = q_u->version;
2020 ZERO_STRUCT(info_win2k);
2022 status = get_a_printer_driver(&info, 3, driver, arch, version);
2024 if ( !W_ERROR_IS_OK(status) )
2027 * if the client asked for a specific version,
2028 * or this is something other than Windows NT x86,
2032 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2035 /* try for Win2k driver if "Windows NT x86" */
2038 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2039 status = WERR_UNKNOWN_PRINTER_DRIVER;
2044 if ( printer_driver_in_use(info.info_3) ) {
2045 status = WERR_PRINTER_DRIVER_IN_USE;
2050 * we have a couple of cases to consider.
2051 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2052 * then the delete should fail if **any** files overlap with
2054 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2055 * non-overlapping files
2056 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2057 * is set, the do not delete any files
2058 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2061 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2063 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2065 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2066 /* no idea of the correct error here */
2067 status = WERR_ACCESS_DENIED;
2072 /* also check for W32X86/3 if necessary; maybe we already have? */
2074 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2075 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2078 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2079 /* no idea of the correct error here */
2080 free_a_printer_driver( info_win2k, 3 );
2081 status = WERR_ACCESS_DENIED;
2085 /* if we get to here, we now have 2 driver info structures to remove */
2086 /* remove the Win2k driver first*/
2088 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2089 free_a_printer_driver( info_win2k, 3 );
2091 /* this should not have failed---if it did, report to client */
2093 if ( !W_ERROR_IS_OK(status_win2k) )
2098 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2100 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2103 free_a_printer_driver( info, 3 );
2109 /****************************************************************************
2110 Internal routine for retreiving printerdata
2111 ***************************************************************************/
2113 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2114 const char *key, const char *value, uint32 *type, uint8 **data,
2115 uint32 *needed, uint32 in_size )
2117 REGISTRY_VALUE *val;
2120 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2121 return WERR_BADFILE;
2123 *type = regval_type( val );
2125 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2127 size = regval_size( val );
2129 /* copy the min(in_size, len) */
2132 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2134 /* special case for 0 length values */
2136 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2140 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2149 DEBUG(5,("get_printer_dataex: copy done\n"));
2154 /****************************************************************************
2155 Internal routine for removing printerdata
2156 ***************************************************************************/
2158 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2160 delete_printer_data( printer->info_2, key, value );
2162 return mod_a_printer(*printer, 2);
2165 /****************************************************************************
2166 Internal routine for storing printerdata
2167 ***************************************************************************/
2169 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2170 uint32 type, uint8 *data, int real_len )
2172 delete_printer_data( printer->info_2, key, value );
2174 add_printer_data( printer->info_2, key, value, type, data, real_len );
2176 return mod_a_printer(*printer, 2);
2179 /********************************************************************
2180 GetPrinterData on a printer server Handle.
2181 ********************************************************************/
2183 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2187 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2189 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2191 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2197 if (!StrCaseCmp(value, "BeepEnabled")) {
2199 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2201 SIVAL(*data, 0, 0x00);
2206 if (!StrCaseCmp(value, "EventLog")) {
2208 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2210 /* formally was 0x1b */
2211 SIVAL(*data, 0, 0x0);
2216 if (!StrCaseCmp(value, "NetPopup")) {
2218 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2220 SIVAL(*data, 0, 0x00);
2225 if (!StrCaseCmp(value, "MajorVersion")) {
2227 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2238 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2241 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2243 *needed = 2*(strlen(string)+1);
2244 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2246 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2248 /* it's done by hand ready to go on the wire */
2249 for (i=0; i<strlen(string); i++) {
2250 (*data)[2*i]=string[i];
2251 (*data)[2*i+1]='\0';
2256 if (!StrCaseCmp(value, "Architecture")) {
2257 pstring string="Windows NT x86";
2259 *needed = 2*(strlen(string)+1);
2260 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2262 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2263 for (i=0; i<strlen(string); i++) {
2264 (*data)[2*i]=string[i];
2265 (*data)[2*i+1]='\0';
2270 if (!StrCaseCmp(value, "DsPresent")) {
2272 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2274 SIVAL(*data, 0, 0x01);
2279 if (!StrCaseCmp(value, "DNSMachineName")) {
2282 if (!get_myfullname(hostname))
2283 return WERR_BADFILE;
2285 *needed = 2*(strlen(hostname)+1);
2286 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2288 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2289 for (i=0; i<strlen(hostname); i++) {
2290 (*data)[2*i]=hostname[i];
2291 (*data)[2*i+1]='\0';
2297 return WERR_BADFILE;
2300 /********************************************************************
2301 * spoolss_getprinterdata
2302 ********************************************************************/
2304 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2306 POLICY_HND *handle = &q_u->handle;
2307 UNISTR2 *valuename = &q_u->valuename;
2308 uint32 in_size = q_u->size;
2309 uint32 *type = &r_u->type;
2310 uint32 *out_size = &r_u->size;
2311 uint8 **data = &r_u->data;
2312 uint32 *needed = &r_u->needed;
2315 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2316 NT_PRINTER_INFO_LEVEL *printer = NULL;
2320 * Reminder: when it's a string, the length is in BYTES
2321 * even if UNICODE is negociated.
2326 *out_size = in_size;
2328 /* in case of problem, return some default values */
2333 DEBUG(4,("_spoolss_getprinterdata\n"));
2336 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2337 status = WERR_BADFID;
2341 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2343 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2344 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2347 if ( !get_printer_snum(p,handle, &snum) ) {
2348 status = WERR_BADFID;
2352 status = get_a_printer(&printer, 2, lp_servicename(snum));
2353 if ( !W_ERROR_IS_OK(status) )
2356 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2358 if ( strequal(value, "ChangeId") ) {
2360 *needed = sizeof(uint32);
2361 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2362 status = WERR_NOMEM;
2365 **data = printer->info_2->changeid;
2369 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2372 if (*needed > *out_size)
2373 status = WERR_MORE_DATA;
2376 if ( !W_ERROR_IS_OK(status) )
2378 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2380 /* reply this param doesn't exist */
2383 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2385 free_a_printer( &printer, 2 );
2394 /* cleanup & exit */
2397 free_a_printer( &printer, 2 );
2402 /*********************************************************
2403 Connect to the client machine.
2404 **********************************************************/
2406 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, const char *remote_machine)
2408 ZERO_STRUCTP(the_cli);
2409 if(cli_initialise(the_cli) == NULL) {
2410 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2414 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2415 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2416 cli_shutdown(the_cli);
2420 if (ismyip(the_cli->dest_ip)) {
2421 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2422 cli_shutdown(the_cli);
2426 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2427 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2428 cli_shutdown(the_cli);
2432 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2433 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2435 cli_shutdown(the_cli);
2439 the_cli->protocol = PROTOCOL_NT1;
2441 if (!cli_negprot(the_cli)) {
2442 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2443 cli_shutdown(the_cli);
2447 if (the_cli->protocol != PROTOCOL_NT1) {
2448 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2449 cli_shutdown(the_cli);
2454 * Do an anonymous session setup.
2457 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2458 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2459 cli_shutdown(the_cli);
2463 if (!(the_cli->sec_mode & 1)) {
2464 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2465 cli_shutdown(the_cli);
2469 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2470 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2471 cli_shutdown(the_cli);
2476 * Ok - we have an anonymous connection to the IPC$ share.
2477 * Now start the NT Domain stuff :-).
2480 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2481 DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2482 cli_nt_session_close(the_cli);
2483 cli_ulogoff(the_cli);
2484 cli_shutdown(the_cli);
2491 /***************************************************************************
2492 Connect to the client.
2493 ****************************************************************************/
2495 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2500 * If it's the first connection, contact the client
2501 * and connect to the IPC$ share anonumously
2503 if (smb_connections==0) {
2504 fstring unix_printer;
2506 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2508 if(!spoolss_connect_to_client(¬ify_cli, unix_printer))
2511 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2512 /* Tell the connections db we're now interested in printer
2513 * notify messages. */
2514 register_message_flags( True, FLAG_MSG_PRINTING );
2518 * Tell the specific printing tdb we want messages for this printer
2519 * by registering our PID.
2522 if (!print_notify_register_pid(snum))
2523 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2527 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2530 if (!W_ERROR_IS_OK(result))
2531 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2532 dos_errstr(result)));
2534 return (W_ERROR_IS_OK(result));
2537 /********************************************************************
2539 * ReplyFindFirstPrinterChangeNotifyEx
2541 * before replying OK: status=0 a rpc call is made to the workstation
2542 * asking ReplyOpenPrinter
2544 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2545 * called from api_spoolss_rffpcnex
2546 ********************************************************************/
2548 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2550 POLICY_HND *handle = &q_u->handle;
2551 uint32 flags = q_u->flags;
2552 uint32 options = q_u->options;
2553 UNISTR2 *localmachine = &q_u->localmachine;
2554 uint32 printerlocal = q_u->printerlocal;
2556 SPOOL_NOTIFY_OPTION *option = q_u->option;
2558 /* store the notify value in the printer struct */
2560 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2563 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2567 Printer->notify.flags=flags;
2568 Printer->notify.options=options;
2569 Printer->notify.printerlocal=printerlocal;
2571 if (Printer->notify.option)
2572 free_spool_notify_option(&Printer->notify.option);
2574 Printer->notify.option=dup_spool_notify_option(option);
2576 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2577 sizeof(Printer->notify.localmachine)-1);
2579 /* Connect to the client machine and send a ReplyOpenPrinter */
2581 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2583 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2584 !get_printer_snum(p, handle, &snum) )
2587 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2588 Printer->notify.printerlocal, 1,
2589 &Printer->notify.client_hnd))
2590 return WERR_SERVER_UNAVAILABLE;
2592 Printer->notify.client_connected=True;
2597 /*******************************************************************
2598 * fill a notify_info_data with the servername
2599 ********************************************************************/
2601 void spoolss_notify_server_name(int snum,
2602 SPOOL_NOTIFY_INFO_DATA *data,
2603 print_queue_struct *queue,
2604 NT_PRINTER_INFO_LEVEL *printer,
2605 TALLOC_CTX *mem_ctx)
2607 pstring temp_name, temp;
2610 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2612 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2614 data->notify_data.data.length = len;
2615 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2617 if (!data->notify_data.data.string) {
2618 data->notify_data.data.length = 0;
2622 memcpy(data->notify_data.data.string, temp, len);
2625 /*******************************************************************
2626 * fill a notify_info_data with the printername (not including the servername).
2627 ********************************************************************/
2629 void spoolss_notify_printer_name(int snum,
2630 SPOOL_NOTIFY_INFO_DATA *data,
2631 print_queue_struct *queue,
2632 NT_PRINTER_INFO_LEVEL *printer,
2633 TALLOC_CTX *mem_ctx)
2638 /* the notify name should not contain the \\server\ part */
2639 char *p = strrchr(printer->info_2->printername, '\\');
2642 p = printer->info_2->printername;
2647 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2649 data->notify_data.data.length = len;
2650 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2652 if (!data->notify_data.data.string) {
2653 data->notify_data.data.length = 0;
2657 memcpy(data->notify_data.data.string, temp, len);
2660 /*******************************************************************
2661 * fill a notify_info_data with the servicename
2662 ********************************************************************/
2664 void spoolss_notify_share_name(int snum,
2665 SPOOL_NOTIFY_INFO_DATA *data,
2666 print_queue_struct *queue,
2667 NT_PRINTER_INFO_LEVEL *printer,
2668 TALLOC_CTX *mem_ctx)
2673 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2675 data->notify_data.data.length = len;
2676 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2678 if (!data->notify_data.data.string) {
2679 data->notify_data.data.length = 0;
2683 memcpy(data->notify_data.data.string, temp, len);
2686 /*******************************************************************
2687 * fill a notify_info_data with the port name
2688 ********************************************************************/
2690 void spoolss_notify_port_name(int snum,
2691 SPOOL_NOTIFY_INFO_DATA *data,
2692 print_queue_struct *queue,
2693 NT_PRINTER_INFO_LEVEL *printer,
2694 TALLOC_CTX *mem_ctx)
2699 /* even if it's strange, that's consistant in all the code */
2701 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2703 data->notify_data.data.length = len;
2704 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2706 if (!data->notify_data.data.string) {
2707 data->notify_data.data.length = 0;
2711 memcpy(data->notify_data.data.string, temp, len);
2714 /*******************************************************************
2715 * fill a notify_info_data with the printername
2716 * but it doesn't exist, have to see what to do
2717 ********************************************************************/
2719 void spoolss_notify_driver_name(int snum,
2720 SPOOL_NOTIFY_INFO_DATA *data,
2721 print_queue_struct *queue,
2722 NT_PRINTER_INFO_LEVEL *printer,
2723 TALLOC_CTX *mem_ctx)
2728 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2730 data->notify_data.data.length = len;
2731 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2733 if (!data->notify_data.data.string) {
2734 data->notify_data.data.length = 0;
2738 memcpy(data->notify_data.data.string, temp, len);
2741 /*******************************************************************
2742 * fill a notify_info_data with the comment
2743 ********************************************************************/
2745 void spoolss_notify_comment(int snum,
2746 SPOOL_NOTIFY_INFO_DATA *data,
2747 print_queue_struct *queue,
2748 NT_PRINTER_INFO_LEVEL *printer,
2749 TALLOC_CTX *mem_ctx)
2754 if (*printer->info_2->comment == '\0')
2755 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2757 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2759 data->notify_data.data.length = len;
2760 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2762 if (!data->notify_data.data.string) {
2763 data->notify_data.data.length = 0;
2767 memcpy(data->notify_data.data.string, temp, len);
2770 /*******************************************************************
2771 * fill a notify_info_data with the comment
2772 * location = "Room 1, floor 2, building 3"
2773 ********************************************************************/
2775 void spoolss_notify_location(int snum,
2776 SPOOL_NOTIFY_INFO_DATA *data,
2777 print_queue_struct *queue,
2778 NT_PRINTER_INFO_LEVEL *printer,
2779 TALLOC_CTX *mem_ctx)
2784 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2786 data->notify_data.data.length = len;
2787 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2789 if (!data->notify_data.data.string) {
2790 data->notify_data.data.length = 0;
2794 memcpy(data->notify_data.data.string, temp, len);
2797 /*******************************************************************
2798 * fill a notify_info_data with the device mode
2799 * jfm:xxxx don't to it for know but that's a real problem !!!
2800 ********************************************************************/
2802 static void spoolss_notify_devmode(int snum,
2803 SPOOL_NOTIFY_INFO_DATA *data,
2804 print_queue_struct *queue,
2805 NT_PRINTER_INFO_LEVEL *printer,
2806 TALLOC_CTX *mem_ctx)
2810 /*******************************************************************
2811 * fill a notify_info_data with the separator file name
2812 ********************************************************************/
2814 void spoolss_notify_sepfile(int snum,
2815 SPOOL_NOTIFY_INFO_DATA *data,
2816 print_queue_struct *queue,
2817 NT_PRINTER_INFO_LEVEL *printer,
2818 TALLOC_CTX *mem_ctx)
2823 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2825 data->notify_data.data.length = len;
2826 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2828 if (!data->notify_data.data.string) {
2829 data->notify_data.data.length = 0;
2833 memcpy(data->notify_data.data.string, temp, len);
2836 /*******************************************************************
2837 * fill a notify_info_data with the print processor
2838 * jfm:xxxx return always winprint to indicate we don't do anything to it
2839 ********************************************************************/
2841 void spoolss_notify_print_processor(int snum,
2842 SPOOL_NOTIFY_INFO_DATA *data,
2843 print_queue_struct *queue,
2844 NT_PRINTER_INFO_LEVEL *printer,
2845 TALLOC_CTX *mem_ctx)
2850 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2852 data->notify_data.data.length = len;
2853 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2855 if (!data->notify_data.data.string) {
2856 data->notify_data.data.length = 0;
2860 memcpy(data->notify_data.data.string, temp, len);
2863 /*******************************************************************
2864 * fill a notify_info_data with the print processor options
2865 * jfm:xxxx send an empty string
2866 ********************************************************************/
2868 void spoolss_notify_parameters(int snum,
2869 SPOOL_NOTIFY_INFO_DATA *data,
2870 print_queue_struct *queue,
2871 NT_PRINTER_INFO_LEVEL *printer,
2872 TALLOC_CTX *mem_ctx)
2877 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2879 data->notify_data.data.length = len;
2880 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2882 if (!data->notify_data.data.string) {
2883 data->notify_data.data.length = 0;
2887 memcpy(data->notify_data.data.string, temp, len);
2890 /*******************************************************************
2891 * fill a notify_info_data with the data type
2892 * jfm:xxxx always send RAW as data type
2893 ********************************************************************/
2895 void spoolss_notify_datatype(int snum,
2896 SPOOL_NOTIFY_INFO_DATA *data,
2897 print_queue_struct *queue,
2898 NT_PRINTER_INFO_LEVEL *printer,
2899 TALLOC_CTX *mem_ctx)
2904 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2906 data->notify_data.data.length = len;
2907 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2909 if (!data->notify_data.data.string) {
2910 data->notify_data.data.length = 0;
2914 memcpy(data->notify_data.data.string, temp, len);
2917 /*******************************************************************
2918 * fill a notify_info_data with the security descriptor
2919 * jfm:xxxx send an null pointer to say no security desc
2920 * have to implement security before !
2921 ********************************************************************/
2923 static void spoolss_notify_security_desc(int snum,
2924 SPOOL_NOTIFY_INFO_DATA *data,
2925 print_queue_struct *queue,
2926 NT_PRINTER_INFO_LEVEL *printer,
2927 TALLOC_CTX *mem_ctx)
2929 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2930 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2933 /*******************************************************************
2934 * fill a notify_info_data with the attributes
2935 * jfm:xxxx a samba printer is always shared
2936 ********************************************************************/
2938 void spoolss_notify_attributes(int snum,
2939 SPOOL_NOTIFY_INFO_DATA *data,
2940 print_queue_struct *queue,
2941 NT_PRINTER_INFO_LEVEL *printer,
2942 TALLOC_CTX *mem_ctx)
2944 data->notify_data.value[0] = printer->info_2->attributes;
2945 data->notify_data.value[1] = 0;
2948 /*******************************************************************
2949 * fill a notify_info_data with the priority
2950 ********************************************************************/
2952 static void spoolss_notify_priority(int snum,
2953 SPOOL_NOTIFY_INFO_DATA *data,
2954 print_queue_struct *queue,
2955 NT_PRINTER_INFO_LEVEL *printer,
2956 TALLOC_CTX *mem_ctx)
2958 data->notify_data.value[0] = printer->info_2->priority;
2959 data->notify_data.value[1] = 0;
2962 /*******************************************************************
2963 * fill a notify_info_data with the default priority
2964 ********************************************************************/
2966 static void spoolss_notify_default_priority(int snum,
2967 SPOOL_NOTIFY_INFO_DATA *data,
2968 print_queue_struct *queue,
2969 NT_PRINTER_INFO_LEVEL *printer,
2970 TALLOC_CTX *mem_ctx)
2972 data->notify_data.value[0] = printer->info_2->default_priority;
2973 data->notify_data.value[1] = 0;
2976 /*******************************************************************
2977 * fill a notify_info_data with the start time
2978 ********************************************************************/
2980 static void spoolss_notify_start_time(int snum,
2981 SPOOL_NOTIFY_INFO_DATA *data,
2982 print_queue_struct *queue,
2983 NT_PRINTER_INFO_LEVEL *printer,
2984 TALLOC_CTX *mem_ctx)
2986 data->notify_data.value[0] = printer->info_2->starttime;
2987 data->notify_data.value[1] = 0;
2990 /*******************************************************************
2991 * fill a notify_info_data with the until time
2992 ********************************************************************/
2994 static void spoolss_notify_until_time(int snum,
2995 SPOOL_NOTIFY_INFO_DATA *data,
2996 print_queue_struct *queue,
2997 NT_PRINTER_INFO_LEVEL *printer,
2998 TALLOC_CTX *mem_ctx)
3000 data->notify_data.value[0] = printer->info_2->untiltime;
3001 data->notify_data.value[1] = 0;
3004 /*******************************************************************
3005 * fill a notify_info_data with the status
3006 ********************************************************************/
3008 static void spoolss_notify_status(int snum,
3009 SPOOL_NOTIFY_INFO_DATA *data,
3010 print_queue_struct *queue,
3011 NT_PRINTER_INFO_LEVEL *printer,
3012 TALLOC_CTX *mem_ctx)
3014 print_status_struct status;
3016 print_queue_length(snum, &status);
3017 data->notify_data.value[0]=(uint32) status.status;
3018 data->notify_data.value[1] = 0;
3021 /*******************************************************************
3022 * fill a notify_info_data with the number of jobs queued
3023 ********************************************************************/
3025 void spoolss_notify_cjobs(int snum,
3026 SPOOL_NOTIFY_INFO_DATA *data,
3027 print_queue_struct *queue,
3028 NT_PRINTER_INFO_LEVEL *printer,
3029 TALLOC_CTX *mem_ctx)
3031 data->notify_data.value[0] = print_queue_length(snum, NULL);
3032 data->notify_data.value[1] = 0;
3035 /*******************************************************************
3036 * fill a notify_info_data with the average ppm
3037 ********************************************************************/
3039 static void spoolss_notify_average_ppm(int snum,
3040 SPOOL_NOTIFY_INFO_DATA *data,
3041 print_queue_struct *queue,
3042 NT_PRINTER_INFO_LEVEL *printer,
3043 TALLOC_CTX *mem_ctx)
3045 /* always respond 8 pages per minutes */
3046 /* a little hard ! */
3047 data->notify_data.value[0] = printer->info_2->averageppm;
3048 data->notify_data.value[1] = 0;
3051 /*******************************************************************
3052 * fill a notify_info_data with username
3053 ********************************************************************/
3055 static void spoolss_notify_username(int snum,
3056 SPOOL_NOTIFY_INFO_DATA *data,
3057 print_queue_struct *queue,
3058 NT_PRINTER_INFO_LEVEL *printer,
3059 TALLOC_CTX *mem_ctx)
3064 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3066 data->notify_data.data.length = len;
3067 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3069 if (!data->notify_data.data.string) {
3070 data->notify_data.data.length = 0;
3074 memcpy(data->notify_data.data.string, temp, len);
3077 /*******************************************************************
3078 * fill a notify_info_data with job status
3079 ********************************************************************/
3081 static void spoolss_notify_job_status(int snum,
3082 SPOOL_NOTIFY_INFO_DATA *data,
3083 print_queue_struct *queue,
3084 NT_PRINTER_INFO_LEVEL *printer,
3085 TALLOC_CTX *mem_ctx)
3087 data->notify_data.value[0]=nt_printj_status(queue->status);
3088 data->notify_data.value[1] = 0;
3091 /*******************************************************************
3092 * fill a notify_info_data with job name
3093 ********************************************************************/
3095 static void spoolss_notify_job_name(int snum,
3096 SPOOL_NOTIFY_INFO_DATA *data,
3097 print_queue_struct *queue,
3098 NT_PRINTER_INFO_LEVEL *printer,
3099 TALLOC_CTX *mem_ctx)
3104 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3106 data->notify_data.data.length = len;
3107 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3109 if (!data->notify_data.data.string) {
3110 data->notify_data.data.length = 0;
3114 memcpy(data->notify_data.data.string, temp, len);
3117 /*******************************************************************
3118 * fill a notify_info_data with job status
3119 ********************************************************************/
3121 static void spoolss_notify_job_status_string(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3128 * Now we're returning job status codes we just return a "" here. JRA.
3135 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3138 switch (queue->status) {
3143 p = ""; /* NT provides the paused string */
3152 #endif /* NO LONGER NEEDED. */
3154 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3156 data->notify_data.data.length = len;
3157 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3159 if (!data->notify_data.data.string) {
3160 data->notify_data.data.length = 0;
3164 memcpy(data->notify_data.data.string, temp, len);
3167 /*******************************************************************
3168 * fill a notify_info_data with job time
3169 ********************************************************************/
3171 static void spoolss_notify_job_time(int snum,
3172 SPOOL_NOTIFY_INFO_DATA *data,
3173 print_queue_struct *queue,
3174 NT_PRINTER_INFO_LEVEL *printer,
3175 TALLOC_CTX *mem_ctx)
3177 data->notify_data.value[0]=0x0;
3178 data->notify_data.value[1]=0;
3181 /*******************************************************************
3182 * fill a notify_info_data with job size
3183 ********************************************************************/
3185 static void spoolss_notify_job_size(int snum,
3186 SPOOL_NOTIFY_INFO_DATA *data,
3187 print_queue_struct *queue,
3188 NT_PRINTER_INFO_LEVEL *printer,
3189 TALLOC_CTX *mem_ctx)
3191 data->notify_data.value[0]=queue->size;
3192 data->notify_data.value[1]=0;
3195 /*******************************************************************
3196 * fill a notify_info_data with page info
3197 ********************************************************************/
3198 static void spoolss_notify_total_pages(int snum,
3199 SPOOL_NOTIFY_INFO_DATA *data,
3200 print_queue_struct *queue,
3201 NT_PRINTER_INFO_LEVEL *printer,
3202 TALLOC_CTX *mem_ctx)
3204 data->notify_data.value[0]=queue->page_count;
3205 data->notify_data.value[1]=0;
3208 /*******************************************************************
3209 * fill a notify_info_data with pages printed info.
3210 ********************************************************************/
3211 static void spoolss_notify_pages_printed(int snum,
3212 SPOOL_NOTIFY_INFO_DATA *data,
3213 print_queue_struct *queue,
3214 NT_PRINTER_INFO_LEVEL *printer,
3215 TALLOC_CTX *mem_ctx)
3217 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3218 data->notify_data.value[1]=0;
3221 /*******************************************************************
3222 Fill a notify_info_data with job position.
3223 ********************************************************************/
3225 static void spoolss_notify_job_position(int snum,
3226 SPOOL_NOTIFY_INFO_DATA *data,
3227 print_queue_struct *queue,
3228 NT_PRINTER_INFO_LEVEL *printer,
3229 TALLOC_CTX *mem_ctx)
3231 data->notify_data.value[0]=queue->job;
3232 data->notify_data.value[1]=0;
3235 /*******************************************************************
3236 Fill a notify_info_data with submitted time.
3237 ********************************************************************/
3239 static void spoolss_notify_submitted_time(int snum,
3240 SPOOL_NOTIFY_INFO_DATA *data,
3241 print_queue_struct *queue,
3242 NT_PRINTER_INFO_LEVEL *printer,
3243 TALLOC_CTX *mem_ctx)
3250 t=gmtime(&queue->time);
3252 len = sizeof(SYSTEMTIME);
3254 data->notify_data.data.length = len;
3255 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3257 if (!data->notify_data.data.string) {
3258 data->notify_data.data.length = 0;
3262 make_systemtime(&st, t);
3265 * Systemtime must be linearized as a set of UINT16's.
3266 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3269 p = (char *)data->notify_data.data.string;
3270 SSVAL(p, 0, st.year);
3271 SSVAL(p, 2, st.month);
3272 SSVAL(p, 4, st.dayofweek);
3273 SSVAL(p, 6, st.day);
3274 SSVAL(p, 8, st.hour);
3275 SSVAL(p, 10, st.minute);
3276 SSVAL(p, 12, st.second);
3277 SSVAL(p, 14, st.milliseconds);
3280 struct s_notify_info_data_table
3286 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3287 print_queue_struct *queue,
3288 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3291 /* A table describing the various print notification constants and
3292 whether the notification data is a pointer to a variable sized
3293 buffer, a one value uint32 or a two value uint32. */
3295 static const struct s_notify_info_data_table notify_info_data_table[] =
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3337 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3338 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3339 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3340 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3341 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3342 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3343 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3344 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3345 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3348 /*******************************************************************
3349 Return the size of info_data structure.
3350 ********************************************************************/
3352 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3356 for (i = 0; i < sizeof(notify_info_data_table); i++)
3358 if ( (notify_info_data_table[i].type == type)
3359 && (notify_info_data_table[i].field == field) )
3361 switch(notify_info_data_table[i].size)
3363 case NOTIFY_ONE_VALUE:
3364 case NOTIFY_TWO_VALUE:
3369 /* The only pointer notify data I have seen on
3370 the wire is the submitted time and this has
3371 the notify size set to 4. -tpot */
3373 case NOTIFY_POINTER:
3376 case NOTIFY_SECDESC:
3382 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3387 /*******************************************************************
3388 Return the type of notify_info_data.
3389 ********************************************************************/
3391 static int type_of_notify_info_data(uint16 type, uint16 field)
3395 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3396 if (notify_info_data_table[i].type == type &&
3397 notify_info_data_table[i].field == field)
3398 return notify_info_data_table[i].size;
3404 /****************************************************************************
3405 ****************************************************************************/
3407 static int search_notify(uint16 type, uint16 field, int *value)
3411 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3412 if (notify_info_data_table[i].type == type &&
3413 notify_info_data_table[i].field == field &&
3414 notify_info_data_table[i].fn != NULL) {
3423 /****************************************************************************
3424 ****************************************************************************/
3426 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3428 info_data->type = type;
3429 info_data->field = field;
3430 info_data->reserved = 0;
3432 info_data->size = size_of_notify_info_data(type, field);
3433 info_data->enc_type = type_of_notify_info_data(type, field);
3440 /*******************************************************************
3442 * fill a notify_info struct with info asked
3444 ********************************************************************/
3446 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
3447 snum, SPOOL_NOTIFY_OPTION_TYPE
3448 *option_type, uint32 id,
3449 TALLOC_CTX *mem_ctx)
3455 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3456 NT_PRINTER_INFO_LEVEL *printer = NULL;
3457 print_queue_struct *queue=NULL;
3459 type=option_type->type;
3461 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3462 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3463 option_type->count, lp_servicename(snum)));
3465 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3468 for(field_num=0; field_num<option_type->count; field_num++)
3470 field = option_type->fields[field_num];
3472 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3474 if (!search_notify(type, field, &j) )
3477 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
3479 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3485 current_data = &info->data[info->count];
3487 construct_info_data(current_data, type, field, id);
3489 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3490 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3492 notify_info_data_table[j].fn(snum, current_data, queue,
3498 free_a_printer(&printer, 2);
3502 /*******************************************************************
3504 * fill a notify_info struct with info asked
3506 ********************************************************************/
3508 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3509 SPOOL_NOTIFY_INFO *info,
3510 NT_PRINTER_INFO_LEVEL *printer,
3511 int snum, SPOOL_NOTIFY_OPTION_TYPE
3512 *option_type, uint32 id,
3513 TALLOC_CTX *mem_ctx)
3519 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3521 DEBUG(4,("construct_notify_jobs_info\n"));
3523 type = option_type->type;
3525 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3526 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3527 option_type->count));
3529 for(field_num=0; field_num<option_type->count; field_num++) {
3530 field = option_type->fields[field_num];
3532 if (!search_notify(type, field, &j) )
3535 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3536 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3539 else info->data = tid;
3541 current_data=&(info->data[info->count]);
3543 construct_info_data(current_data, type, field, id);
3544 notify_info_data_table[j].fn(snum, current_data, queue,
3553 * JFM: The enumeration is not that simple, it's even non obvious.
3555 * let's take an example: I want to monitor the PRINTER SERVER for
3556 * the printer's name and the number of jobs currently queued.
3557 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3558 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3560 * I have 3 printers on the back of my server.
3562 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3565 * 1 printer 1 name 1
3566 * 2 printer 1 cjob 1
3567 * 3 printer 2 name 2
3568 * 4 printer 2 cjob 2
3569 * 5 printer 3 name 3
3570 * 6 printer 3 name 3
3572 * that's the print server case, the printer case is even worse.
3575 /*******************************************************************
3577 * enumerate all printers on the printserver
3578 * fill a notify_info struct with info asked
3580 ********************************************************************/
3582 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3583 SPOOL_NOTIFY_INFO *info,
3584 TALLOC_CTX *mem_ctx)
3587 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3588 int n_services=lp_numservices();
3591 SPOOL_NOTIFY_OPTION *option;
3592 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3594 DEBUG(4,("printserver_notify_info\n"));
3599 option=Printer->notify.option;
3605 for (i=0; i<option->count; i++) {
3606 option_type=&(option->ctr.type[i]);
3608 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3611 for (snum=0; snum<n_services; snum++)
3613 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3614 construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
3620 * Debugging information, don't delete.
3623 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3624 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3625 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3627 for (i=0; i<info->count; i++) {
3628 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3629 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3630 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3637 /*******************************************************************
3639 * fill a notify_info struct with info asked
3641 ********************************************************************/
3643 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3644 TALLOC_CTX *mem_ctx)
3647 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3650 SPOOL_NOTIFY_OPTION *option;
3651 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3653 print_queue_struct *queue=NULL;
3654 print_status_struct status;
3656 DEBUG(4,("printer_notify_info\n"));
3661 option=Printer->notify.option;
3667 get_printer_snum(p, hnd, &snum);
3669 for (i=0; i<option->count; i++) {
3670 option_type=&option->ctr.type[i];
3672 switch ( option_type->type ) {
3673 case PRINTER_NOTIFY_TYPE:
3674 if(construct_notify_printer_info(info, snum,
3680 case JOB_NOTIFY_TYPE: {
3681 NT_PRINTER_INFO_LEVEL *printer = NULL;
3683 count = print_queue_status(snum, &queue, &status);
3685 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3686 lp_servicename(snum))))
3689 for (j=0; j<count; j++) {
3690 construct_notify_jobs_info(&queue[j], info,
3697 free_a_printer(&printer, 2);
3707 * Debugging information, don't delete.
3710 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3711 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3712 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3714 for (i=0; i<info->count; i++) {
3715 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3716 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3717 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3723 /********************************************************************
3725 ********************************************************************/
3727 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3729 POLICY_HND *handle = &q_u->handle;
3730 SPOOL_NOTIFY_INFO *info = &r_u->info;
3732 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3733 WERROR result = WERR_BADFID;
3735 /* we always have a NOTIFY_INFO struct */
3739 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3740 OUR_HANDLE(handle)));
3744 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3747 * We are now using the change value, and
3748 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3749 * I don't have a global notification system, I'm sending back all the
3750 * informations even when _NOTHING_ has changed.
3753 /* We need to keep track of the change value to send back in
3754 RRPCN replies otherwise our updates are ignored. */
3756 Printer->notify.fnpcn = True;
3758 if (Printer->notify.client_connected) {
3759 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3760 Printer->notify.change = q_u->change;
3763 /* just ignore the SPOOL_NOTIFY_OPTION */
3765 switch (Printer->printer_type) {
3766 case PRINTER_HANDLE_IS_PRINTSERVER:
3767 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3770 case PRINTER_HANDLE_IS_PRINTER:
3771 result = printer_notify_info(p, handle, info, p->mem_ctx);
3775 Printer->notify.fnpcn = False;
3781 /********************************************************************
3782 * construct_printer_info_0
3783 * fill a printer_info_0 struct
3784 ********************************************************************/
3786 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3790 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3791 counter_printer_0 *session_counter;
3792 uint32 global_counter;
3795 print_status_struct status;
3797 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3800 count = print_queue_length(snum, &status);
3802 /* check if we already have a counter for this printer */
3803 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3805 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3806 if (session_counter->snum == snum)
3810 /* it's the first time, add it to the list */
3811 if (session_counter==NULL) {
3812 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3813 free_a_printer(&ntprinter, 2);
3816 ZERO_STRUCTP(session_counter);
3817 session_counter->snum=snum;
3818 session_counter->counter=0;
3819 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3823 session_counter->counter++;
3826 * the global_counter should be stored in a TDB as it's common to all the clients
3827 * and should be zeroed on samba startup
3829 global_counter=session_counter->counter;
3831 pstrcpy(chaine,ntprinter->info_2->printername);
3833 init_unistr(&printer->printername, chaine);
3835 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3836 init_unistr(&printer->servername, chaine);
3838 printer->cjobs = count;
3839 printer->total_jobs = 0;
3840 printer->total_bytes = 0;
3842 setuptime = (time_t)ntprinter->info_2->setuptime;
3843 t=gmtime(&setuptime);
3845 printer->year = t->tm_year+1900;
3846 printer->month = t->tm_mon+1;
3847 printer->dayofweek = t->tm_wday;
3848 printer->day = t->tm_mday;
3849 printer->hour = t->tm_hour;
3850 printer->minute = t->tm_min;
3851 printer->second = t->tm_sec;
3852 printer->milliseconds = 0;
3854 printer->global_counter = global_counter;
3855 printer->total_pages = 0;
3857 printer->major_version = 0x0005; /* NT 5 */
3858 printer->build_version = 0x0893; /* build 2195 */
3860 printer->major_version = 0x0004; /* NT 4 */
3861 printer->build_version = 0x0565; /* build 1381 */
3863 printer->unknown7 = 0x1;
3864 printer->unknown8 = 0x0;
3865 printer->unknown9 = 0x0;
3866 printer->session_counter = session_counter->counter;
3867 printer->unknown11 = 0x0;
3868 printer->printer_errors = 0x0; /* number of print failure */
3869 printer->unknown13 = 0x0;
3870 printer->unknown14 = 0x1;
3871 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3872 printer->unknown16 = 0x0;
3873 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3874 printer->unknown18 = 0x0;
3875 printer->status = nt_printq_status(status.status);
3876 printer->unknown20 = 0x0;
3877 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3878 printer->unknown22 = 0x0;
3879 printer->unknown23 = 0x6; /* 6 ???*/
3880 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3881 printer->unknown25 = 0;
3882 printer->unknown26 = 0;
3883 printer->unknown27 = 0;
3884 printer->unknown28 = 0;
3885 printer->unknown29 = 0;
3887 free_a_printer(&ntprinter,2);
3891 /********************************************************************
3892 * construct_printer_info_1
3893 * fill a printer_info_1 struct
3894 ********************************************************************/
3895 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3899 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3901 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3904 printer->flags=flags;
3906 if (*ntprinter->info_2->comment == '\0') {
3907 init_unistr(&printer->comment, lp_comment(snum));
3908 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3909 ntprinter->info_2->drivername, lp_comment(snum));
3912 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3913 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3914 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3917 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3919 init_unistr(&printer->description, chaine);
3920 init_unistr(&printer->name, chaine2);
3922 free_a_printer(&ntprinter,2);
3927 /****************************************************************************
3928 Free a DEVMODE struct.
3929 ****************************************************************************/
3931 static void free_dev_mode(DEVICEMODE *dev)
3936 SAFE_FREE(dev->private);
3941 /****************************************************************************
3942 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3943 should be valid upon entry
3944 ****************************************************************************/
3946 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
3948 if ( !devmode || !ntdevmode )
3951 init_unistr(&devmode->devicename, ntdevmode->devicename);
3953 init_unistr(&devmode->formname, ntdevmode->formname);
3955 devmode->specversion = ntdevmode->specversion;
3956 devmode->driverversion = ntdevmode->driverversion;
3957 devmode->size = ntdevmode->size;
3958 devmode->driverextra = ntdevmode->driverextra;
3959 devmode->fields = ntdevmode->fields;
3961 devmode->orientation = ntdevmode->orientation;
3962 devmode->papersize = ntdevmode->papersize;
3963 devmode->paperlength = ntdevmode->paperlength;
3964 devmode->paperwidth = ntdevmode->paperwidth;
3965 devmode->scale = ntdevmode->scale;
3966 devmode->copies = ntdevmode->copies;
3967 devmode->defaultsource = ntdevmode->defaultsource;
3968 devmode->printquality = ntdevmode->printquality;
3969 devmode->color = ntdevmode->color;
3970 devmode->duplex = ntdevmode->duplex;
3971 devmode->yresolution = ntdevmode->yresolution;
3972 devmode->ttoption = ntdevmode->ttoption;
3973 devmode->collate = ntdevmode->collate;
3974 devmode->icmmethod = ntdevmode->icmmethod;
3975 devmode->icmintent = ntdevmode->icmintent;
3976 devmode->mediatype = ntdevmode->mediatype;
3977 devmode->dithertype = ntdevmode->dithertype;
3979 if (ntdevmode->private != NULL) {
3980 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3987 /****************************************************************************
3988 Create a DEVMODE struct. Returns malloced memory.
3989 ****************************************************************************/
3991 DEVICEMODE *construct_dev_mode(int snum)
3993 NT_PRINTER_INFO_LEVEL *printer = NULL;
3994 DEVICEMODE *devmode = NULL;
3996 DEBUG(7,("construct_dev_mode\n"));
3998 DEBUGADD(8,("getting printer characteristics\n"));
4000 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4003 if ( !printer->info_2->devmode ) {
4004 DEBUG(5, ("BONG! There was no device mode!\n"));
4008 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4009 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4013 ZERO_STRUCTP(devmode);
4015 DEBUGADD(8,("loading DEVICEMODE\n"));
4017 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4018 free_dev_mode( devmode );
4023 free_a_printer(&printer,2);
4028 /********************************************************************
4029 * construct_printer_info_2
4030 * fill a printer_info_2 struct
4031 ********************************************************************/
4033 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
4036 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4038 print_status_struct status;
4040 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4043 count = print_queue_length(snum, &status);
4045 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4046 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4047 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4048 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4049 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4051 if (*ntprinter->info_2->comment == '\0')
4052 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4054 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4056 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4057 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4058 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4059 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4060 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4062 printer->attributes = ntprinter->info_2->attributes;
4064 printer->priority = ntprinter->info_2->priority; /* priority */
4065 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4066 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4067 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4068 printer->status = nt_printq_status(status.status); /* status */
4069 printer->cjobs = count; /* jobs */
4070 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4072 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4073 DEBUG(8, ("Returning NULL Devicemode!\n"));
4076 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4077 /* steal the printer info sec_desc structure. [badly done]. */
4078 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4079 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4080 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4081 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4084 printer->secdesc = NULL;
4087 free_a_printer(&ntprinter, 2);
4091 /********************************************************************
4092 * construct_printer_info_3
4093 * fill a printer_info_3 struct
4094 ********************************************************************/
4096 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
4098 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4099 PRINTER_INFO_3 *printer = NULL;
4101 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4105 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4106 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4110 ZERO_STRUCTP(printer);
4112 printer->flags = 4; /* These are the components of the SD we are returning. */
4113 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4114 /* steal the printer info sec_desc structure. [badly done]. */
4115 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4119 * Set the flags for the components we are returning.
4122 if (printer->secdesc->owner_sid)
4123 printer->flags |= OWNER_SECURITY_INFORMATION;
4125 if (printer->secdesc->grp_sid)
4126 printer->flags |= GROUP_SECURITY_INFORMATION;
4128 if (printer->secdesc->dacl)
4129 printer->flags |= DACL_SECURITY_INFORMATION;
4131 if (printer->secdesc->sacl)
4132 printer->flags |= SACL_SECURITY_INFORMATION;
4135 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4136 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4137 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4140 free_a_printer(&ntprinter, 2);
4142 *pp_printer = printer;
4146 /********************************************************************
4147 * construct_printer_info_4
4148 * fill a printer_info_4 struct
4149 ********************************************************************/
4151 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
4153 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4155 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4158 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4159 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4160 printer->attributes = ntprinter->info_2->attributes;
4162 free_a_printer(&ntprinter, 2);
4166 /********************************************************************
4167 * construct_printer_info_5
4168 * fill a printer_info_5 struct
4169 ********************************************************************/
4171 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
4173 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4175 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4178 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4179 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
4180 printer->attributes = ntprinter->info_2->attributes;
4181 printer->device_not_selected_timeout = 0x3a98;
4182 printer->transmission_retry_timeout = 0xafc8;
4184 free_a_printer(&ntprinter, 2);
4188 /********************************************************************
4189 * construct_printer_info_7
4190 * fill a printer_info_7 struct
4191 ********************************************************************/
4193 static BOOL construct_printer_info_7(PRINTER_INFO_7 *printer, int snum)
4195 char *guid_str = NULL;
4198 if (is_printer_published(snum, &guid)) {
4199 asprintf(&guid_str, "{%s}", uuid_string_static(guid));
4201 init_unistr(&printer->guid, guid_str);
4202 printer->action = SPOOL_DS_PUBLISH;
4204 init_unistr(&printer->guid, "");
4205 printer->action = SPOOL_DS_UNPUBLISH;
4211 /********************************************************************
4212 Spoolss_enumprinters.
4213 ********************************************************************/
4215 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4219 int n_services=lp_numservices();
4220 PRINTER_INFO_1 *tp, *printers=NULL;
4221 PRINTER_INFO_1 current_prt;
4223 DEBUG(4,("enum_all_printers_info_1\n"));
4225 for (snum=0; snum<n_services; snum++) {
4226 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4227 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4229 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
4230 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4231 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4232 SAFE_FREE(printers);
4237 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4239 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4245 /* check the required size. */
4246 for (i=0; i<*returned; i++)
4247 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4249 if (!alloc_buffer_size(buffer, *needed))
4250 return WERR_INSUFFICIENT_BUFFER;
4252 /* fill the buffer with the structures */
4253 for (i=0; i<*returned; i++)
4254 smb_io_printer_info_1("", buffer, &printers[i], 0);
4257 SAFE_FREE(printers);
4259 if (*needed > offered) {
4261 return WERR_INSUFFICIENT_BUFFER;
4267 /********************************************************************
4268 enum_all_printers_info_1_local.
4269 *********************************************************************/
4271 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4273 DEBUG(4,("enum_all_printers_info_1_local\n"));
4275 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4278 /********************************************************************
4279 enum_all_printers_info_1_name.
4280 *********************************************************************/
4282 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4286 DEBUG(4,("enum_all_printers_info_1_name\n"));
4288 if ((name[0] == '\\') && (name[1] == '\\'))
4291 if (is_myname_or_ipaddr(s)) {
4292 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4295 return WERR_INVALID_NAME;
4298 /********************************************************************
4299 enum_all_printers_info_1_remote.
4300 *********************************************************************/
4302 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4304 PRINTER_INFO_1 *printer;
4305 fstring printername;
4308 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4310 /* JFM: currently it's more a place holder than anything else.
4311 * In the spooler world there is a notion of server registration.
4312 * the print servers are registring (sp ?) on the PDC (in the same domain)
4314 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4317 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4322 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4323 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4324 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4326 init_unistr(&printer->description, desc);
4327 init_unistr(&printer->name, printername);
4328 init_unistr(&printer->comment, comment);
4329 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4331 /* check the required size. */
4332 *needed += spoolss_size_printer_info_1(printer);
4334 if (!alloc_buffer_size(buffer, *needed)) {
4336 return WERR_INSUFFICIENT_BUFFER;
4339 /* fill the buffer with the structures */
4340 smb_io_printer_info_1("", buffer, printer, 0);
4345 if (*needed > offered) {
4347 return WERR_INSUFFICIENT_BUFFER;
4353 /********************************************************************
4354 enum_all_printers_info_1_network.
4355 *********************************************************************/
4357 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4361 DEBUG(4,("enum_all_printers_info_1_network\n"));
4363 /* If we respond to a enum_printers level 1 on our name with flags
4364 set to PRINTER_ENUM_REMOTE with a list of printers then these
4365 printers incorrectly appear in the APW browse list.
4366 Specifically the printers for the server appear at the workgroup
4367 level where all the other servers in the domain are
4368 listed. Windows responds to this call with a
4369 WERR_CAN_NOT_COMPLETE so we should do the same. */
4371 if (name[0] == '\\' && name[1] == '\\')
4374 if (is_myname_or_ipaddr(s))
4375 return WERR_CAN_NOT_COMPLETE;
4377 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4380 /********************************************************************
4381 * api_spoolss_enumprinters
4383 * called from api_spoolss_enumprinters (see this to understand)
4384 ********************************************************************/
4386 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4390 int n_services=lp_numservices();
4391 PRINTER_INFO_2 *tp, *printers=NULL;
4392 PRINTER_INFO_2 current_prt;
4394 for (snum=0; snum<n_services; snum++) {
4395 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4396 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4398 if (construct_printer_info_2(¤t_prt, snum)) {
4399 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4400 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4401 SAFE_FREE(printers);
4406 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4407 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4413 /* check the required size. */
4414 for (i=0; i<*returned; i++)
4415 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4417 if (!alloc_buffer_size(buffer, *needed)) {
4418 for (i=0; i<*returned; i++) {
4419 free_devmode(printers[i].devmode);
4421 SAFE_FREE(printers);
4422 return WERR_INSUFFICIENT_BUFFER;
4425 /* fill the buffer with the structures */
4426 for (i=0; i<*returned; i++)
4427 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4430 for (i=0; i<*returned; i++) {
4431 free_devmode(printers[i].devmode);
4433 SAFE_FREE(printers);
4435 if (*needed > offered) {
4437 return WERR_INSUFFICIENT_BUFFER;
4443 /********************************************************************
4444 * handle enumeration of printers at level 1
4445 ********************************************************************/
4447 static WERROR enumprinters_level1( uint32 flags, fstring name,
4448 NEW_BUFFER *buffer, uint32 offered,
4449 uint32 *needed, uint32 *returned)
4451 /* Not all the flags are equals */
4453 if (flags & PRINTER_ENUM_LOCAL)
4454 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4456 if (flags & PRINTER_ENUM_NAME)
4457 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4459 if (flags & PRINTER_ENUM_REMOTE)
4460 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4462 if (flags & PRINTER_ENUM_NETWORK)
4463 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4465 return WERR_OK; /* NT4sp5 does that */
4468 /********************************************************************
4469 * handle enumeration of printers at level 2
4470 ********************************************************************/
4472 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4473 NEW_BUFFER *buffer, uint32 offered,
4474 uint32 *needed, uint32 *returned)
4476 char *s = servername;
4478 if (flags & PRINTER_ENUM_LOCAL) {
4479 return enum_all_printers_info_2(buffer, offered, needed, returned);
4482 if (flags & PRINTER_ENUM_NAME) {
4483 if ((servername[0] == '\\') && (servername[1] == '\\'))
4485 if (is_myname_or_ipaddr(s))
4486 return enum_all_printers_info_2(buffer, offered, needed, returned);
4488 return WERR_INVALID_NAME;
4491 if (flags & PRINTER_ENUM_REMOTE)
4492 return WERR_UNKNOWN_LEVEL;
4497 /********************************************************************
4498 * handle enumeration of printers at level 5
4499 ********************************************************************/
4501 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4502 NEW_BUFFER *buffer, uint32 offered,
4503 uint32 *needed, uint32 *returned)
4505 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4509 /********************************************************************
4510 * api_spoolss_enumprinters
4512 * called from api_spoolss_enumprinters (see this to understand)
4513 ********************************************************************/
4515 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4517 uint32 flags = q_u->flags;
4518 UNISTR2 *servername = &q_u->servername;
4519 uint32 level = q_u->level;
4520 NEW_BUFFER *buffer = NULL;
4521 uint32 offered = q_u->offered;
4522 uint32 *needed = &r_u->needed;
4523 uint32 *returned = &r_u->returned;
4527 /* that's an [in out] buffer */
4528 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4529 buffer = r_u->buffer;
4531 DEBUG(4,("_spoolss_enumprinters\n"));
4538 * flags==PRINTER_ENUM_NAME
4539 * if name=="" then enumerates all printers
4540 * if name!="" then enumerate the printer
4541 * flags==PRINTER_ENUM_REMOTE
4542 * name is NULL, enumerate printers
4543 * Level 2: name!="" enumerates printers, name can't be NULL
4544 * Level 3: doesn't exist
4545 * Level 4: does a local registry lookup
4546 * Level 5: same as Level 2
4549 unistr2_to_ascii(name, servername, sizeof(name)-1);
4554 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4556 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4558 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4563 return WERR_UNKNOWN_LEVEL;
4566 /****************************************************************************
4567 ****************************************************************************/
4569 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4571 PRINTER_INFO_0 *printer=NULL;
4573 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4576 construct_printer_info_0(printer, snum);
4578 /* check the required size. */
4579 *needed += spoolss_size_printer_info_0(printer);
4581 if (!alloc_buffer_size(buffer, *needed)) {
4583 return WERR_INSUFFICIENT_BUFFER;
4586 /* fill the buffer with the structures */
4587 smb_io_printer_info_0("", buffer, printer, 0);
4592 if (*needed > offered) {
4593 return WERR_INSUFFICIENT_BUFFER;
4599 /****************************************************************************
4600 ****************************************************************************/
4602 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4604 PRINTER_INFO_1 *printer=NULL;
4606 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4609 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4611 /* check the required size. */
4612 *needed += spoolss_size_printer_info_1(printer);
4614 if (!alloc_buffer_size(buffer, *needed)) {
4616 return WERR_INSUFFICIENT_BUFFER;
4619 /* fill the buffer with the structures */
4620 smb_io_printer_info_1("", buffer, printer, 0);
4625 if (*needed > offered) {
4626 return WERR_INSUFFICIENT_BUFFER;
4632 /****************************************************************************
4633 ****************************************************************************/
4635 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4637 PRINTER_INFO_2 *printer=NULL;
4639 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4642 construct_printer_info_2(printer, snum);
4644 /* check the required size. */
4645 *needed += spoolss_size_printer_info_2(printer);
4647 if (!alloc_buffer_size(buffer, *needed)) {
4648 free_printer_info_2(printer);
4649 return WERR_INSUFFICIENT_BUFFER;
4652 /* fill the buffer with the structures */
4653 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4654 free_printer_info_2(printer);
4659 free_printer_info_2(printer);
4661 if (*needed > offered) {
4662 return WERR_INSUFFICIENT_BUFFER;
4668 /****************************************************************************
4669 ****************************************************************************/
4671 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4673 PRINTER_INFO_3 *printer=NULL;
4675 if (!construct_printer_info_3(&printer, snum))
4678 /* check the required size. */
4679 *needed += spoolss_size_printer_info_3(printer);
4681 if (!alloc_buffer_size(buffer, *needed)) {
4682 free_printer_info_3(printer);
4683 return WERR_INSUFFICIENT_BUFFER;
4686 /* fill the buffer with the structures */
4687 smb_io_printer_info_3("", buffer, printer, 0);
4690 free_printer_info_3(printer);
4692 if (*needed > offered) {
4693 return WERR_INSUFFICIENT_BUFFER;
4699 /****************************************************************************
4700 ****************************************************************************/
4702 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4704 PRINTER_INFO_4 *printer=NULL;
4706 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4709 if (!construct_printer_info_4(printer, snum))
4712 /* check the required size. */
4713 *needed += spoolss_size_printer_info_4(printer);
4715 if (!alloc_buffer_size(buffer, *needed)) {
4716 free_printer_info_4(printer);
4717 return WERR_INSUFFICIENT_BUFFER;
4720 /* fill the buffer with the structures */
4721 smb_io_printer_info_4("", buffer, printer, 0);
4724 free_printer_info_4(printer);
4726 if (*needed > offered) {
4727 return WERR_INSUFFICIENT_BUFFER;
4733 /****************************************************************************
4734 ****************************************************************************/
4736 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4738 PRINTER_INFO_5 *printer=NULL;
4740 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4743 if (!construct_printer_info_5(printer, snum))
4746 /* check the required size. */
4747 *needed += spoolss_size_printer_info_5(printer);
4749 if (!alloc_buffer_size(buffer, *needed)) {
4750 free_printer_info_5(printer);
4751 return WERR_INSUFFICIENT_BUFFER;
4754 /* fill the buffer with the structures */
4755 smb_io_printer_info_5("", buffer, printer, 0);
4758 free_printer_info_5(printer);
4760 if (*needed > offered) {
4761 return WERR_INSUFFICIENT_BUFFER;
4767 static WERROR getprinter_level_7(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4769 PRINTER_INFO_7 *printer=NULL;
4771 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4774 if (!construct_printer_info_7(printer, snum))
4777 /* check the required size. */
4778 *needed += spoolss_size_printer_info_7(printer);
4780 if (!alloc_buffer_size(buffer, *needed)) {
4781 free_printer_info_7(printer);
4782 return WERR_INSUFFICIENT_BUFFER;
4785 /* fill the buffer with the structures */
4786 smb_io_printer_info_7("", buffer, printer, 0);
4789 free_printer_info_7(printer);
4791 if (*needed > offered) {
4792 return WERR_INSUFFICIENT_BUFFER;
4798 /****************************************************************************
4799 ****************************************************************************/
4801 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4803 POLICY_HND *handle = &q_u->handle;
4804 uint32 level = q_u->level;
4805 NEW_BUFFER *buffer = NULL;
4806 uint32 offered = q_u->offered;
4807 uint32 *needed = &r_u->needed;
4811 /* that's an [in out] buffer */
4812 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4813 buffer = r_u->buffer;
4817 if (!get_printer_snum(p, handle, &snum))
4822 return getprinter_level_0(snum, buffer, offered, needed);
4824 return getprinter_level_1(snum, buffer, offered, needed);
4826 return getprinter_level_2(snum, buffer, offered, needed);
4828 return getprinter_level_3(snum, buffer, offered, needed);
4830 return getprinter_level_4(snum, buffer, offered, needed);
4832 return getprinter_level_5(snum, buffer, offered, needed);
4834 return getprinter_level_7(snum, buffer, offered, needed);
4836 return WERR_UNKNOWN_LEVEL;
4839 /********************************************************************
4840 * fill a DRIVER_INFO_1 struct
4841 ********************************************************************/
4843 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4845 init_unistr( &info->name, driver.info_3->name);
4848 /********************************************************************
4849 * construct_printer_driver_info_1
4850 ********************************************************************/
4852 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4854 NT_PRINTER_INFO_LEVEL *printer = NULL;
4855 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4857 ZERO_STRUCT(driver);
4859 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4860 return WERR_INVALID_PRINTER_NAME;
4862 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4863 return WERR_UNKNOWN_PRINTER_DRIVER;
4865 fill_printer_driver_info_1(info, driver, servername, architecture);
4867 free_a_printer(&printer,2);
4872 /********************************************************************
4873 * construct_printer_driver_info_2
4874 * fill a printer_info_2 struct
4875 ********************************************************************/
4877 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4881 info->version=driver.info_3->cversion;
4883 init_unistr( &info->name, driver.info_3->name );
4884 init_unistr( &info->architecture, driver.info_3->environment );
4887 if (strlen(driver.info_3->driverpath)) {
4888 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4889 init_unistr( &info->driverpath, temp );
4891 init_unistr( &info->driverpath, "" );
4893 if (strlen(driver.info_3->datafile)) {
4894 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4895 init_unistr( &info->datafile, temp );
4897 init_unistr( &info->datafile, "" );
4899 if (strlen(driver.info_3->configfile)) {
4900 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4901 init_unistr( &info->configfile, temp );
4903 init_unistr( &info->configfile, "" );
4906 /********************************************************************
4907 * construct_printer_driver_info_2
4908 * fill a printer_info_2 struct
4909 ********************************************************************/
4911 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4913 NT_PRINTER_INFO_LEVEL *printer = NULL;
4914 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4916 ZERO_STRUCT(printer);
4917 ZERO_STRUCT(driver);
4919 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4920 return WERR_INVALID_PRINTER_NAME;
4922 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4923 return WERR_UNKNOWN_PRINTER_DRIVER;
4925 fill_printer_driver_info_2(info, driver, servername);
4927 free_a_printer(&printer,2);
4932 /********************************************************************
4933 * copy a strings array and convert to UNICODE
4935 * convert an array of ascii string to a UNICODE string
4936 ********************************************************************/
4938 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
4946 DEBUG(6,("init_unistr_array\n"));
4957 v = ""; /* hack to handle null lists */
4960 /* hack to allow this to be used in places other than when generating
4961 the list of dependent files */
4964 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4968 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4970 /* add one extra unit16 for the second terminating NULL */
4972 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4973 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4981 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4986 /* special case for ""; we need to add both NULL's here */
4988 (*uni_array)[j++]=0x0000;
4989 (*uni_array)[j]=0x0000;
4992 DEBUGADD(6,("last one:done\n"));
4994 /* return size of array in uint16's */
4999 /********************************************************************
5000 * construct_printer_info_3
5001 * fill a printer_info_3 struct
5002 ********************************************************************/
5004 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5010 info->version=driver.info_3->cversion;
5012 init_unistr( &info->name, driver.info_3->name );
5013 init_unistr( &info->architecture, driver.info_3->environment );
5015 if (strlen(driver.info_3->driverpath)) {
5016 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5017 init_unistr( &info->driverpath, temp );
5019 init_unistr( &info->driverpath, "" );
5021 if (strlen(driver.info_3->datafile)) {
5022 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5023 init_unistr( &info->datafile, temp );
5025 init_unistr( &info->datafile, "" );
5027 if (strlen(driver.info_3->configfile)) {
5028 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5029 init_unistr( &info->configfile, temp );
5031 init_unistr( &info->configfile, "" );
5033 if (strlen(driver.info_3->helpfile)) {
5034 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5035 init_unistr( &info->helpfile, temp );
5037 init_unistr( &info->helpfile, "" );
5039 init_unistr( &info->monitorname, driver.info_3->monitorname );
5040 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5042 info->dependentfiles=NULL;
5043 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5046 /********************************************************************
5047 * construct_printer_info_3
5048 * fill a printer_info_3 struct
5049 ********************************************************************/
5051 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5053 NT_PRINTER_INFO_LEVEL *printer = NULL;
5054 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5056 ZERO_STRUCT(driver);
5058 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5059 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5060 if (!W_ERROR_IS_OK(status))
5061 return WERR_INVALID_PRINTER_NAME;
5063 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5064 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5069 * I put this code in during testing. Helpful when commenting out the
5070 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5071 * as win2k always queries the driver using an infor level of 6.
5072 * I've left it in (but ifdef'd out) because I'll probably
5073 * use it in experimentation again in the future. --jerry 22/01/2002
5076 if (!W_ERROR_IS_OK(status)) {
5078 * Is this a W2k client ?
5081 /* Yes - try again with a WinNT driver. */
5083 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5084 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5088 if (!W_ERROR_IS_OK(status)) {
5089 free_a_printer(&printer,2);
5090 return WERR_UNKNOWN_PRINTER_DRIVER;
5098 fill_printer_driver_info_3(info, driver, servername);
5100 free_a_printer(&printer,2);
5105 /********************************************************************
5106 * construct_printer_info_6
5107 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5108 ********************************************************************/
5110 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5116 memset(&nullstr, '\0', sizeof(fstring));
5118 info->version=driver.info_3->cversion;
5120 init_unistr( &info->name, driver.info_3->name );
5121 init_unistr( &info->architecture, driver.info_3->environment );
5123 if (strlen(driver.info_3->driverpath)) {
5124 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5125 init_unistr( &info->driverpath, temp );
5127 init_unistr( &info->driverpath, "" );
5129 if (strlen(driver.info_3->datafile)) {
5130 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5131 init_unistr( &info->datafile, temp );
5133 init_unistr( &info->datafile, "" );
5135 if (strlen(driver.info_3->configfile)) {
5136 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5137 init_unistr( &info->configfile, temp );
5139 init_unistr( &info->configfile, "" );
5141 if (strlen(driver.info_3->helpfile)) {
5142 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5143 init_unistr( &info->helpfile, temp );
5145 init_unistr( &info->helpfile, "" );
5147 init_unistr( &info->monitorname, driver.info_3->monitorname );
5148 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5150 info->dependentfiles = NULL;
5151 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5153 info->previousdrivernames=NULL;
5154 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5156 info->driver_date.low=0;
5157 info->driver_date.high=0;
5160 info->driver_version_low=0;
5161 info->driver_version_high=0;
5163 init_unistr( &info->mfgname, "");
5164 init_unistr( &info->oem_url, "");
5165 init_unistr( &info->hardware_id, "");
5166 init_unistr( &info->provider, "");
5169 /********************************************************************
5170 * construct_printer_info_6
5171 * fill a printer_info_6 struct
5172 ********************************************************************/
5174 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5175 fstring servername, fstring architecture, uint32 version)
5177 NT_PRINTER_INFO_LEVEL *printer = NULL;
5178 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5181 ZERO_STRUCT(driver);
5183 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5185 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5187 if (!W_ERROR_IS_OK(status))
5188 return WERR_INVALID_PRINTER_NAME;
5190 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5192 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5194 if (!W_ERROR_IS_OK(status))
5197 * Is this a W2k client ?
5201 free_a_printer(&printer,2);
5202 return WERR_UNKNOWN_PRINTER_DRIVER;
5205 /* Yes - try again with a WinNT driver. */
5207 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5208 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5209 if (!W_ERROR_IS_OK(status)) {
5210 free_a_printer(&printer,2);
5211 return WERR_UNKNOWN_PRINTER_DRIVER;
5215 fill_printer_driver_info_6(info, driver, servername);
5217 free_a_printer(&printer,2);
5218 free_a_printer_driver(driver, 3);
5223 /****************************************************************************
5224 ****************************************************************************/
5226 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5228 SAFE_FREE(info->dependentfiles);
5231 /****************************************************************************
5232 ****************************************************************************/
5234 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5236 SAFE_FREE(info->dependentfiles);
5240 /****************************************************************************
5241 ****************************************************************************/
5243 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5245 DRIVER_INFO_1 *info=NULL;
5248 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5251 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5252 if (!W_ERROR_IS_OK(status)) {
5257 /* check the required size. */
5258 *needed += spoolss_size_printer_driver_info_1(info);
5260 if (!alloc_buffer_size(buffer, *needed)) {
5262 return WERR_INSUFFICIENT_BUFFER;
5265 /* fill the buffer with the structures */
5266 smb_io_printer_driver_info_1("", buffer, info, 0);
5271 if (*needed > offered)
5272 return WERR_INSUFFICIENT_BUFFER;
5277 /****************************************************************************
5278 ****************************************************************************/
5280 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5282 DRIVER_INFO_2 *info=NULL;
5285 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5288 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5289 if (!W_ERROR_IS_OK(status)) {
5294 /* check the required size. */
5295 *needed += spoolss_size_printer_driver_info_2(info);
5297 if (!alloc_buffer_size(buffer, *needed)) {
5299 return WERR_INSUFFICIENT_BUFFER;
5302 /* fill the buffer with the structures */
5303 smb_io_printer_driver_info_2("", buffer, info, 0);
5308 if (*needed > offered)
5309 return WERR_INSUFFICIENT_BUFFER;
5314 /****************************************************************************
5315 ****************************************************************************/
5317 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5324 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5325 if (!W_ERROR_IS_OK(status)) {
5329 /* check the required size. */
5330 *needed += spoolss_size_printer_driver_info_3(&info);
5332 if (!alloc_buffer_size(buffer, *needed)) {
5333 free_printer_driver_info_3(&info);
5334 return WERR_INSUFFICIENT_BUFFER;
5337 /* fill the buffer with the structures */
5338 smb_io_printer_driver_info_3("", buffer, &info, 0);
5340 free_printer_driver_info_3(&info);
5342 if (*needed > offered)
5343 return WERR_INSUFFICIENT_BUFFER;
5348 /****************************************************************************
5349 ****************************************************************************/
5351 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5358 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5359 if (!W_ERROR_IS_OK(status)) {
5363 /* check the required size. */
5364 *needed += spoolss_size_printer_driver_info_6(&info);
5366 if (!alloc_buffer_size(buffer, *needed)) {
5367 free_printer_driver_info_6(&info);
5368 return WERR_INSUFFICIENT_BUFFER;
5371 /* fill the buffer with the structures */
5372 smb_io_printer_driver_info_6("", buffer, &info, 0);
5374 free_printer_driver_info_6(&info);
5376 if (*needed > offered)
5377 return WERR_INSUFFICIENT_BUFFER;
5382 /****************************************************************************
5383 ****************************************************************************/
5385 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5387 POLICY_HND *handle = &q_u->handle;
5388 UNISTR2 *uni_arch = &q_u->architecture;
5389 uint32 level = q_u->level;
5390 uint32 clientmajorversion = q_u->clientmajorversion;
5391 NEW_BUFFER *buffer = NULL;
5392 uint32 offered = q_u->offered;
5393 uint32 *needed = &r_u->needed;
5394 uint32 *servermajorversion = &r_u->servermajorversion;
5395 uint32 *serverminorversion = &r_u->serverminorversion;
5398 fstring architecture;
5401 /* that's an [in out] buffer */
5402 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5403 buffer = r_u->buffer;
5405 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5408 *servermajorversion = 0;
5409 *serverminorversion = 0;
5411 fstrcpy(servername, get_called_name());
5412 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5414 if (!get_printer_snum(p, handle, &snum))
5419 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5421 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5423 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5425 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5428 return WERR_UNKNOWN_LEVEL;
5431 /****************************************************************************
5432 ****************************************************************************/
5434 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5436 POLICY_HND *handle = &q_u->handle;
5438 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5441 DEBUG(3,("Error in startpageprinter printer handle\n"));
5445 Printer->page_started=True;
5449 /****************************************************************************
5450 ****************************************************************************/
5452 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5454 POLICY_HND *handle = &q_u->handle;
5457 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5460 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5464 if (!get_printer_snum(p, handle, &snum))
5467 Printer->page_started=False;
5468 print_job_endpage(snum, Printer->jobid);
5473 /********************************************************************
5474 * api_spoolss_getprinter
5475 * called from the spoolss dispatcher
5477 ********************************************************************/
5479 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5481 POLICY_HND *handle = &q_u->handle;
5482 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5483 uint32 *jobid = &r_u->jobid;
5485 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5489 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5490 struct current_user user;
5493 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5497 get_current_user(&user, p);
5500 * a nice thing with NT is it doesn't listen to what you tell it.
5501 * when asked to send _only_ RAW datas, it tries to send datas
5504 * So I add checks like in NT Server ...
5507 if (info_1->p_datatype != 0) {
5508 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5509 if (strcmp(datatype, "RAW") != 0) {
5511 return WERR_INVALID_DATATYPE;
5515 /* get the share number of the printer */
5516 if (!get_printer_snum(p, handle, &snum)) {
5520 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5522 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5524 /* An error occured in print_job_start() so return an appropriate
5527 if (Printer->jobid == -1) {
5528 return map_werror_from_unix(errno);
5531 Printer->document_started=True;
5532 (*jobid) = Printer->jobid;
5537 /********************************************************************
5538 * api_spoolss_getprinter
5539 * called from the spoolss dispatcher
5541 ********************************************************************/
5543 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5545 POLICY_HND *handle = &q_u->handle;
5547 return _spoolss_enddocprinter_internal(p, handle);
5550 /****************************************************************************
5551 ****************************************************************************/
5553 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5555 POLICY_HND *handle = &q_u->handle;
5556 uint32 buffer_size = q_u->buffer_size;
5557 uint8 *buffer = q_u->buffer;
5558 uint32 *buffer_written = &q_u->buffer_size2;
5560 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5563 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5564 r_u->buffer_written = q_u->buffer_size2;
5568 if (!get_printer_snum(p, handle, &snum))
5571 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5572 if (*buffer_written == -1) {
5573 r_u->buffer_written = 0;
5574 if (errno == ENOSPC)
5575 return WERR_NO_SPOOL_SPACE;
5577 return WERR_ACCESS_DENIED;
5580 r_u->buffer_written = q_u->buffer_size2;
5585 /********************************************************************
5586 * api_spoolss_getprinter
5587 * called from the spoolss dispatcher
5589 ********************************************************************/
5591 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5594 struct current_user user;
5596 WERROR errcode = WERR_BADFUNC;
5597 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5599 get_current_user(&user, p);
5602 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5606 if (!get_printer_snum(p, handle, &snum))
5610 case PRINTER_CONTROL_PAUSE:
5611 if (print_queue_pause(&user, snum, &errcode)) {
5615 case PRINTER_CONTROL_RESUME:
5616 case PRINTER_CONTROL_UNPAUSE:
5617 if (print_queue_resume(&user, snum, &errcode)) {
5621 case PRINTER_CONTROL_PURGE:
5622 if (print_queue_purge(&user, snum, &errcode)) {
5627 return WERR_UNKNOWN_LEVEL;
5633 /********************************************************************
5634 * api_spoolss_abortprinter
5635 * From MSDN: "Deletes printer's spool file if printer is configured
5637 ********************************************************************/
5639 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5641 POLICY_HND *handle = &q_u->handle;
5642 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5644 struct current_user user;
5645 WERROR errcode = WERR_OK;
5648 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5652 if (!get_printer_snum(p, handle, &snum))
5655 get_current_user( &user, p );
5657 print_job_delete( &user, snum, Printer->jobid, &errcode );
5662 /********************************************************************
5663 * called by spoolss_api_setprinter
5664 * when updating a printer description
5665 ********************************************************************/
5667 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5668 const SPOOL_PRINTER_INFO_LEVEL *info,
5669 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5671 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5672 struct current_user user;
5676 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5678 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5679 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5680 OUR_HANDLE(handle)));
5682 result = WERR_BADFID;
5686 /* NT seems to like setting the security descriptor even though
5687 nothing may have actually changed. This causes annoying
5688 dialog boxes when the user doesn't have permission to change
5689 the security descriptor. */
5691 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5693 if (DEBUGLEVEL >= 10) {
5697 the_acl = old_secdesc_ctr->sec->dacl;
5698 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5699 PRINTERNAME(snum), the_acl->num_aces));
5701 for (i = 0; i < the_acl->num_aces; i++) {
5704 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5706 DEBUG(10, ("%s 0x%08x\n", sid_str,
5707 the_acl->ace[i].info.mask));
5710 the_acl = secdesc_ctr->sec->dacl;
5713 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5714 PRINTERNAME(snum), the_acl->num_aces));
5716 for (i = 0; i < the_acl->num_aces; i++) {
5719 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5721 DEBUG(10, ("%s 0x%08x\n", sid_str,
5722 the_acl->ace[i].info.mask));
5725 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5729 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5731 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5736 /* Work out which user is performing the operation */
5738 get_current_user(&user, p);
5740 /* Check the user has permissions to change the security
5741 descriptor. By experimentation with two NT machines, the user
5742 requires Full Access to the printer to change security
5745 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5746 result = WERR_ACCESS_DENIED;
5750 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5757 /********************************************************************
5758 Do Samba sanity checks on a printer info struct.
5759 this has changed purpose: it now "canonicalises" printer
5760 info from a client rather than just checking it is correct
5761 ********************************************************************/
5763 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5765 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5766 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5768 /* we force some elements to "correct" values */
5769 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5770 fstrcpy(info->sharename, lp_servicename(snum));
5771 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5772 get_called_name(), info->sharename);
5773 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5778 /****************************************************************************
5779 ****************************************************************************/
5781 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5783 extern userdom_struct current_user_info;
5784 char *cmd = lp_addprinter_cmd();
5790 fstring remote_machine = "%m";
5792 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5794 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5795 cmd, printer->info_2->printername, printer->info_2->sharename,
5796 printer->info_2->portname, printer->info_2->drivername,
5797 printer->info_2->location, printer->info_2->comment, remote_machine);
5799 DEBUG(10,("Running [%s]\n", command));
5800 ret = smbrun(command, &fd);
5801 DEBUGADD(10,("returned [%d]\n", ret));
5810 /* Get lines and convert them back to dos-codepage */
5811 qlines = fd_lines_load(fd, &numlines);
5812 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5816 /* Set the portname to what the script says the portname should be. */
5817 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5818 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5820 /* Send SIGHUP to process group... is there a better way? */
5823 /* reload our services immediately */
5824 reload_services( False );
5827 file_lines_free(qlines);
5831 /********************************************************************
5832 * Called by spoolss_api_setprinter
5833 * when updating a printer description.
5834 ********************************************************************/
5836 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5837 const SPOOL_PRINTER_INFO_LEVEL *info,
5838 DEVICEMODE *devmode)
5841 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5842 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5845 DEBUG(8,("update_printer\n"));
5850 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5851 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5852 result = WERR_UNKNOWN_LEVEL;
5857 result = WERR_BADFID;
5861 if (!get_printer_snum(p, handle, &snum)) {
5862 result = WERR_BADFID;
5866 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5867 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5868 result = WERR_BADFID;
5872 DEBUGADD(8,("Converting info_2 struct\n"));
5875 * convert_printer_info converts the incoming
5876 * info from the client and overwrites the info
5877 * just read from the tdb in the pointer 'printer'.
5880 if (!convert_printer_info(info, printer, level)) {
5881 result = WERR_NOMEM;
5886 /* we have a valid devmode
5887 convert it and link it*/
5889 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5890 if (!convert_devicemode(printer->info_2->printername, devmode,
5891 &printer->info_2->devmode)) {
5892 result = WERR_NOMEM;
5897 * make sure we actually reload the services after
5898 * this as smb.conf could have a new section in it
5899 * .... shouldn't .... but could
5901 reload_services(False);
5904 /* Do sanity check on the requested changes for Samba */
5906 if (!check_printer_ok(printer->info_2, snum)) {
5907 result = WERR_INVALID_PARAM;
5911 /* Check calling user has permission to update printer description */
5913 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5914 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5915 result = WERR_ACCESS_DENIED;
5919 /* Call addprinter hook */
5920 /* Check changes to see if this is really needed */
5922 if ( *lp_addprinter_cmd()
5923 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5924 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5925 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5926 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5928 if ( !add_printer_hook(printer) ) {
5929 result = WERR_ACCESS_DENIED;
5935 * When a *new* driver is bound to a printer, the drivername is used to
5936 * lookup previously saved driver initialization info, which is then
5937 * bound to the printer, simulating what happens in the Windows arch.
5939 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5941 if (!set_driver_init(printer, 2))
5943 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5944 printer->info_2->drivername));
5947 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5948 printer->info_2->drivername));
5950 notify_printer_driver(snum, printer->info_2->drivername);
5953 /* Update printer info */
5954 result = mod_a_printer(*printer, 2);
5956 /* flag which changes actually occured. This is a small subset of
5957 all the possible changes */
5959 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5960 notify_printer_comment(snum, printer->info_2->comment);
5962 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5963 notify_printer_sharename(snum, printer->info_2->sharename);
5965 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5966 notify_printer_port(snum, printer->info_2->portname);
5968 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5969 notify_printer_location(snum, printer->info_2->location);
5972 free_a_printer(&printer, 2);
5973 free_a_printer(&old_printer, 2);
5979 /****************************************************************************
5980 ****************************************************************************/
5981 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
5982 const SPOOL_PRINTER_INFO_LEVEL *info)
5985 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
5987 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5990 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5997 if (!get_printer_snum(p, handle, &snum))
6000 nt_printer_publish(snum, info7->action);
6004 return WERR_UNKNOWN_LEVEL;
6007 /****************************************************************************
6008 ****************************************************************************/
6010 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6012 POLICY_HND *handle = &q_u->handle;
6013 uint32 level = q_u->level;
6014 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6015 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6016 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6017 uint32 command = q_u->command;
6019 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6022 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6026 /* check the level */
6029 return control_printer(handle, command, p);
6031 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6033 return update_printer_sec(handle, level, info, p,
6036 return publish_or_unpublish_printer(p, handle, info);
6038 return WERR_UNKNOWN_LEVEL;
6042 /****************************************************************************
6043 ****************************************************************************/
6045 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6047 POLICY_HND *handle = &q_u->handle;
6048 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6051 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6055 if (Printer->notify.client_connected==True) {
6058 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6060 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6061 !get_printer_snum(p, handle, &snum) )
6064 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6067 Printer->notify.flags=0;
6068 Printer->notify.options=0;
6069 Printer->notify.localmachine[0]='\0';
6070 Printer->notify.printerlocal=0;
6071 if (Printer->notify.option)
6072 free_spool_notify_option(&Printer->notify.option);
6073 Printer->notify.client_connected=False;
6078 /****************************************************************************
6079 ****************************************************************************/
6081 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6083 /* that's an [in out] buffer (despite appearences to the contrary) */
6084 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6087 return WERR_INVALID_PARAM; /* this is what a NT server
6088 returns for AddJob. AddJob
6089 must fail on non-local
6093 /****************************************************************************
6094 ****************************************************************************/
6096 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6097 int position, int snum)
6103 t=gmtime(&queue->time);
6104 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6106 job_info->jobid=queue->job;
6107 init_unistr(&job_info->printername, lp_servicename(snum));
6108 init_unistr(&job_info->machinename, temp_name);
6109 init_unistr(&job_info->username, queue->fs_user);
6110 init_unistr(&job_info->document, queue->fs_file);
6111 init_unistr(&job_info->datatype, "RAW");
6112 init_unistr(&job_info->text_status, "");
6113 job_info->status=nt_printj_status(queue->status);
6114 job_info->priority=queue->priority;
6115 job_info->position=position;
6116 job_info->totalpages=queue->page_count;
6117 job_info->pagesprinted=0;
6119 make_systemtime(&job_info->submitted, t);
6122 /****************************************************************************
6123 ****************************************************************************/
6125 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6126 int position, int snum,
6127 NT_PRINTER_INFO_LEVEL *ntprinter,
6128 DEVICEMODE *devmode)
6133 t=gmtime(&queue->time);
6134 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6136 job_info->jobid=queue->job;
6138 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6140 init_unistr(&job_info->machinename, temp_name);
6141 init_unistr(&job_info->username, queue->fs_user);
6142 init_unistr(&job_info->document, queue->fs_file);
6143 init_unistr(&job_info->notifyname, queue->fs_user);
6144 init_unistr(&job_info->datatype, "RAW");
6145 init_unistr(&job_info->printprocessor, "winprint");
6146 init_unistr(&job_info->parameters, "");
6147 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6148 init_unistr(&job_info->text_status, "");
6150 /* and here the security descriptor */
6152 job_info->status=nt_printj_status(queue->status);
6153 job_info->priority=queue->priority;
6154 job_info->position=position;
6155 job_info->starttime=0;
6156 job_info->untiltime=0;
6157 job_info->totalpages=queue->page_count;
6158 job_info->size=queue->size;
6159 make_systemtime(&(job_info->submitted), t);
6160 job_info->timeelapsed=0;
6161 job_info->pagesprinted=0;
6163 job_info->devmode = devmode;
6168 /****************************************************************************
6169 Enumjobs at level 1.
6170 ****************************************************************************/
6172 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6173 NEW_BUFFER *buffer, uint32 offered,
6174 uint32 *needed, uint32 *returned)
6179 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6186 for (i=0; i<*returned; i++)
6187 fill_job_info_1(&info[i], &queue[i], i, snum);
6191 /* check the required size. */
6192 for (i=0; i<*returned; i++)
6193 (*needed) += spoolss_size_job_info_1(&info[i]);
6195 if (!alloc_buffer_size(buffer, *needed)) {
6197 return WERR_INSUFFICIENT_BUFFER;
6200 /* fill the buffer with the structures */
6201 for (i=0; i<*returned; i++)
6202 smb_io_job_info_1("", buffer, &info[i], 0);
6207 if (*needed > offered) {
6209 return WERR_INSUFFICIENT_BUFFER;
6215 /****************************************************************************
6216 Enumjobs at level 2.
6217 ****************************************************************************/
6219 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6220 NEW_BUFFER *buffer, uint32 offered,
6221 uint32 *needed, uint32 *returned)
6223 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6224 JOB_INFO_2 *info = NULL;
6227 DEVICEMODE *devmode = NULL;
6229 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6232 result = WERR_NOMEM;
6236 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6237 if (!W_ERROR_IS_OK(result)) {
6242 /* this should not be a failure condition if the devmode is NULL */
6244 devmode = construct_dev_mode(snum);
6246 for (i=0; i<*returned; i++)
6247 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6250 free_a_printer(&ntprinter, 2);
6253 /* check the required size. */
6254 for (i=0; i<*returned; i++)
6255 (*needed) += spoolss_size_job_info_2(&info[i]);
6257 if (*needed > offered) {
6259 result = WERR_INSUFFICIENT_BUFFER;
6263 if (!alloc_buffer_size(buffer, *needed)) {
6265 result = WERR_INSUFFICIENT_BUFFER;
6269 /* fill the buffer with the structures */
6270 for (i=0; i<*returned; i++)
6271 smb_io_job_info_2("", buffer, &info[i], 0);
6276 free_a_printer(&ntprinter, 2);
6277 free_devmode(devmode);
6285 /****************************************************************************
6287 ****************************************************************************/
6289 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6291 POLICY_HND *handle = &q_u->handle;
6292 uint32 level = q_u->level;
6293 NEW_BUFFER *buffer = NULL;
6294 uint32 offered = q_u->offered;
6295 uint32 *needed = &r_u->needed;
6296 uint32 *returned = &r_u->returned;
6299 print_status_struct prt_status;
6300 print_queue_struct *queue=NULL;
6302 /* that's an [in out] buffer */
6303 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6304 buffer = r_u->buffer;
6306 DEBUG(4,("_spoolss_enumjobs\n"));
6311 if (!get_printer_snum(p, handle, &snum))
6314 *returned = print_queue_status(snum, &queue, &prt_status);
6315 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6317 if (*returned == 0) {
6324 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6326 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6330 return WERR_UNKNOWN_LEVEL;
6334 /****************************************************************************
6335 ****************************************************************************/
6337 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6342 /****************************************************************************
6343 ****************************************************************************/
6345 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6347 POLICY_HND *handle = &q_u->handle;
6348 uint32 jobid = q_u->jobid;
6349 uint32 command = q_u->command;
6351 struct current_user user;
6353 WERROR errcode = WERR_BADFUNC;
6355 if (!get_printer_snum(p, handle, &snum)) {
6359 if (!print_job_exists(snum, jobid)) {
6360 return WERR_INVALID_PRINTER_NAME;
6363 get_current_user(&user, p);
6366 case JOB_CONTROL_CANCEL:
6367 case JOB_CONTROL_DELETE:
6368 if (print_job_delete(&user, snum, jobid, &errcode)) {
6372 case JOB_CONTROL_PAUSE:
6373 if (print_job_pause(&user, snum, jobid, &errcode)) {
6377 case JOB_CONTROL_RESTART:
6378 case JOB_CONTROL_RESUME:
6379 if (print_job_resume(&user, snum, jobid, &errcode)) {
6384 return WERR_UNKNOWN_LEVEL;
6390 /****************************************************************************
6391 Enumerates all printer drivers at level 1.
6392 ****************************************************************************/
6394 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6399 fstring *list = NULL;
6401 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6402 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6406 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6408 ndrivers=get_ntdrivers(&list, architecture, version);
6409 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6415 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6416 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6417 SAFE_FREE(driver_info_1);
6421 else driver_info_1 = tdi1;
6424 for (i=0; i<ndrivers; i++) {
6426 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6427 ZERO_STRUCT(driver);
6428 status = get_a_printer_driver(&driver, 3, list[i],
6429 architecture, version);
6430 if (!W_ERROR_IS_OK(status)) {
6434 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6435 free_a_printer_driver(driver, 3);
6438 *returned+=ndrivers;
6442 /* check the required size. */
6443 for (i=0; i<*returned; i++) {
6444 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6445 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6448 if (!alloc_buffer_size(buffer, *needed)) {
6449 SAFE_FREE(driver_info_1);
6450 return WERR_INSUFFICIENT_BUFFER;
6453 /* fill the buffer with the driver structures */
6454 for (i=0; i<*returned; i++) {
6455 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6456 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6459 SAFE_FREE(driver_info_1);
6461 if (*needed > offered) {
6463 return WERR_INSUFFICIENT_BUFFER;
6469 /****************************************************************************
6470 Enumerates all printer drivers at level 2.
6471 ****************************************************************************/
6473 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6478 fstring *list = NULL;
6480 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6481 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6485 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6487 ndrivers=get_ntdrivers(&list, architecture, version);
6488 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6494 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6495 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6496 SAFE_FREE(driver_info_2);
6500 else driver_info_2 = tdi2;
6503 for (i=0; i<ndrivers; i++) {
6506 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6507 ZERO_STRUCT(driver);
6508 status = get_a_printer_driver(&driver, 3, list[i],
6509 architecture, version);
6510 if (!W_ERROR_IS_OK(status)) {
6514 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6515 free_a_printer_driver(driver, 3);
6518 *returned+=ndrivers;
6522 /* check the required size. */
6523 for (i=0; i<*returned; i++) {
6524 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6525 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6528 if (!alloc_buffer_size(buffer, *needed)) {
6529 SAFE_FREE(driver_info_2);
6530 return WERR_INSUFFICIENT_BUFFER;
6533 /* fill the buffer with the form structures */
6534 for (i=0; i<*returned; i++) {
6535 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6536 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6539 SAFE_FREE(driver_info_2);
6541 if (*needed > offered) {
6543 return WERR_INSUFFICIENT_BUFFER;
6549 /****************************************************************************
6550 Enumerates all printer drivers at level 3.
6551 ****************************************************************************/
6553 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6558 fstring *list = NULL;
6560 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6561 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6565 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6567 ndrivers=get_ntdrivers(&list, architecture, version);
6568 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6574 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6575 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6576 SAFE_FREE(driver_info_3);
6580 else driver_info_3 = tdi3;
6583 for (i=0; i<ndrivers; i++) {
6586 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6587 ZERO_STRUCT(driver);
6588 status = get_a_printer_driver(&driver, 3, list[i],
6589 architecture, version);
6590 if (!W_ERROR_IS_OK(status)) {
6594 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6595 free_a_printer_driver(driver, 3);
6598 *returned+=ndrivers;
6602 /* check the required size. */
6603 for (i=0; i<*returned; i++) {
6604 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6605 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6608 if (!alloc_buffer_size(buffer, *needed)) {
6609 SAFE_FREE(driver_info_3);
6610 return WERR_INSUFFICIENT_BUFFER;
6613 /* fill the buffer with the driver structures */
6614 for (i=0; i<*returned; i++) {
6615 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6616 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6619 for (i=0; i<*returned; i++)
6620 SAFE_FREE(driver_info_3[i].dependentfiles);
6622 SAFE_FREE(driver_info_3);
6624 if (*needed > offered) {
6626 return WERR_INSUFFICIENT_BUFFER;
6632 /****************************************************************************
6633 Enumerates all printer drivers.
6634 ****************************************************************************/
6636 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6638 UNISTR2 *environment = &q_u->environment;
6639 uint32 level = q_u->level;
6640 NEW_BUFFER *buffer = NULL;
6641 uint32 offered = q_u->offered;
6642 uint32 *needed = &r_u->needed;
6643 uint32 *returned = &r_u->returned;
6645 fstring *list = NULL;
6647 fstring architecture;
6649 /* that's an [in out] buffer */
6650 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6651 buffer = r_u->buffer;
6653 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6654 fstrcpy(servername, get_called_name());
6658 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6662 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6664 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6666 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6670 return WERR_UNKNOWN_LEVEL;
6674 /****************************************************************************
6675 ****************************************************************************/
6677 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6679 form->flag=list->flag;
6680 init_unistr(&form->name, list->name);
6681 form->width=list->width;
6682 form->length=list->length;
6683 form->left=list->left;
6684 form->top=list->top;
6685 form->right=list->right;
6686 form->bottom=list->bottom;
6689 /****************************************************************************
6690 ****************************************************************************/
6692 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6694 uint32 level = q_u->level;
6695 NEW_BUFFER *buffer = NULL;
6696 uint32 offered = q_u->offered;
6697 uint32 *needed = &r_u->needed;
6698 uint32 *numofforms = &r_u->numofforms;
6699 uint32 numbuiltinforms;
6701 nt_forms_struct *list=NULL;
6702 nt_forms_struct *builtinlist=NULL;
6707 /* that's an [in out] buffer */
6708 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6709 buffer = r_u->buffer;
6711 DEBUG(4,("_spoolss_enumforms\n"));
6712 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6713 DEBUGADD(5,("Info level [%d]\n", level));
6715 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6716 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6717 *numofforms = get_ntforms(&list);
6718 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6719 *numofforms += numbuiltinforms;
6721 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6725 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6730 /* construct the list of form structures */
6731 for (i=0; i<numbuiltinforms; i++) {
6732 DEBUGADD(6,("Filling form number [%d]\n",i));
6733 fill_form_1(&forms_1[i], &builtinlist[i]);
6736 SAFE_FREE(builtinlist);
6738 for (; i<*numofforms; i++) {
6739 DEBUGADD(6,("Filling form number [%d]\n",i));
6740 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6745 /* check the required size. */
6746 for (i=0; i<numbuiltinforms; i++) {
6747 DEBUGADD(6,("adding form [%d]'s size\n",i));
6748 buffer_size += spoolss_size_form_1(&forms_1[i]);
6750 for (; i<*numofforms; i++) {
6751 DEBUGADD(6,("adding form [%d]'s size\n",i));
6752 buffer_size += spoolss_size_form_1(&forms_1[i]);
6755 *needed=buffer_size;
6757 if (!alloc_buffer_size(buffer, buffer_size)){
6759 return WERR_INSUFFICIENT_BUFFER;
6762 /* fill the buffer with the form structures */
6763 for (i=0; i<numbuiltinforms; i++) {
6764 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6765 smb_io_form_1("", buffer, &forms_1[i], 0);
6767 for (; i<*numofforms; i++) {
6768 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6769 smb_io_form_1("", buffer, &forms_1[i], 0);
6774 if (*needed > offered) {
6776 return WERR_INSUFFICIENT_BUFFER;
6783 SAFE_FREE(builtinlist);
6784 return WERR_UNKNOWN_LEVEL;
6789 /****************************************************************************
6790 ****************************************************************************/
6792 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6794 uint32 level = q_u->level;
6795 UNISTR2 *uni_formname = &q_u->formname;
6796 NEW_BUFFER *buffer = NULL;
6797 uint32 offered = q_u->offered;
6798 uint32 *needed = &r_u->needed;
6800 nt_forms_struct *list=NULL;
6801 nt_forms_struct builtin_form;
6806 int numofforms=0, i=0;
6808 /* that's an [in out] buffer */
6809 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6810 buffer = r_u->buffer;
6812 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6814 DEBUG(4,("_spoolss_getform\n"));
6815 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6816 DEBUGADD(5,("Info level [%d]\n", level));
6818 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6819 if (!foundBuiltin) {
6820 numofforms = get_ntforms(&list);
6821 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6823 if (numofforms == 0)
6830 fill_form_1(&form_1, &builtin_form);
6833 /* Check if the requested name is in the list of form structures */
6834 for (i=0; i<numofforms; i++) {
6836 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6838 if (strequal(form_name, list[i].name)) {
6839 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6840 fill_form_1(&form_1, &list[i]);
6846 if (i == numofforms) {
6850 /* check the required size. */
6852 *needed=spoolss_size_form_1(&form_1);
6854 if (!alloc_buffer_size(buffer, buffer_size)){
6855 return WERR_INSUFFICIENT_BUFFER;
6858 if (*needed > offered) {
6859 return WERR_INSUFFICIENT_BUFFER;
6862 /* fill the buffer with the form structures */
6863 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6864 smb_io_form_1("", buffer, &form_1, 0);
6870 return WERR_UNKNOWN_LEVEL;
6874 /****************************************************************************
6875 ****************************************************************************/
6877 static void fill_port_1(PORT_INFO_1 *port, const char *name)
6879 init_unistr(&port->port_name, name);
6882 /****************************************************************************
6883 ****************************************************************************/
6885 static void fill_port_2(PORT_INFO_2 *port, const char *name)
6887 init_unistr(&port->port_name, name);
6888 init_unistr(&port->monitor_name, "Local Monitor");
6889 init_unistr(&port->description, "Local Port");
6890 #define PORT_TYPE_WRITE 1
6891 port->port_type=PORT_TYPE_WRITE;
6895 /****************************************************************************
6897 ****************************************************************************/
6899 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6901 PORT_INFO_1 *ports=NULL;
6904 if (*lp_enumports_cmd()) {
6905 char *cmd = lp_enumports_cmd();
6912 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6914 DEBUG(10,("Running [%s]\n", command));
6915 ret = smbrun(command, &fd);
6916 DEBUG(10,("Returned [%d]\n", ret));
6920 /* Is this the best error to return here? */
6921 return WERR_ACCESS_DENIED;
6925 qlines = fd_lines_load(fd, &numlines);
6926 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6930 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6931 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6932 dos_errstr(WERR_NOMEM)));
6933 file_lines_free(qlines);
6937 for (i=0; i<numlines; i++) {
6938 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6939 fill_port_1(&ports[i], qlines[i]);
6942 file_lines_free(qlines);
6945 *returned = numlines;
6948 *returned = 1; /* Sole Samba port returned. */
6950 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6953 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6955 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6958 /* check the required size. */
6959 for (i=0; i<*returned; i++) {
6960 DEBUGADD(6,("adding port [%d]'s size\n", i));
6961 *needed += spoolss_size_port_info_1(&ports[i]);
6964 if (!alloc_buffer_size(buffer, *needed)) {
6966 return WERR_INSUFFICIENT_BUFFER;
6969 /* fill the buffer with the ports structures */
6970 for (i=0; i<*returned; i++) {
6971 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6972 smb_io_port_1("", buffer, &ports[i], 0);
6977 if (*needed > offered) {
6979 return WERR_INSUFFICIENT_BUFFER;
6985 /****************************************************************************
6987 ****************************************************************************/
6989 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6991 PORT_INFO_2 *ports=NULL;
6994 if (*lp_enumports_cmd()) {
6995 char *cmd = lp_enumports_cmd();
7004 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7005 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7007 path = lp_lockdir();
7009 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7010 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7013 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7014 ret = smbrun(command, &fd);
7015 DEBUGADD(10,("returned [%d]\n", ret));
7019 /* Is this the best error to return here? */
7020 return WERR_ACCESS_DENIED;
7024 qlines = fd_lines_load(fd, &numlines);
7025 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7029 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7030 file_lines_free(qlines);
7034 for (i=0; i<numlines; i++) {
7035 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7036 fill_port_2(&(ports[i]), qlines[i]);
7039 file_lines_free(qlines);
7042 *returned = numlines;
7048 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7051 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7053 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7056 /* check the required size. */
7057 for (i=0; i<*returned; i++) {
7058 DEBUGADD(6,("adding port [%d]'s size\n", i));
7059 *needed += spoolss_size_port_info_2(&ports[i]);
7062 if (!alloc_buffer_size(buffer, *needed)) {
7064 return WERR_INSUFFICIENT_BUFFER;
7067 /* fill the buffer with the ports structures */
7068 for (i=0; i<*returned; i++) {
7069 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7070 smb_io_port_2("", buffer, &ports[i], 0);
7075 if (*needed > offered) {
7077 return WERR_INSUFFICIENT_BUFFER;
7083 /****************************************************************************
7085 ****************************************************************************/
7087 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7089 uint32 level = q_u->level;
7090 NEW_BUFFER *buffer = NULL;
7091 uint32 offered = q_u->offered;
7092 uint32 *needed = &r_u->needed;
7093 uint32 *returned = &r_u->returned;
7095 /* that's an [in out] buffer */
7096 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7097 buffer = r_u->buffer;
7099 DEBUG(4,("_spoolss_enumports\n"));
7106 return enumports_level_1(buffer, offered, needed, returned);
7108 return enumports_level_2(buffer, offered, needed, returned);
7110 return WERR_UNKNOWN_LEVEL;
7114 /****************************************************************************
7115 ****************************************************************************/
7117 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7118 const SPOOL_PRINTER_INFO_LEVEL *info,
7119 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7120 uint32 user_switch, const SPOOL_USER_CTR *user,
7123 NT_PRINTER_INFO_LEVEL *printer = NULL;
7126 WERROR err = WERR_OK;
7128 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7129 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7133 ZERO_STRUCTP(printer);
7135 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7136 if (!convert_printer_info(info, printer, 2)) {
7137 free_a_printer(&printer, 2);
7141 /* check to see if the printer already exists */
7143 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7144 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7145 printer->info_2->sharename));
7146 free_a_printer(&printer, 2);
7147 return WERR_PRINTER_ALREADY_EXISTS;
7150 if (*lp_addprinter_cmd() ) {
7151 if ( !add_printer_hook(printer) ) {
7152 free_a_printer(&printer,2);
7153 return WERR_ACCESS_DENIED;
7157 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7158 printer->info_2->sharename);
7161 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7162 free_a_printer(&printer,2);
7163 return WERR_ACCESS_DENIED;
7166 /* you must be a printer admin to add a new printer */
7167 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7168 free_a_printer(&printer,2);
7169 return WERR_ACCESS_DENIED;
7173 * Do sanity check on the requested changes for Samba.
7176 if (!check_printer_ok(printer->info_2, snum)) {
7177 free_a_printer(&printer,2);
7178 return WERR_INVALID_PARAM;
7182 * When a printer is created, the drivername bound to the printer is used
7183 * to lookup previously saved driver initialization info, which is then
7184 * bound to the new printer, simulating what happens in the Windows arch.
7189 set_driver_init(printer, 2);
7193 /* A valid devmode was included, convert and link it
7195 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7197 if (!convert_devicemode(printer->info_2->printername, devmode,
7198 &printer->info_2->devmode))
7202 /* write the ASCII on disk */
7203 err = mod_a_printer(*printer, 2);
7204 if (!W_ERROR_IS_OK(err)) {
7205 free_a_printer(&printer,2);
7209 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7210 /* Handle open failed - remove addition. */
7211 del_a_printer(printer->info_2->sharename);
7212 free_a_printer(&printer,2);
7213 return WERR_ACCESS_DENIED;
7216 update_c_setprinter(False);
7217 free_a_printer(&printer,2);
7222 /****************************************************************************
7223 ****************************************************************************/
7225 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7227 UNISTR2 *uni_srv_name = &q_u->server_name;
7228 uint32 level = q_u->level;
7229 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7230 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7231 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7232 uint32 user_switch = q_u->user_switch;
7233 SPOOL_USER_CTR *user = &q_u->user_ctr;
7234 POLICY_HND *handle = &r_u->handle;
7238 /* we don't handle yet */
7239 /* but I know what to do ... */
7240 return WERR_UNKNOWN_LEVEL;
7242 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7244 user_switch, user, handle);
7246 return WERR_UNKNOWN_LEVEL;
7250 /****************************************************************************
7251 ****************************************************************************/
7253 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7255 uint32 level = q_u->level;
7256 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7257 WERROR err = WERR_OK;
7258 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7259 struct current_user user;
7260 fstring driver_name;
7263 ZERO_STRUCT(driver);
7265 get_current_user(&user, p);
7267 if (!convert_printer_driver_info(info, &driver, level)) {
7272 DEBUG(5,("Cleaning driver's information\n"));
7273 err = clean_up_driver_struct(driver, level, &user);
7274 if (!W_ERROR_IS_OK(err))
7277 DEBUG(5,("Moving driver to final destination\n"));
7278 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7279 if (W_ERROR_IS_OK(err))
7280 err = WERR_ACCESS_DENIED;
7284 if (add_a_printer_driver(driver, level)!=0) {
7285 err = WERR_ACCESS_DENIED;
7289 /* BEGIN_ADMIN_LOG */
7292 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7293 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7294 fstrcpy(driver_name, driver.info_3->name);
7297 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7298 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7299 fstrcpy(driver_name, driver.info_6->name);
7305 * I think this is where he DrvUpgradePrinter() hook would be
7306 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7307 * server. Right now, we just need to send ourselves a message
7308 * to update each printer bound to this driver. --jerry
7311 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7312 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7317 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7318 * decide if the driver init data should be deleted. The rules are:
7319 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7320 * 2) delete init data only if there is no 2k/Xp driver
7321 * 3) always delete init data
7322 * The generalized rule is always use init data from the highest order driver.
7323 * It is necessary to follow the driver install by an initialization step to
7324 * finish off this process.
7327 version = driver.info_3->cversion;
7328 else if (level == 6)
7329 version = driver.info_6->version;
7334 * 9x printer driver - never delete init data
7337 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7342 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7343 * there is no 2k/Xp driver init data for this driver name.
7347 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7349 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7351 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7353 if (!del_driver_init(driver_name))
7354 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7357 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7359 free_a_printer_driver(driver1,3);
7360 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7367 * 2k or Xp printer driver - always delete init data
7370 if (!del_driver_init(driver_name))
7371 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7375 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7381 free_a_printer_driver(driver, level);
7385 /********************************************************************
7386 * spoolss_addprinterdriverex
7387 ********************************************************************/
7389 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7391 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7392 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7395 * we only support the semantics of AddPrinterDriver()
7396 * i.e. only copy files that are newer than existing ones
7399 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7400 return WERR_ACCESS_DENIED;
7402 ZERO_STRUCT(q_u_local);
7403 ZERO_STRUCT(r_u_local);
7405 /* just pass the information off to _spoolss_addprinterdriver() */
7406 q_u_local.server_name_ptr = q_u->server_name_ptr;
7407 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7408 q_u_local.level = q_u->level;
7409 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7411 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7414 /****************************************************************************
7415 ****************************************************************************/
7417 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7419 init_unistr(&info->name, name);
7422 /****************************************************************************
7423 ****************************************************************************/
7425 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7429 pstring short_archi;
7430 DRIVER_DIRECTORY_1 *info=NULL;
7432 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7434 if (get_short_archi(short_archi, long_archi)==False)
7435 return WERR_INVALID_ENVIRONMENT;
7437 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7440 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7442 DEBUG(4,("printer driver directory: [%s]\n", path));
7444 fill_driverdir_1(info, path);
7446 *needed += spoolss_size_driverdir_info_1(info);
7448 if (!alloc_buffer_size(buffer, *needed)) {
7450 return WERR_INSUFFICIENT_BUFFER;
7453 smb_io_driverdir_1("", buffer, info, 0);
7457 if (*needed > offered)
7458 return WERR_INSUFFICIENT_BUFFER;
7463 /****************************************************************************
7464 ****************************************************************************/
7466 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7468 UNISTR2 *name = &q_u->name;
7469 UNISTR2 *uni_environment = &q_u->environment;
7470 uint32 level = q_u->level;
7471 NEW_BUFFER *buffer = NULL;
7472 uint32 offered = q_u->offered;
7473 uint32 *needed = &r_u->needed;
7475 /* that's an [in out] buffer */
7476 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7477 buffer = r_u->buffer;
7479 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7485 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7487 return WERR_UNKNOWN_LEVEL;
7491 /****************************************************************************
7492 ****************************************************************************/
7494 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7496 POLICY_HND *handle = &q_u->handle;
7497 uint32 idx = q_u->index;
7498 uint32 in_value_len = q_u->valuesize;
7499 uint32 in_data_len = q_u->datasize;
7500 uint32 *out_max_value_len = &r_u->valuesize;
7501 uint16 **out_value = &r_u->value;
7502 uint32 *out_value_len = &r_u->realvaluesize;
7503 uint32 *out_type = &r_u->type;
7504 uint32 *out_max_data_len = &r_u->datasize;
7505 uint8 **data_out = &r_u->data;
7506 uint32 *out_data_len = &r_u->realdatasize;
7508 NT_PRINTER_INFO_LEVEL *printer = NULL;
7511 uint32 biggest_valuesize;
7512 uint32 biggest_datasize;
7514 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7517 REGISTRY_VALUE *val;
7518 NT_PRINTER_DATA *p_data;
7519 int i, key_index, num_values;
7522 ZERO_STRUCT( printer );
7526 *out_max_data_len = 0;
7530 DEBUG(5,("spoolss_enumprinterdata\n"));
7533 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7537 if (!get_printer_snum(p,handle, &snum))
7540 result = get_a_printer(&printer, 2, lp_servicename(snum));
7541 if (!W_ERROR_IS_OK(result))
7544 p_data = &printer->info_2->data;
7545 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7550 * The NT machine wants to know the biggest size of value and data
7552 * cf: MSDN EnumPrinterData remark section
7555 if ( !in_value_len && !in_data_len )
7557 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7560 biggest_valuesize = 0;
7561 biggest_datasize = 0;
7563 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7565 for ( i=0; i<num_values; i++ )
7567 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7569 name_length = strlen(val->valuename);
7570 if ( strlen(val->valuename) > biggest_valuesize )
7571 biggest_valuesize = name_length;
7573 if ( val->size > biggest_datasize )
7574 biggest_datasize = val->size;
7576 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7580 /* the value is an UNICODE string but real_value_size is the length
7581 in bytes including the trailing 0 */
7583 *out_value_len = 2 * (1+biggest_valuesize);
7584 *out_data_len = biggest_datasize;
7586 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7592 * the value len is wrong in NT sp3
7593 * that's the number of bytes not the number of unicode chars
7596 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7601 /* out_value should default to "" or else NT4 has
7602 problems unmarshalling the response */
7604 *out_max_value_len = (in_value_len/sizeof(uint16));
7606 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7608 result = WERR_NOMEM;
7612 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7614 /* the data is counted in bytes */
7616 *out_max_data_len = in_data_len;
7617 *out_data_len = in_data_len;
7619 /* only allocate when given a non-zero data_len */
7621 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7623 result = WERR_NOMEM;
7627 result = WERR_NO_MORE_ITEMS;
7633 * - counted in bytes in the request
7634 * - counted in UNICODE chars in the max reply
7635 * - counted in bytes in the real size
7637 * take a pause *before* coding not *during* coding
7641 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7642 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7644 result = WERR_NOMEM;
7648 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7652 *out_type = regval_type( val );
7654 /* data - counted in bytes */
7656 *out_max_data_len = in_data_len;
7657 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7659 result = WERR_NOMEM;
7662 data_len = (size_t)regval_size(val);
7663 memcpy( *data_out, regval_data_p(val), data_len );
7664 *out_data_len = data_len;
7668 free_a_printer(&printer, 2);
7672 /****************************************************************************
7673 ****************************************************************************/
7675 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7677 POLICY_HND *handle = &q_u->handle;
7678 UNISTR2 *value = &q_u->value;
7679 uint32 type = q_u->type;
7680 uint8 *data = q_u->data;
7681 uint32 real_len = q_u->real_len;
7683 NT_PRINTER_INFO_LEVEL *printer = NULL;
7685 WERROR status = WERR_OK;
7686 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7689 DEBUG(5,("spoolss_setprinterdata\n"));
7692 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7696 if (!get_printer_snum(p,handle, &snum))
7700 * Access check : NT returns "access denied" if you make a
7701 * SetPrinterData call without the necessary privildge.
7702 * we were originally returning OK if nothing changed
7703 * which made Win2k issue **a lot** of SetPrinterData
7704 * when connecting to a printer --jerry
7707 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7709 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7710 status = WERR_ACCESS_DENIED;
7714 status = get_a_printer(&printer, 2, lp_servicename(snum));
7715 if (!W_ERROR_IS_OK(status))
7718 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7721 * When client side code sets a magic printer data key, detect it and save
7722 * the current printer data and the magic key's data (its the DEVMODE) for
7723 * future printer/driver initializations.
7725 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7727 /* Set devmode and printer initialization info */
7728 status = save_driver_init( printer, 2, data, real_len );
7730 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7734 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7735 type, data, real_len );
7736 if ( W_ERROR_IS_OK(status) )
7737 status = mod_a_printer(*printer, 2);
7741 free_a_printer(&printer, 2);
7746 /****************************************************************************
7747 ****************************************************************************/
7749 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7751 POLICY_HND *handle = &q_u->handle;
7752 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7755 DEBUG(5,("_spoolss_resetprinter\n"));
7758 * All we do is to check to see if the handle and queue is valid.
7759 * This call really doesn't mean anything to us because we only
7760 * support RAW printing. --jerry
7764 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7768 if (!get_printer_snum(p,handle, &snum))
7772 /* blindly return success */
7777 /****************************************************************************
7778 ****************************************************************************/
7780 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7782 POLICY_HND *handle = &q_u->handle;
7783 UNISTR2 *value = &q_u->valuename;
7785 NT_PRINTER_INFO_LEVEL *printer = NULL;
7787 WERROR status = WERR_OK;
7788 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7791 DEBUG(5,("spoolss_deleteprinterdata\n"));
7794 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7798 if (!get_printer_snum(p, handle, &snum))
7801 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7802 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7803 return WERR_ACCESS_DENIED;
7806 status = get_a_printer(&printer, 2, lp_servicename(snum));
7807 if (!W_ERROR_IS_OK(status))
7810 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7812 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7814 free_a_printer(&printer, 2);
7819 /****************************************************************************
7820 ****************************************************************************/
7822 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7824 POLICY_HND *handle = &q_u->handle;
7825 FORM *form = &q_u->form;
7826 nt_forms_struct tmpForm;
7828 WERROR status = WERR_OK;
7829 NT_PRINTER_INFO_LEVEL *printer = NULL;
7832 nt_forms_struct *list=NULL;
7833 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7835 DEBUG(5,("spoolss_addform\n"));
7838 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7843 /* forms can be added on printer of on the print server handle */
7845 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7847 if (!get_printer_snum(p,handle, &snum))
7850 status = get_a_printer(&printer, 2, lp_servicename(snum));
7851 if (!W_ERROR_IS_OK(status))
7855 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7856 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7857 status = WERR_ACCESS_DENIED;
7861 /* can't add if builtin */
7863 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7864 status = WERR_ALREADY_EXISTS;
7868 count = get_ntforms(&list);
7870 if(!add_a_form(&list, form, &count)) {
7871 status = WERR_NOMEM;
7875 write_ntforms(&list, count);
7878 * ChangeID must always be set if this is a printer
7881 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7882 status = mod_a_printer(*printer, 2);
7886 free_a_printer(&printer, 2);
7892 /****************************************************************************
7893 ****************************************************************************/
7895 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7897 POLICY_HND *handle = &q_u->handle;
7898 UNISTR2 *form_name = &q_u->name;
7899 nt_forms_struct tmpForm;
7901 nt_forms_struct *list=NULL;
7902 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7904 WERROR status = WERR_OK;
7905 NT_PRINTER_INFO_LEVEL *printer = NULL;
7907 DEBUG(5,("spoolss_deleteform\n"));
7910 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7914 /* forms can be deleted on printer of on the print server handle */
7916 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7918 if (!get_printer_snum(p,handle, &snum))
7921 status = get_a_printer(&printer, 2, lp_servicename(snum));
7922 if (!W_ERROR_IS_OK(status))
7926 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7927 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7928 status = WERR_ACCESS_DENIED;
7932 /* can't delete if builtin */
7934 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7935 status = WERR_INVALID_PARAM;
7939 count = get_ntforms(&list);
7941 if ( !delete_a_form(&list, form_name, &count, &status ))
7945 * ChangeID must always be set if this is a printer
7948 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7949 status = mod_a_printer(*printer, 2);
7953 free_a_printer(&printer, 2);
7959 /****************************************************************************
7960 ****************************************************************************/
7962 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7964 POLICY_HND *handle = &q_u->handle;
7965 FORM *form = &q_u->form;
7966 nt_forms_struct tmpForm;
7968 WERROR status = WERR_OK;
7969 NT_PRINTER_INFO_LEVEL *printer = NULL;
7972 nt_forms_struct *list=NULL;
7973 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7975 DEBUG(5,("spoolss_setform\n"));
7978 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7982 /* forms can be modified on printer of on the print server handle */
7984 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7986 if (!get_printer_snum(p,handle, &snum))
7989 status = get_a_printer(&printer, 2, lp_servicename(snum));
7990 if (!W_ERROR_IS_OK(status))
7994 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7995 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7996 status = WERR_ACCESS_DENIED;
8000 /* can't set if builtin */
8001 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8002 status = WERR_INVALID_PARAM;
8006 count = get_ntforms(&list);
8007 update_a_form(&list, form, count);
8008 write_ntforms(&list, count);
8011 * ChangeID must always be set if this is a printer
8014 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8015 status = mod_a_printer(*printer, 2);
8020 free_a_printer(&printer, 2);
8026 /****************************************************************************
8027 enumprintprocessors level 1.
8028 ****************************************************************************/
8030 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8032 PRINTPROCESSOR_1 *info_1=NULL;
8034 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8039 init_unistr(&info_1->name, "winprint");
8041 *needed += spoolss_size_printprocessor_info_1(info_1);
8043 if (!alloc_buffer_size(buffer, *needed))
8044 return WERR_INSUFFICIENT_BUFFER;
8046 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8050 if (*needed > offered) {
8052 return WERR_INSUFFICIENT_BUFFER;
8058 /****************************************************************************
8059 ****************************************************************************/
8061 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8063 uint32 level = q_u->level;
8064 NEW_BUFFER *buffer = NULL;
8065 uint32 offered = q_u->offered;
8066 uint32 *needed = &r_u->needed;
8067 uint32 *returned = &r_u->returned;
8069 /* that's an [in out] buffer */
8070 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8071 buffer = r_u->buffer;
8073 DEBUG(5,("spoolss_enumprintprocessors\n"));
8076 * Enumerate the print processors ...
8078 * Just reply with "winprint", to keep NT happy
8079 * and I can use my nice printer checker.
8087 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8089 return WERR_UNKNOWN_LEVEL;
8093 /****************************************************************************
8094 enumprintprocdatatypes level 1.
8095 ****************************************************************************/
8097 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8099 PRINTPROCDATATYPE_1 *info_1=NULL;
8101 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8106 init_unistr(&info_1->name, "RAW");
8108 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8110 if (!alloc_buffer_size(buffer, *needed))
8111 return WERR_INSUFFICIENT_BUFFER;
8113 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8117 if (*needed > offered) {
8119 return WERR_INSUFFICIENT_BUFFER;
8125 /****************************************************************************
8126 ****************************************************************************/
8128 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8130 uint32 level = q_u->level;
8131 NEW_BUFFER *buffer = NULL;
8132 uint32 offered = q_u->offered;
8133 uint32 *needed = &r_u->needed;
8134 uint32 *returned = &r_u->returned;
8136 /* that's an [in out] buffer */
8137 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8138 buffer = r_u->buffer;
8140 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8147 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8149 return WERR_UNKNOWN_LEVEL;
8153 /****************************************************************************
8154 enumprintmonitors level 1.
8155 ****************************************************************************/
8157 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8159 PRINTMONITOR_1 *info_1=NULL;
8161 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8166 init_unistr(&info_1->name, "Local Port");
8168 *needed += spoolss_size_printmonitor_info_1(info_1);
8170 if (!alloc_buffer_size(buffer, *needed))
8171 return WERR_INSUFFICIENT_BUFFER;
8173 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8177 if (*needed > offered) {
8179 return WERR_INSUFFICIENT_BUFFER;
8185 /****************************************************************************
8186 enumprintmonitors level 2.
8187 ****************************************************************************/
8189 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8191 PRINTMONITOR_2 *info_2=NULL;
8193 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8198 init_unistr(&info_2->name, "Local Port");
8199 init_unistr(&info_2->environment, "Windows NT X86");
8200 init_unistr(&info_2->dll_name, "localmon.dll");
8202 *needed += spoolss_size_printmonitor_info_2(info_2);
8204 if (!alloc_buffer_size(buffer, *needed))
8205 return WERR_INSUFFICIENT_BUFFER;
8207 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8211 if (*needed > offered) {
8213 return WERR_INSUFFICIENT_BUFFER;
8219 /****************************************************************************
8220 ****************************************************************************/
8222 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8224 uint32 level = q_u->level;
8225 NEW_BUFFER *buffer = NULL;
8226 uint32 offered = q_u->offered;
8227 uint32 *needed = &r_u->needed;
8228 uint32 *returned = &r_u->returned;
8230 /* that's an [in out] buffer */
8231 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8232 buffer = r_u->buffer;
8234 DEBUG(5,("spoolss_enumprintmonitors\n"));
8237 * Enumerate the print monitors ...
8239 * Just reply with "Local Port", to keep NT happy
8240 * and I can use my nice printer checker.
8248 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8250 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8252 return WERR_UNKNOWN_LEVEL;
8256 /****************************************************************************
8257 ****************************************************************************/
8259 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8263 JOB_INFO_1 *info_1=NULL;
8265 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8267 if (info_1 == NULL) {
8272 for (i=0; i<count && found==False; i++) {
8273 if (queue[i].job==(int)jobid)
8280 /* NT treats not found as bad param... yet another bad choice */
8281 return WERR_INVALID_PARAM;
8284 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8286 *needed += spoolss_size_job_info_1(info_1);
8288 if (!alloc_buffer_size(buffer, *needed)) {
8290 return WERR_INSUFFICIENT_BUFFER;
8293 smb_io_job_info_1("", buffer, info_1, 0);
8297 if (*needed > offered)
8298 return WERR_INSUFFICIENT_BUFFER;
8303 /****************************************************************************
8304 ****************************************************************************/
8306 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8311 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8313 DEVICEMODE *devmode = NULL;
8314 NT_DEVICEMODE *nt_devmode = NULL;
8316 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8318 ZERO_STRUCTP(info_2);
8320 if (info_2 == NULL) {
8325 for ( i=0; i<count && found==False; i++ )
8327 if (queue[i].job == (int)jobid)
8333 /* NT treats not found as bad param... yet another bad
8335 ret = WERR_INVALID_PARAM;
8339 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
8340 if (!W_ERROR_IS_OK(ret))
8344 * if the print job does not have a DEVMODE associated with it,
8345 * just use the one for the printer. A NULL devicemode is not
8346 * a failure condition
8349 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8350 devmode = construct_dev_mode(snum);
8352 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8353 ZERO_STRUCTP( devmode );
8354 convert_nt_devicemode( devmode, nt_devmode );
8358 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8360 *needed += spoolss_size_job_info_2(info_2);
8362 if (!alloc_buffer_size(buffer, *needed)) {
8363 ret = WERR_INSUFFICIENT_BUFFER;
8367 smb_io_job_info_2("", buffer, info_2, 0);
8369 if (*needed > offered) {
8370 ret = WERR_INSUFFICIENT_BUFFER;
8377 /* Cleanup allocated memory */
8379 free_job_info_2(info_2); /* Also frees devmode */
8381 free_a_printer(&ntprinter, 2);
8386 /****************************************************************************
8387 ****************************************************************************/
8389 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8391 POLICY_HND *handle = &q_u->handle;
8392 uint32 jobid = q_u->jobid;
8393 uint32 level = q_u->level;
8394 NEW_BUFFER *buffer = NULL;
8395 uint32 offered = q_u->offered;
8396 uint32 *needed = &r_u->needed;
8397 WERROR wstatus = WERR_OK;
8401 print_queue_struct *queue = NULL;
8402 print_status_struct prt_status;
8404 /* that's an [in out] buffer */
8405 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8406 buffer = r_u->buffer;
8408 DEBUG(5,("spoolss_getjob\n"));
8412 if (!get_printer_snum(p, handle, &snum))
8415 count = print_queue_status(snum, &queue, &prt_status);
8417 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8418 count, prt_status.status, prt_status.message));
8422 wstatus = getjob_level_1(queue, count, snum, jobid,
8423 buffer, offered, needed);
8426 wstatus = getjob_level_2(queue, count, snum, jobid,
8427 buffer, offered, needed);
8430 wstatus = WERR_UNKNOWN_LEVEL;
8438 /********************************************************************
8439 spoolss_getprinterdataex
8441 From MSDN documentation of GetPrinterDataEx: pass request
8442 to GetPrinterData if key is "PrinterDriverData".
8443 ********************************************************************/
8445 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8447 POLICY_HND *handle = &q_u->handle;
8448 uint32 in_size = q_u->size;
8449 uint32 *type = &r_u->type;
8450 uint32 *out_size = &r_u->size;
8451 uint8 **data = &r_u->data;
8452 uint32 *needed = &r_u->needed;
8453 fstring keyname, valuename;
8455 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8457 NT_PRINTER_INFO_LEVEL *printer = NULL;
8459 WERROR status = WERR_OK;
8461 DEBUG(4,("_spoolss_getprinterdataex\n"));
8463 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8464 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8466 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8467 keyname, valuename));
8469 /* in case of problem, return some default values */
8473 *out_size = in_size;
8476 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8477 status = WERR_BADFID;
8481 /* Is the handle to a printer or to the server? */
8483 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8484 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8485 status = WERR_INVALID_PARAM;
8489 if ( !get_printer_snum(p,handle, &snum) )
8492 status = get_a_printer(&printer, 2, lp_servicename(snum));
8493 if ( !W_ERROR_IS_OK(status) )
8496 /* check to see if the keyname is valid */
8497 if ( !strlen(keyname) ) {
8498 status = WERR_INVALID_PARAM;
8502 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8503 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8504 free_a_printer( &printer, 2 );
8505 status = WERR_BADFILE;
8509 /* When given a new keyname, we should just create it */
8511 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8513 if (*needed > *out_size)
8514 status = WERR_MORE_DATA;
8517 if ( !W_ERROR_IS_OK(status) )
8519 DEBUG(5, ("error: allocating %d\n", *out_size));
8521 /* reply this param doesn't exist */
8525 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8526 status = WERR_NOMEM;
8536 free_a_printer( &printer, 2 );
8541 /********************************************************************
8542 * spoolss_setprinterdataex
8543 ********************************************************************/
8545 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8547 POLICY_HND *handle = &q_u->handle;
8548 uint32 type = q_u->type;
8549 uint8 *data = q_u->data;
8550 uint32 real_len = q_u->real_len;
8552 NT_PRINTER_INFO_LEVEL *printer = NULL;
8554 WERROR status = WERR_OK;
8555 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8560 DEBUG(4,("_spoolss_setprinterdataex\n"));
8562 /* From MSDN documentation of SetPrinterDataEx: pass request to
8563 SetPrinterData if key is "PrinterDriverData" */
8566 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8570 if ( !get_printer_snum(p,handle, &snum) )
8574 * Access check : NT returns "access denied" if you make a
8575 * SetPrinterData call without the necessary privildge.
8576 * we were originally returning OK if nothing changed
8577 * which made Win2k issue **a lot** of SetPrinterData
8578 * when connecting to a printer --jerry
8581 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8583 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8584 return WERR_ACCESS_DENIED;
8587 status = get_a_printer(&printer, 2, lp_servicename(snum));
8588 if (!W_ERROR_IS_OK(status))
8591 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8592 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8594 /* check for OID in valuename */
8596 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8602 /* save the registry data */
8604 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8606 /* save the OID if one was specified and the previous set call succeeded */
8608 if ( W_ERROR_IS_OK(status) && oid_string )
8611 fstrcat( keyname, "\\" );
8612 fstrcat( keyname, SPOOL_OID_KEY );
8615 * I'm not checking the status here on purpose. Don't know
8616 * if this is right, but I'm returning the status from the
8617 * previous set_printer_dataex() call. I have no idea if
8618 * this is right. --jerry
8621 set_printer_dataex( printer, keyname, valuename,
8622 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8625 free_a_printer(&printer, 2);
8631 /********************************************************************
8632 * spoolss_deleteprinterdataex
8633 ********************************************************************/
8635 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8637 POLICY_HND *handle = &q_u->handle;
8638 UNISTR2 *value = &q_u->valuename;
8639 UNISTR2 *key = &q_u->keyname;
8641 NT_PRINTER_INFO_LEVEL *printer = NULL;
8643 WERROR status = WERR_OK;
8644 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8645 pstring valuename, keyname;
8647 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8650 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8654 if (!get_printer_snum(p, handle, &snum))
8657 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8658 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8659 return WERR_ACCESS_DENIED;
8662 status = get_a_printer(&printer, 2, lp_servicename(snum));
8663 if (!W_ERROR_IS_OK(status))
8666 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8667 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8669 status = delete_printer_dataex( printer, keyname, valuename );
8671 free_a_printer(&printer, 2);
8676 /********************************************************************
8677 * spoolss_enumprinterkey
8678 ********************************************************************/
8681 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8684 fstring *keynames = NULL;
8685 uint16 *enumkeys = NULL;
8688 POLICY_HND *handle = &q_u->handle;
8689 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8690 NT_PRINTER_DATA *data;
8691 NT_PRINTER_INFO_LEVEL *printer = NULL;
8693 WERROR status = WERR_BADFILE;
8696 DEBUG(4,("_spoolss_enumprinterkey\n"));
8699 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8703 if ( !get_printer_snum(p,handle, &snum) )
8706 status = get_a_printer(&printer, 2, lp_servicename(snum));
8707 if (!W_ERROR_IS_OK(status))
8710 /* get the list of subkey names */
8712 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8713 data = &printer->info_2->data;
8715 num_keys = get_printer_subkeys( data, key, &keynames );
8717 if ( num_keys == -1 ) {
8718 status = WERR_BADFILE;
8722 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8724 r_u->needed = printerkey_len*2;
8726 if ( q_u->size < r_u->needed ) {
8727 status = WERR_MORE_DATA;
8731 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8732 status = WERR_NOMEM;
8738 if ( q_u->size < r_u->needed )
8739 status = WERR_MORE_DATA;
8742 free_a_printer( &printer, 2 );
8743 SAFE_FREE( keynames );
8748 /********************************************************************
8749 * spoolss_deleteprinterkey
8750 ********************************************************************/
8752 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8754 POLICY_HND *handle = &q_u->handle;
8755 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8757 NT_PRINTER_INFO_LEVEL *printer = NULL;
8761 DEBUG(5,("spoolss_deleteprinterkey\n"));
8764 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8768 /* if keyname == NULL, return error */
8770 if ( !q_u->keyname.buffer )
8771 return WERR_INVALID_PARAM;
8773 if (!get_printer_snum(p, handle, &snum))
8776 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8777 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8778 return WERR_ACCESS_DENIED;
8781 status = get_a_printer(&printer, 2, lp_servicename(snum));
8782 if (!W_ERROR_IS_OK(status))
8785 /* delete the key and all subneys */
8787 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8789 status = delete_all_printer_data( printer->info_2, key );
8791 if ( W_ERROR_IS_OK(status) )
8792 status = mod_a_printer(*printer, 2);
8794 free_a_printer( &printer, 2 );
8800 /********************************************************************
8801 * spoolss_enumprinterdataex
8802 ********************************************************************/
8804 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8806 POLICY_HND *handle = &q_u->handle;
8807 uint32 in_size = q_u->size;
8810 NT_PRINTER_INFO_LEVEL *printer = NULL;
8811 PRINTER_ENUM_VALUES *enum_values = NULL;
8812 NT_PRINTER_DATA *p_data;
8814 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8819 REGISTRY_VALUE *val;
8824 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8827 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8831 /* first get the printer off of disk */
8833 if (!get_printer_snum(p,handle, &snum))
8836 ZERO_STRUCT(printer);
8837 result = get_a_printer(&printer, 2, lp_servicename(snum));
8838 if (!W_ERROR_IS_OK(result))
8841 /* now look for a match on the key name */
8843 p_data = &printer->info_2->data;
8845 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8846 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8848 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8849 result = WERR_INVALID_PARAM;
8856 /* allocate the memory for the array of pointers -- if necessary */
8858 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8861 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8863 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8864 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8865 result = WERR_NOMEM;
8869 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8873 * loop through all params and build the array to pass
8874 * back to the client
8877 for ( i=0; i<num_entries; i++ )
8879 /* lookup the registry value */
8881 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8882 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8886 value_name = regval_name( val );
8887 init_unistr( &enum_values[i].valuename, value_name );
8888 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8889 enum_values[i].type = regval_type( val );
8891 data_len = regval_size( val );
8893 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8895 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8897 result = WERR_NOMEM;
8901 enum_values[i].data_len = data_len;
8903 /* keep track of the size of the array in bytes */
8905 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8908 /* housekeeping information in the reply */
8910 r_u->needed = needed;
8911 r_u->returned = num_entries;
8913 if (needed > in_size) {
8914 result = WERR_MORE_DATA;
8918 /* copy data into the reply */
8920 r_u->ctr.size = r_u->needed;
8921 r_u->ctr.size_of_array = r_u->returned;
8922 r_u->ctr.values = enum_values;
8927 free_a_printer(&printer, 2);
8932 /****************************************************************************
8933 ****************************************************************************/
8935 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8937 init_unistr(&info->name, name);
8940 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8941 UNISTR2 *environment,
8948 pstring short_archi;
8949 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8951 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8953 if (get_short_archi(short_archi, long_archi)==False)
8954 return WERR_INVALID_ENVIRONMENT;
8956 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8959 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8961 fill_printprocessordirectory_1(info, path);
8963 *needed += spoolss_size_printprocessordirectory_info_1(info);
8965 if (!alloc_buffer_size(buffer, *needed)) {
8967 return WERR_INSUFFICIENT_BUFFER;
8970 smb_io_printprocessordirectory_1("", buffer, info, 0);
8974 if (*needed > offered)
8975 return WERR_INSUFFICIENT_BUFFER;
8980 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8982 uint32 level = q_u->level;
8983 NEW_BUFFER *buffer = NULL;
8984 uint32 offered = q_u->offered;
8985 uint32 *needed = &r_u->needed;
8988 /* that's an [in out] buffer */
8989 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8990 buffer = r_u->buffer;
8992 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8998 result = getprintprocessordirectory_level_1
8999 (&q_u->name, &q_u->environment, buffer, offered, needed);
9002 result = WERR_UNKNOWN_LEVEL;
9010 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9011 SPOOL_R_REPLYOPENPRINTER *r_u)
9013 DEBUG(5,("_spoolss_replyopenprinter\n"));
9015 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9020 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9021 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9023 DEBUG(5,("_spoolss_replycloseprinter\n"));