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
33 /* #define EMULATE_WIN2K_HACK 1 */
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41 #define PRINTER_HANDLE_IS_PRINTER 0
42 #define PRINTER_HANDLE_IS_PRINTSERVER 1
44 /* Table to map the driver version */
46 char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
60 /* structure to store the printer handles */
61 /* and a reference to what it's pointing to */
62 /* and the notify info asked about */
63 /* that's the central struct */
64 typedef struct _Printer{
65 struct _Printer *prev, *next;
66 BOOL document_started;
68 uint32 jobid; /* jobid in printing backend */
72 fstring printerservername;
75 uint32 access_granted;
81 SPOOL_NOTIFY_OPTION *option;
82 POLICY_HND client_hnd;
83 uint32 client_connected;
91 /* devmode sent in the OpenPrinter() call */
92 NT_DEVICEMODE *nt_devmode;
96 static Printer_entry *printers_list;
98 typedef struct _counter_printer_0 {
106 static ubi_dlList counter_list;
108 static struct cli_state notify_cli; /* print notify back-channel */
109 static uint32 smb_connections=0;
112 /* in printing/nt_printing.c */
114 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
116 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
117 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
119 /* translate between internal status numbers and NT status numbers */
120 static int nt_printj_status(int v)
126 return JOB_STATUS_PAUSED;
128 return JOB_STATUS_SPOOLING;
130 return JOB_STATUS_PRINTING;
132 return JOB_STATUS_ERROR;
134 return JOB_STATUS_DELETING;
136 return JOB_STATUS_OFFLINE;
138 return JOB_STATUS_PAPEROUT;
140 return JOB_STATUS_PRINTED;
142 return JOB_STATUS_DELETED;
144 return JOB_STATUS_BLOCKED;
145 case LPQ_USER_INTERVENTION:
146 return JOB_STATUS_USER_INTERVENTION;
151 static int nt_printq_status(int v)
155 return PRINTER_STATUS_PAUSED;
164 /****************************************************************************
165 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
166 ****************************************************************************/
168 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
173 SAFE_FREE((*pp)->ctr.type);
177 /***************************************************************************
178 Disconnect from the client
179 ****************************************************************************/
181 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
186 * Tell the specific printing tdb we no longer want messages for this printer
187 * by deregistering our PID.
190 if (!print_notify_deregister_pid(snum))
191 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
193 /* weird if the test succeds !!! */
194 if (smb_connections==0) {
195 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
199 result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle);
201 if (!W_ERROR_IS_OK(result))
202 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
203 dos_errstr(result)));
205 /* if it's the last connection, deconnect the IPC$ share */
206 if (smb_connections==1) {
207 cli_nt_session_close(¬ify_cli);
208 cli_ulogoff(¬ify_cli);
209 cli_shutdown(¬ify_cli);
210 message_deregister(MSG_PRINTER_NOTIFY2);
212 /* Tell the connections db we're no longer interested in
213 * printer notify messages. */
215 register_message_flags( False, FLAG_MSG_PRINTING );
221 /****************************************************************************
222 Functions to free a printer entry datastruct.
223 ****************************************************************************/
225 static void free_printer_entry(void *ptr)
227 Printer_entry *Printer = (Printer_entry *)ptr;
229 if (Printer->notify.client_connected==True) {
232 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
234 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
235 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
236 snum = print_queue_snum(Printer->dev.handlename);
238 srv_spoolss_replycloseprinter(snum,
239 &Printer->notify.client_hnd);
243 Printer->notify.flags=0;
244 Printer->notify.options=0;
245 Printer->notify.localmachine[0]='\0';
246 Printer->notify.printerlocal=0;
247 free_spool_notify_option(&Printer->notify.option);
248 Printer->notify.option=NULL;
249 Printer->notify.client_connected=False;
251 free_nt_devicemode( &Printer->nt_devmode );
253 /* Remove from the internal list. */
254 DLIST_REMOVE(printers_list, Printer);
259 /****************************************************************************
260 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
261 ****************************************************************************/
263 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
265 SPOOL_NOTIFY_OPTION *new_sp = NULL;
270 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
277 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
279 if (!new_sp->ctr.type) {
288 /****************************************************************************
289 find printer index by handle
290 ****************************************************************************/
292 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
294 Printer_entry *find_printer = NULL;
296 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
297 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
304 /****************************************************************************
305 Close printer index by handle.
306 ****************************************************************************/
308 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
310 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
313 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
317 close_policy_hnd(p, hnd);
322 /****************************************************************************
323 Delete a printer given a handle.
324 ****************************************************************************/
326 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
328 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
331 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
336 * It turns out that Windows allows delete printer on a handle
337 * opened by an admin user, then used on a pipe handle created
338 * by an anonymous user..... but they're working on security.... riiight !
342 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
343 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
344 return WERR_ACCESS_DENIED;
348 /* Check calling user has permission to delete printer. Note that
349 since we set the snum parameter to -1 only administrators can
350 delete the printer. This stops people with the Full Control
351 permission from deleting the printer. */
353 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
354 DEBUG(3, ("printer delete denied by security descriptor\n"));
355 return WERR_ACCESS_DENIED;
359 if (del_a_printer(Printer->dev.handlename) != 0) {
360 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
364 if (*lp_deleteprinter_cmd()) {
366 char *cmd = lp_deleteprinter_cmd();
371 /* Printer->dev.handlename equals portname equals sharename */
372 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
373 Printer->dev.handlename);
375 DEBUG(10,("Running [%s]\n", command));
376 ret = smbrun(command, NULL);
378 return WERR_BADFID; /* What to return here? */
380 DEBUGADD(10,("returned [%d]\n", ret));
382 /* Send SIGHUP to process group... is there a better way? */
385 /* go ahead and re-read the services immediately */
386 reload_services( False );
388 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
389 return WERR_ACCESS_DENIED;
395 /****************************************************************************
396 Return the snum of a printer corresponding to an handle.
397 ****************************************************************************/
399 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
401 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
404 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
408 switch (Printer->printer_type) {
409 case PRINTER_HANDLE_IS_PRINTER:
410 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
411 *number = print_queue_snum(Printer->dev.handlename);
412 return (*number != -1);
413 case PRINTER_HANDLE_IS_PRINTSERVER:
420 /****************************************************************************
421 Set printer handle type.
422 Check if it's \\server or \\server\printer
423 ****************************************************************************/
425 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
427 DEBUG(3,("Setting printer type=%s\n", handlename));
429 if ( strlen(handlename) < 3 ) {
430 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
434 /* it's a print server */
435 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
436 DEBUGADD(4,("Printer is a print server\n"));
437 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
441 DEBUGADD(4,("Printer is a printer\n"));
442 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
448 /****************************************************************************
449 Set printer handle name.
450 ****************************************************************************/
452 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
455 int n_services=lp_numservices();
460 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
462 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
463 ZERO_STRUCT(Printer->dev.printerservername);
464 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
468 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
471 if (*handlename=='\\') {
472 aprinter=strchr_m(handlename+2, '\\');
479 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
482 * The original code allowed smbd to store a printer name that
483 * was different from the share name. This is not possible
484 * anymore, so I've simplified this loop greatly. Here
485 * we are just verifying that the printer name is a valid
486 * printer service defined in smb.conf
487 * --jerry [Fri Feb 15 11:17:46 CST 2002]
490 for (snum=0; snum<n_services; snum++) {
492 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
495 fstrcpy(sname, lp_servicename(snum));
497 DEBUGADD(5,("share:%s\n",sname));
499 if (! StrCaseCmp(sname, aprinter)) {
508 DEBUGADD(4,("Printer not found\n"));
512 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
514 ZERO_STRUCT(Printer->dev.handlename);
515 fstrcpy(Printer->dev.handlename, sname);
520 /****************************************************************************
521 Find first available printer slot. creates a printer handle for you.
522 ****************************************************************************/
524 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
526 Printer_entry *new_printer;
528 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
530 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
533 ZERO_STRUCTP(new_printer);
535 new_printer->notify.option=NULL;
537 /* Add to the internal list. */
538 DLIST_ADD(printers_list, new_printer);
540 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
541 SAFE_FREE(new_printer);
545 if (!set_printer_hnd_printertype(new_printer, name)) {
546 close_printer_handle(p, hnd);
550 if (!set_printer_hnd_name(new_printer, name)) {
551 close_printer_handle(p, hnd);
555 new_printer->access_granted = access_granted;
557 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
562 /****************************************************************************
563 Allocate more memory for a BUFFER.
564 ****************************************************************************/
566 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
574 /* damn, I'm doing the reverse operation of prs_grow() :) */
575 if (buffer_size < prs_data_size(ps))
578 extra_space = buffer_size - prs_data_size(ps);
581 * save the offset and move to the end of the buffer
582 * prs_grow() checks the extra_space against the offset
584 old_offset=prs_offset(ps);
585 prs_set_offset(ps, prs_data_size(ps));
587 if (!prs_grow(ps, extra_space))
590 prs_set_offset(ps, old_offset);
592 buffer->string_at_end=prs_data_size(ps);
597 /***************************************************************************
598 check to see if the client motify handle is monitoring the notification
599 given by (notify_type, notify_field).
600 **************************************************************************/
602 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
608 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
611 SPOOL_NOTIFY_OPTION *option = p->notify.option;
615 * Flags should always be zero when the change notify
616 * is registered by the cliebnt's spooler. A user Win32 app
617 * might use the flags though instead of the NOTIFY_OPTION_INFO
622 return is_monitoring_event_flags(
623 p->notify.flags, notify_type, notify_field);
625 for (i = 0; i < option->count; i++) {
627 /* Check match for notify_type */
629 if (option->ctr.type[i].type != notify_type)
632 /* Check match for field */
634 for (j = 0; j < option->ctr.type[i].count; j++) {
635 if (option->ctr.type[i].fields[j] == notify_field) {
641 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
642 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
643 p->dev.handlename : p->dev.printerservername,
644 notify_type, notify_field));
649 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
651 static void notify_one_value(struct spoolss_notify_msg *msg,
652 SPOOL_NOTIFY_INFO_DATA *data,
655 data->notify_data.value[0] = msg->notify.value[0];
656 data->notify_data.value[1] = 0;
659 static void notify_string(struct spoolss_notify_msg *msg,
660 SPOOL_NOTIFY_INFO_DATA *data,
665 /* The length of the message includes the trailing \0 */
667 init_unistr2(&unistr, msg->notify.data, msg->len);
669 data->notify_data.data.length = msg->len * 2;
670 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
672 if (!data->notify_data.data.string) {
673 data->notify_data.data.length = 0;
677 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
680 static void notify_system_time(struct spoolss_notify_msg *msg,
681 SPOOL_NOTIFY_INFO_DATA *data,
687 if (msg->len != sizeof(time_t)) {
688 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
693 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
694 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
698 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
699 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
703 if (!spoolss_io_system_time("", &ps, 0, &systime))
706 data->notify_data.data.length = prs_offset(&ps);
707 data->notify_data.data.string =
708 talloc(mem_ctx, prs_offset(&ps));
710 memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
715 struct notify2_message_table {
717 void (*fn)(struct spoolss_notify_msg *msg,
718 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
721 static struct notify2_message_table printer_notify_table[] = {
722 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
723 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
724 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
725 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
726 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
727 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
728 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
729 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
730 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
731 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
732 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
733 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
734 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
735 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
736 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
737 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
738 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
739 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
740 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
743 static struct notify2_message_table job_notify_table[] = {
744 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
745 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
746 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
747 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
748 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
749 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
750 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
751 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
752 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
753 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
754 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
755 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
756 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
757 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
758 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
759 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
760 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
761 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
762 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
763 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
764 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
765 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
766 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
767 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
771 /***********************************************************************
772 Allocate talloc context for container object
773 **********************************************************************/
775 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
780 ctr->ctx = talloc_init();
785 /***********************************************************************
786 release all allocated memory and zero out structure
787 **********************************************************************/
789 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
795 talloc_destroy(ctr->ctx);
802 /***********************************************************************
803 **********************************************************************/
805 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
813 /***********************************************************************
814 **********************************************************************/
816 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
818 if ( !ctr || !ctr->msg_groups )
821 if ( idx >= ctr->num_groups )
824 return &ctr->msg_groups[idx];
828 /***********************************************************************
829 How many groups of change messages do we have ?
830 **********************************************************************/
832 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
837 return ctr->num_groups;
840 /***********************************************************************
841 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
842 **********************************************************************/
844 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
846 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
847 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
848 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
854 /* loop over all groups looking for a matching printer name */
856 for ( i=0; i<ctr->num_groups; i++ ) {
857 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
861 /* add a new group? */
863 if ( i == ctr->num_groups )
867 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
868 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
871 ctr->msg_groups = groups;
873 /* clear the new entry and set the printer name */
875 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
876 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
879 /* add the change messages; 'i' is the correct index now regardless */
881 msg_grp = &ctr->msg_groups[i];
885 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
886 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
889 msg_grp->msgs = msg_list;
891 new_slot = msg_grp->num_msgs-1;
892 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
894 /* need to allocate own copy of data */
897 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
899 return ctr->num_groups;
902 /***********************************************************************
903 Send a change notication message on all handles which have a call
905 **********************************************************************/
907 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
910 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
911 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
912 SPOOLSS_NOTIFY_MSG *messages;
916 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
920 messages = msg_group->msgs;
923 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
927 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
929 /* loop over all printers */
931 for (p = printers_list; p; p = p->next)
933 SPOOL_NOTIFY_INFO_DATA *data;
938 /* Is there notification on this handle? */
940 if ( !p->notify.client_connected )
943 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
945 /* For this printer? Print servers always receive
948 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
949 ( !strequal(msg_group->printername, p->dev.handlename) ) )
952 DEBUG(10,("Our printer\n"));
954 /* allocate the max entries possible */
956 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
959 /* build the array of change notifications */
961 for ( i=0; i<msg_group->num_msgs; i++ )
963 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
965 /* Are we monitoring this event? */
967 if (!is_monitoring_event(p, msg->type, msg->field))
971 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
972 msg->type, msg->field, p->dev.handlename));
975 * if the is a printer notification handle and not a job notification
976 * type, then set the id to 0. Other wise just use what was specified
979 * When registering change notification on a print server handle
980 * we always need to send back the id (snum) matching the printer
981 * for which the change took place. For change notify registered
982 * on a printer handle, this does not matter and the id should be 0.
987 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
993 /* Convert unix jobid to smb jobid */
995 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID)
997 id = sysjob_to_jobid(msg->id);
1000 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1005 construct_info_data( &data[data_len], msg->type, msg->field, id );
1008 case PRINTER_NOTIFY_TYPE:
1009 if ( !printer_notify_table[msg->field].fn )
1011 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1015 case JOB_NOTIFY_TYPE:
1016 if ( !job_notify_table[msg->field].fn )
1018 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1023 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1030 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1031 data_len, data, p->notify.change, 0 );
1035 DEBUG(8,("send_notify2_changes: Exit...\n"));
1039 /***********************************************************************
1040 **********************************************************************/
1042 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
1047 /* Unpack message */
1049 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1052 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
1053 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1056 tdb_unpack((char *)buf + offset, len - offset, "dd",
1057 &msg->notify.value[0], &msg->notify.value[1]);
1059 tdb_unpack((char *)buf + offset, len - offset, "B",
1060 &msg->len, &msg->notify.data);
1062 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1063 msg->type, msg->field, msg->flags));
1066 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1067 msg->notify.value[1]));
1069 dump_data(3, msg->notify.data, msg->len);
1074 /********************************************************************
1075 Receive a notify2 message list
1076 ********************************************************************/
1078 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1080 size_t msg_count, i;
1081 char *buf = (char *)msg;
1084 SPOOLSS_NOTIFY_MSG notify;
1085 SPOOLSS_NOTIFY_MSG_CTR messages;
1089 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1093 msg_count = IVAL(buf, 0);
1096 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1098 if (msg_count == 0) {
1099 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1103 /* initialize the container */
1105 ZERO_STRUCT( messages );
1106 notify_msg_ctr_init( &messages );
1109 * build message groups for each printer identified
1110 * in a change_notify msg. Remember that a PCN message
1111 * includes the handle returned for the srv_spoolss_replyopenprinter()
1112 * call. Therefore messages are grouped according to printer handle.
1115 for ( i=0; i<msg_count; i++ )
1117 if (msg_ptr + 4 - buf > len) {
1118 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1122 msg_len = IVAL(msg_ptr,0);
1125 if (msg_ptr + msg_len - buf > len) {
1126 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1130 /* unpack messages */
1132 ZERO_STRUCT( notify );
1133 notify2_unpack_msg( ¬ify, msg_ptr, msg_len );
1136 /* add to correct list in container */
1138 notify_msg_ctr_addmsg( &messages, ¬ify );
1140 /* free memory that might have been allocated by notify2_unpack_msg() */
1142 if ( notify.len != 0 )
1143 SAFE_FREE( notify.notify.data );
1146 /* process each group of messages */
1148 num_groups = notify_msg_ctr_numgroups( &messages );
1149 for ( i=0; i<num_groups; i++ )
1150 send_notify2_changes( &messages, i );
1155 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1157 notify_msg_ctr_destroy( &messages );
1162 /********************************************************************
1163 Send a message to ourself about new driver being installed
1164 so we can upgrade the information for each printer bound to this
1166 ********************************************************************/
1168 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1170 int len = strlen(drivername);
1175 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1178 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1183 /**********************************************************************
1184 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1185 over all printers, upgrading ones as neessary
1186 **********************************************************************/
1188 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1192 int n_services = lp_numservices();
1194 len = MIN(len,sizeof(drivername)-1);
1195 strncpy(drivername, buf, len);
1197 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1199 /* Iterate the printer list */
1201 for (snum=0; snum<n_services; snum++)
1203 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1206 NT_PRINTER_INFO_LEVEL *printer = NULL;
1208 result = get_a_printer(&printer, 2, lp_servicename(snum));
1209 if (!W_ERROR_IS_OK(result))
1212 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1214 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1216 /* all we care about currently is the change_id */
1218 result = mod_a_printer(*printer, 2);
1219 if (!W_ERROR_IS_OK(result)) {
1220 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1221 dos_errstr(result)));
1225 free_a_printer(&printer, 2);
1232 /********************************************************************
1233 Send a message to ourself about new driver being installed
1234 so we can upgrade the information for each printer bound to this
1236 ********************************************************************/
1238 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1240 int len = strlen(drivername);
1245 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1248 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1253 /**********************************************************************
1254 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1255 over all printers, resetting printer data as neessary
1256 **********************************************************************/
1258 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1262 int n_services = lp_numservices();
1264 len = MIN( len, sizeof(drivername)-1 );
1265 strncpy( drivername, buf, len );
1267 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1269 /* Iterate the printer list */
1271 for ( snum=0; snum<n_services; snum++ )
1273 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1276 NT_PRINTER_INFO_LEVEL *printer = NULL;
1278 result = get_a_printer( &printer, 2, lp_servicename(snum) );
1279 if ( !W_ERROR_IS_OK(result) )
1283 * if the printer is bound to the driver,
1284 * then reset to the new driver initdata
1287 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1289 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1291 if ( !set_driver_init(printer, 2) ) {
1292 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1293 printer->info_2->printername, printer->info_2->drivername));
1296 result = mod_a_printer( *printer, 2 );
1297 if ( !W_ERROR_IS_OK(result) ) {
1298 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1299 get_dos_error_msg(result)));
1303 free_a_printer( &printer, 2 );
1312 /********************************************************************
1313 Copy routines used by convert_to_openprinterex()
1314 *******************************************************************/
1316 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1324 DEBUG (8,("dup_devmode\n"));
1326 /* bulk copy first */
1328 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1332 /* dup the pointer members separately */
1334 len = unistrlen(devmode->devicename.buffer);
1336 d->devicename.buffer = talloc(ctx, len*2);
1337 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1342 len = unistrlen(devmode->formname.buffer);
1344 d->devicename.buffer = talloc(ctx, len*2);
1345 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1349 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1354 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1356 if (!new_ctr || !ctr)
1359 DEBUG(8,("copy_devmode_ctr\n"));
1361 new_ctr->size = ctr->size;
1362 new_ctr->devmode_ptr = ctr->devmode_ptr;
1364 if(ctr->devmode_ptr)
1365 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1368 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1370 if (!new_def || !def)
1373 DEBUG(8,("copy_printer_defaults\n"));
1375 new_def->datatype_ptr = def->datatype_ptr;
1377 if (def->datatype_ptr)
1378 copy_unistr2(&new_def->datatype, &def->datatype);
1380 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1382 new_def->access_required = def->access_required;
1385 /********************************************************************
1386 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1387 * SPOOL_Q_OPEN_PRINTER_EX structure
1388 ********************************************************************/
1390 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1392 if (!q_u_ex || !q_u)
1395 DEBUG(8,("convert_to_openprinterex\n"));
1397 q_u_ex->printername_ptr = q_u->printername_ptr;
1399 if (q_u->printername_ptr)
1400 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1402 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1405 /********************************************************************
1406 * spoolss_open_printer
1408 * called from the spoolss dispatcher
1409 ********************************************************************/
1411 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1413 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1414 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1419 ZERO_STRUCT(q_u_ex);
1420 ZERO_STRUCT(r_u_ex);
1422 /* convert the OpenPrinter() call to OpenPrinterEx() */
1424 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1426 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1428 /* convert back to OpenPrinter() */
1430 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1435 /********************************************************************
1436 * spoolss_open_printer
1438 * If the openprinterex rpc call contains a devmode,
1439 * it's a per-user one. This per-user devmode is derivated
1440 * from the global devmode. Openprinterex() contains a per-user
1441 * devmode for when you do EMF printing and spooling.
1442 * In the EMF case, the NT workstation is only doing half the job
1443 * of rendering the page. The other half is done by running the printer
1444 * driver on the server.
1445 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1446 * The EMF file only contains what is to be printed on the page.
1447 * So in order for the server to know how to print, the NT client sends
1448 * a devicemode attached to the openprinterex call.
1449 * But this devicemode is short lived, it's only valid for the current print job.
1451 * If Samba would have supported EMF spooling, this devicemode would
1452 * have been attached to the handle, to sent it to the driver to correctly
1453 * rasterize the EMF file.
1455 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1456 * we just act as a pass-thru between windows and the printer.
1458 * In order to know that Samba supports only RAW spooling, NT has to call
1459 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1460 * and until NT sends a RAW job, we refuse it.
1462 * But to call getprinter() or startdoc(), you first need a valid handle,
1463 * and to get an handle you have to call openprintex(). Hence why you have
1464 * a devicemode in the openprinterex() call.
1467 * Differences between NT4 and NT 2000.
1470 * On NT4, you only have a global devicemode. This global devicemode can be changed
1471 * by the administrator (or by a user with enough privs). Everytime a user
1472 * wants to print, the devicemode is resetted to the default. In Word, everytime
1473 * you print, the printer's characteristics are always reset to the global devicemode.
1477 * In W2K, there is the notion of per-user devicemode. The first time you use
1478 * a printer, a per-user devicemode is build from the global devicemode.
1479 * If you change your per-user devicemode, it is saved in the registry, under the
1480 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1481 * printer preferences available.
1483 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1484 * on the General Tab of the printer properties windows.
1486 * To change the global devicemode: it's the "Printing Defaults..." button
1487 * on the Advanced Tab of the printer properties window.
1490 ********************************************************************/
1492 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1494 UNISTR2 *printername = NULL;
1495 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1496 POLICY_HND *handle = &r_u->handle;
1500 struct current_user user;
1501 Printer_entry *Printer=NULL;
1503 if (q_u->printername_ptr != 0)
1504 printername = &q_u->printername;
1506 if (printername == NULL)
1507 return WERR_INVALID_PRINTER_NAME;
1509 /* some sanity check because you can open a printer or a print server */
1510 /* aka: \\server\printer or \\server */
1511 unistr2_to_ascii(name, printername, sizeof(name)-1);
1513 DEBUGADD(3,("checking name: %s\n",name));
1515 if (!open_printer_hnd(p, handle, name, 0))
1516 return WERR_INVALID_PRINTER_NAME;
1518 Printer=find_printer_index_by_hnd(p, handle);
1520 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1521 Can't find printer handle we created for printer %s\n", name ));
1522 close_printer_handle(p,handle);
1523 return WERR_INVALID_PRINTER_NAME;
1526 get_current_user(&user, p);
1529 * First case: the user is opening the print server:
1531 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1532 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1534 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1535 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1536 * or if the user is listed in the smb.conf printer admin parameter.
1538 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1539 * client view printer folder, but does not show the MSAPW.
1541 * Note: this test needs code to check access rights here too. Jeremy
1542 * could you look at this?
1544 * Second case: the user is opening a printer:
1545 * NT doesn't let us connect to a printer if the connecting user
1546 * doesn't have print permission.
1549 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1551 /* Printserver handles use global struct... */
1555 /* Map standard access rights to object specific access rights */
1557 se_map_standard(&printer_default->access_required,
1558 &printserver_std_mapping);
1560 /* Deny any object specific bits that don't apply to print
1561 servers (i.e printer and job specific bits) */
1563 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1565 if (printer_default->access_required &
1566 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1567 DEBUG(3, ("access DENIED for non-printserver bits"));
1568 close_printer_handle(p, handle);
1569 return WERR_ACCESS_DENIED;
1572 /* Allow admin access */
1574 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1576 if (!lp_ms_add_printer_wizard()) {
1577 close_printer_handle(p, handle);
1578 return WERR_ACCESS_DENIED;
1581 /* if the user is not root and not a printer admin, then fail */
1584 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
1586 close_printer_handle(p, handle);
1587 return WERR_ACCESS_DENIED;
1590 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1594 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1597 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1598 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1600 /* We fall through to return WERR_OK */
1605 /* NT doesn't let us connect to a printer if the connecting user
1606 doesn't have print permission. */
1608 if (!get_printer_snum(p, handle, &snum))
1611 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1613 /* map an empty access mask to the minimum access mask */
1614 if (printer_default->access_required == 0x0)
1615 printer_default->access_required = PRINTER_ACCESS_USE;
1618 * If we are not serving the printer driver for this printer,
1619 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1620 * will keep NT clients happy --jerry
1623 if (lp_use_client_driver(snum)
1624 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1626 printer_default->access_required = PRINTER_ACCESS_USE;
1629 /* check smb.conf parameters and the the sec_desc */
1631 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1632 DEBUG(3, ("access DENIED for printer open\n"));
1633 close_printer_handle(p, handle);
1634 return WERR_ACCESS_DENIED;
1637 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1638 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1639 close_printer_handle(p, handle);
1640 return WERR_ACCESS_DENIED;
1643 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1644 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1646 printer_default->access_required = PRINTER_ACCESS_USE;
1648 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1649 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1653 Printer->access_granted = printer_default->access_required;
1656 * If the client sent a devmode in the OpenPrinter() call, then
1657 * save it here in case we get a job submission on this handle
1660 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1661 && q_u->printer_default.devmode_cont.devmode_ptr )
1663 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1664 &Printer->nt_devmode );
1670 /****************************************************************************
1671 ****************************************************************************/
1673 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1674 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1680 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1689 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1690 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1696 printer->info_3=NULL;
1697 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1701 printer->info_6=NULL;
1702 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1712 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1713 NT_DEVICEMODE **pp_nt_devmode)
1715 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1718 * Ensure nt_devmode is a valid pointer
1719 * as we will be overwriting it.
1722 if (nt_devmode == NULL) {
1723 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1724 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1728 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1729 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1731 nt_devmode->specversion=devmode->specversion;
1732 nt_devmode->driverversion=devmode->driverversion;
1733 nt_devmode->size=devmode->size;
1734 nt_devmode->fields=devmode->fields;
1735 nt_devmode->orientation=devmode->orientation;
1736 nt_devmode->papersize=devmode->papersize;
1737 nt_devmode->paperlength=devmode->paperlength;
1738 nt_devmode->paperwidth=devmode->paperwidth;
1739 nt_devmode->scale=devmode->scale;
1740 nt_devmode->copies=devmode->copies;
1741 nt_devmode->defaultsource=devmode->defaultsource;
1742 nt_devmode->printquality=devmode->printquality;
1743 nt_devmode->color=devmode->color;
1744 nt_devmode->duplex=devmode->duplex;
1745 nt_devmode->yresolution=devmode->yresolution;
1746 nt_devmode->ttoption=devmode->ttoption;
1747 nt_devmode->collate=devmode->collate;
1749 nt_devmode->logpixels=devmode->logpixels;
1750 nt_devmode->bitsperpel=devmode->bitsperpel;
1751 nt_devmode->pelswidth=devmode->pelswidth;
1752 nt_devmode->pelsheight=devmode->pelsheight;
1753 nt_devmode->displayflags=devmode->displayflags;
1754 nt_devmode->displayfrequency=devmode->displayfrequency;
1755 nt_devmode->icmmethod=devmode->icmmethod;
1756 nt_devmode->icmintent=devmode->icmintent;
1757 nt_devmode->mediatype=devmode->mediatype;
1758 nt_devmode->dithertype=devmode->dithertype;
1759 nt_devmode->reserved1=devmode->reserved1;
1760 nt_devmode->reserved2=devmode->reserved2;
1761 nt_devmode->panningwidth=devmode->panningwidth;
1762 nt_devmode->panningheight=devmode->panningheight;
1765 * Only change private and driverextra if the incoming devmode
1766 * has a new one. JRA.
1769 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1770 SAFE_FREE(nt_devmode->private);
1771 nt_devmode->driverextra=devmode->driverextra;
1772 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1774 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1777 *pp_nt_devmode = nt_devmode;
1782 /********************************************************************
1783 * _spoolss_enddocprinter_internal.
1784 ********************************************************************/
1786 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1788 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1792 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1796 if (!get_printer_snum(p, handle, &snum))
1799 Printer->document_started=False;
1800 print_job_end(snum, Printer->jobid,True);
1801 /* error codes unhandled so far ... */
1806 /********************************************************************
1807 * api_spoolss_closeprinter
1808 ********************************************************************/
1810 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1812 POLICY_HND *handle = &q_u->handle;
1814 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1816 if (Printer && Printer->document_started)
1817 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1819 if (!close_printer_handle(p, handle))
1822 /* clear the returned printer handle. Observed behavior
1823 from Win2k server. Don't think this really matters.
1824 Previous code just copied the value of the closed
1827 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1832 /********************************************************************
1833 * api_spoolss_deleteprinter
1835 ********************************************************************/
1837 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1839 POLICY_HND *handle = &q_u->handle;
1840 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1843 if (Printer && Printer->document_started)
1844 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1846 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1848 result = delete_printer_handle(p, handle);
1850 update_c_setprinter(False);
1855 /*******************************************************************
1856 * static function to lookup the version id corresponding to an
1857 * long architecture string
1858 ******************************************************************/
1860 static int get_version_id (char * arch)
1863 struct table_node archi_table[]= {
1865 {"Windows 4.0", "WIN40", 0 },
1866 {"Windows NT x86", "W32X86", 2 },
1867 {"Windows NT R4000", "W32MIPS", 2 },
1868 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1869 {"Windows NT PowerPC", "W32PPC", 2 },
1873 for (i=0; archi_table[i].long_archi != NULL; i++)
1875 if (strcmp(arch, archi_table[i].long_archi) == 0)
1876 return (archi_table[i].version);
1882 /********************************************************************
1883 * _spoolss_deleteprinterdriver
1884 ********************************************************************/
1886 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1890 NT_PRINTER_DRIVER_INFO_LEVEL info;
1891 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1893 struct current_user user;
1895 WERROR status_win2k = WERR_ACCESS_DENIED;
1897 get_current_user(&user, p);
1899 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1900 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1902 /* check that we have a valid driver name first */
1904 if ((version=get_version_id(arch)) == -1)
1905 return WERR_INVALID_ENVIRONMENT;
1908 ZERO_STRUCT(info_win2k);
1910 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1912 /* try for Win2k driver if "Windows NT x86" */
1914 if ( version == 2 ) {
1916 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1917 status = WERR_UNKNOWN_PRINTER_DRIVER;
1921 /* otherwise it was a failure */
1923 status = WERR_UNKNOWN_PRINTER_DRIVER;
1929 if (printer_driver_in_use(info.info_3)) {
1930 status = WERR_PRINTER_DRIVER_IN_USE;
1936 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1938 /* if we get to here, we now have 2 driver info structures to remove */
1939 /* remove the Win2k driver first*/
1941 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1942 free_a_printer_driver( info_win2k, 3 );
1944 /* this should not have failed---if it did, report to client */
1945 if ( !W_ERROR_IS_OK(status_win2k) )
1950 status = delete_printer_driver(info.info_3, &user, version, False);
1952 /* if at least one of the deletes succeeded return OK */
1954 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1958 free_a_printer_driver( info, 3 );
1963 /********************************************************************
1964 * spoolss_deleteprinterdriverex
1965 ********************************************************************/
1967 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1971 NT_PRINTER_DRIVER_INFO_LEVEL info;
1972 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1974 uint32 flags = q_u->delete_flags;
1976 struct current_user user;
1978 WERROR status_win2k = WERR_ACCESS_DENIED;
1980 get_current_user(&user, p);
1982 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1983 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1985 /* check that we have a valid driver name first */
1986 if ((version=get_version_id(arch)) == -1) {
1987 /* this is what NT returns */
1988 return WERR_INVALID_ENVIRONMENT;
1991 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
1992 version = q_u->version;
1995 ZERO_STRUCT(info_win2k);
1997 status = get_a_printer_driver(&info, 3, driver, arch, version);
1999 if ( !W_ERROR_IS_OK(status) )
2002 * if the client asked for a specific version,
2003 * or this is something other than Windows NT x86,
2007 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2010 /* try for Win2k driver if "Windows NT x86" */
2013 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2014 status = WERR_UNKNOWN_PRINTER_DRIVER;
2019 if ( printer_driver_in_use(info.info_3) ) {
2020 status = WERR_PRINTER_DRIVER_IN_USE;
2025 * we have a couple of cases to consider.
2026 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2027 * then the delete should fail if **any** files overlap with
2029 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2030 * non-overlapping files
2031 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2032 * is set, the do not delete any files
2033 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2036 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2038 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2040 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2041 /* no idea of the correct error here */
2042 status = WERR_ACCESS_DENIED;
2047 /* also check for W32X86/3 if necessary; maybe we already have? */
2049 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2050 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2053 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2054 /* no idea of the correct error here */
2055 free_a_printer_driver( info_win2k, 3 );
2056 status = WERR_ACCESS_DENIED;
2060 /* if we get to here, we now have 2 driver info structures to remove */
2061 /* remove the Win2k driver first*/
2063 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2064 free_a_printer_driver( info_win2k, 3 );
2066 /* this should not have failed---if it did, report to client */
2068 if ( !W_ERROR_IS_OK(status_win2k) )
2073 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2075 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2078 free_a_printer_driver( info, 3 );
2084 /****************************************************************************
2085 Internal routine for retreiving printerdata
2086 ***************************************************************************/
2088 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2089 char *key, char *value, uint32 *type, uint8 **data,
2090 uint32 *needed, uint32 in_size )
2092 REGISTRY_VALUE *val;
2095 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2096 return WERR_BADFILE;
2098 *type = regval_type( val );
2100 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2102 size = regval_size( val );
2104 /* copy the min(in_size, len) */
2107 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2108 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2116 DEBUG(5,("get_printer_dataex: copy done\n"));
2121 /****************************************************************************
2122 Internal routine for removing printerdata
2123 ***************************************************************************/
2125 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value )
2127 delete_printer_data( printer->info_2, key, value );
2129 return mod_a_printer(*printer, 2);
2132 /****************************************************************************
2133 Internal routine for storing printerdata
2134 ***************************************************************************/
2136 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value,
2137 uint32 type, uint8 *data, int real_len )
2139 delete_printer_data( printer->info_2, key, value );
2141 add_printer_data( printer->info_2, key, value, type, data, real_len );
2143 return mod_a_printer(*printer, 2);
2146 /********************************************************************
2147 GetPrinterData on a printer server Handle.
2148 ********************************************************************/
2150 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2154 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2156 if (!strcmp(value, "W3SvcInstalled")) {
2158 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2164 if (!strcmp(value, "BeepEnabled")) {
2166 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2168 SIVAL(*data, 0, 0x00);
2173 if (!strcmp(value, "EventLog")) {
2175 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2177 /* formally was 0x1b */
2178 SIVAL(*data, 0, 0x0);
2183 if (!strcmp(value, "NetPopup")) {
2185 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2187 SIVAL(*data, 0, 0x00);
2192 if (!strcmp(value, "MajorVersion")) {
2194 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2196 #ifndef EMULATE_WIN2K_HACK /* JERRY */
2205 if (!strcmp(value, "DefaultSpoolDirectory")) {
2208 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2210 *needed = 2*(strlen(string)+1);
2211 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2213 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2215 /* it's done by hand ready to go on the wire */
2216 for (i=0; i<strlen(string); i++) {
2217 (*data)[2*i]=string[i];
2218 (*data)[2*i+1]='\0';
2223 if (!strcmp(value, "Architecture")) {
2224 pstring string="Windows NT x86";
2226 *needed = 2*(strlen(string)+1);
2227 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2229 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2230 for (i=0; i<strlen(string); i++) {
2231 (*data)[2*i]=string[i];
2232 (*data)[2*i+1]='\0';
2237 return WERR_INVALID_PARAM;
2240 /********************************************************************
2241 * spoolss_getprinterdata
2242 ********************************************************************/
2244 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2246 POLICY_HND *handle = &q_u->handle;
2247 UNISTR2 *valuename = &q_u->valuename;
2248 uint32 in_size = q_u->size;
2249 uint32 *type = &r_u->type;
2250 uint32 *out_size = &r_u->size;
2251 uint8 **data = &r_u->data;
2252 uint32 *needed = &r_u->needed;
2255 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2256 NT_PRINTER_INFO_LEVEL *printer = NULL;
2260 * Reminder: when it's a string, the length is in BYTES
2261 * even if UNICODE is negociated.
2266 *out_size = in_size;
2268 /* in case of problem, return some default values */
2273 DEBUG(4,("_spoolss_getprinterdata\n"));
2276 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2277 status = WERR_BADFID;
2281 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2283 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2284 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2287 if ( !get_printer_snum(p,handle, &snum) ) {
2288 status = WERR_BADFID;
2292 status = get_a_printer(&printer, 2, lp_servicename(snum));
2293 if ( !W_ERROR_IS_OK(status) )
2296 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2298 if ( strequal(value, "ChangeId") ) {
2300 *needed = sizeof(uint32);
2301 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2302 status = WERR_NOMEM;
2305 **data = printer->info_2->changeid;
2309 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2312 if (*needed > *out_size)
2313 status = WERR_MORE_DATA;
2316 if ( !W_ERROR_IS_OK(status) )
2318 DEBUG(5, ("error: allocating %d\n", *out_size));
2320 /* reply this param doesn't exist */
2323 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2325 free_a_printer( &printer, 2 );
2334 /* cleanup & exit */
2337 free_a_printer( &printer, 2 );
2342 /*********************************************************
2343 Connect to the client machine.
2344 **********************************************************/
2346 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, const char *remote_machine)
2348 ZERO_STRUCTP(the_cli);
2349 if(cli_initialise(the_cli) == NULL) {
2350 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2354 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2355 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2356 cli_shutdown(the_cli);
2360 if (ismyip(the_cli->dest_ip)) {
2361 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2362 cli_shutdown(the_cli);
2366 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2367 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2368 cli_shutdown(the_cli);
2372 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2373 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2375 cli_shutdown(the_cli);
2379 the_cli->protocol = PROTOCOL_NT1;
2381 if (!cli_negprot(the_cli)) {
2382 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2383 cli_shutdown(the_cli);
2387 if (the_cli->protocol != PROTOCOL_NT1) {
2388 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2389 cli_shutdown(the_cli);
2394 * Do an anonymous session setup.
2397 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2398 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2399 cli_shutdown(the_cli);
2403 if (!(the_cli->sec_mode & 1)) {
2404 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2405 cli_shutdown(the_cli);
2409 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2410 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2411 cli_shutdown(the_cli);
2416 * Ok - we have an anonymous connection to the IPC$ share.
2417 * Now start the NT Domain stuff :-).
2420 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2421 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)));
2422 cli_nt_session_close(the_cli);
2423 cli_ulogoff(the_cli);
2424 cli_shutdown(the_cli);
2431 /***************************************************************************
2432 Connect to the client.
2433 ****************************************************************************/
2435 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2440 * If it's the first connection, contact the client
2441 * and connect to the IPC$ share anonumously
2443 if (smb_connections==0) {
2444 fstring unix_printer;
2446 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2448 if(!spoolss_connect_to_client(¬ify_cli, unix_printer))
2451 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2452 /* Tell the connections db we're now interested in printer
2453 * notify messages. */
2454 register_message_flags( True, FLAG_MSG_PRINTING );
2458 * Tell the specific printing tdb we want messages for this printer
2459 * by registering our PID.
2462 if (!print_notify_register_pid(snum))
2463 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2467 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2470 if (!W_ERROR_IS_OK(result))
2471 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2472 dos_errstr(result)));
2474 return (W_ERROR_IS_OK(result));
2477 /********************************************************************
2479 * ReplyFindFirstPrinterChangeNotifyEx
2481 * before replying OK: status=0 a rpc call is made to the workstation
2482 * asking ReplyOpenPrinter
2484 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2485 * called from api_spoolss_rffpcnex
2486 ********************************************************************/
2488 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2490 POLICY_HND *handle = &q_u->handle;
2491 uint32 flags = q_u->flags;
2492 uint32 options = q_u->options;
2493 UNISTR2 *localmachine = &q_u->localmachine;
2494 uint32 printerlocal = q_u->printerlocal;
2496 SPOOL_NOTIFY_OPTION *option = q_u->option;
2498 /* store the notify value in the printer struct */
2500 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2503 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2507 Printer->notify.flags=flags;
2508 Printer->notify.options=options;
2509 Printer->notify.printerlocal=printerlocal;
2511 if (Printer->notify.option)
2512 free_spool_notify_option(&Printer->notify.option);
2514 Printer->notify.option=dup_spool_notify_option(option);
2516 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2517 sizeof(Printer->notify.localmachine)-1);
2519 /* Connect to the client machine and send a ReplyOpenPrinter */
2521 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2523 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2524 !get_printer_snum(p, handle, &snum) )
2527 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2528 Printer->notify.printerlocal, 1,
2529 &Printer->notify.client_hnd))
2530 return WERR_SERVER_UNAVAILABLE;
2532 Printer->notify.client_connected=True;
2537 /*******************************************************************
2538 * fill a notify_info_data with the servername
2539 ********************************************************************/
2541 void spoolss_notify_server_name(int snum,
2542 SPOOL_NOTIFY_INFO_DATA *data,
2543 print_queue_struct *queue,
2544 NT_PRINTER_INFO_LEVEL *printer,
2545 TALLOC_CTX *mem_ctx)
2547 pstring temp_name, temp;
2550 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2552 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2554 data->notify_data.data.length = len;
2555 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2557 if (!data->notify_data.data.string) {
2558 data->notify_data.data.length = 0;
2562 memcpy(data->notify_data.data.string, temp, len);
2565 /*******************************************************************
2566 * fill a notify_info_data with the printername (not including the servername).
2567 ********************************************************************/
2569 void spoolss_notify_printer_name(int snum,
2570 SPOOL_NOTIFY_INFO_DATA *data,
2571 print_queue_struct *queue,
2572 NT_PRINTER_INFO_LEVEL *printer,
2573 TALLOC_CTX *mem_ctx)
2578 /* the notify name should not contain the \\server\ part */
2579 char *p = strrchr(printer->info_2->printername, '\\');
2582 p = printer->info_2->printername;
2587 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2589 data->notify_data.data.length = len;
2590 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2592 if (!data->notify_data.data.string) {
2593 data->notify_data.data.length = 0;
2597 memcpy(data->notify_data.data.string, temp, len);
2600 /*******************************************************************
2601 * fill a notify_info_data with the servicename
2602 ********************************************************************/
2604 void spoolss_notify_share_name(int snum,
2605 SPOOL_NOTIFY_INFO_DATA *data,
2606 print_queue_struct *queue,
2607 NT_PRINTER_INFO_LEVEL *printer,
2608 TALLOC_CTX *mem_ctx)
2613 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2615 data->notify_data.data.length = len;
2616 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2618 if (!data->notify_data.data.string) {
2619 data->notify_data.data.length = 0;
2623 memcpy(data->notify_data.data.string, temp, len);
2626 /*******************************************************************
2627 * fill a notify_info_data with the port name
2628 ********************************************************************/
2630 void spoolss_notify_port_name(int snum,
2631 SPOOL_NOTIFY_INFO_DATA *data,
2632 print_queue_struct *queue,
2633 NT_PRINTER_INFO_LEVEL *printer,
2634 TALLOC_CTX *mem_ctx)
2639 /* even if it's strange, that's consistant in all the code */
2641 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2643 data->notify_data.data.length = len;
2644 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2646 if (!data->notify_data.data.string) {
2647 data->notify_data.data.length = 0;
2651 memcpy(data->notify_data.data.string, temp, len);
2654 /*******************************************************************
2655 * fill a notify_info_data with the printername
2656 * but it doesn't exist, have to see what to do
2657 ********************************************************************/
2659 void spoolss_notify_driver_name(int snum,
2660 SPOOL_NOTIFY_INFO_DATA *data,
2661 print_queue_struct *queue,
2662 NT_PRINTER_INFO_LEVEL *printer,
2663 TALLOC_CTX *mem_ctx)
2668 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2670 data->notify_data.data.length = len;
2671 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2673 if (!data->notify_data.data.string) {
2674 data->notify_data.data.length = 0;
2678 memcpy(data->notify_data.data.string, temp, len);
2681 /*******************************************************************
2682 * fill a notify_info_data with the comment
2683 ********************************************************************/
2685 void spoolss_notify_comment(int snum,
2686 SPOOL_NOTIFY_INFO_DATA *data,
2687 print_queue_struct *queue,
2688 NT_PRINTER_INFO_LEVEL *printer,
2689 TALLOC_CTX *mem_ctx)
2694 if (*printer->info_2->comment == '\0')
2695 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2697 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2699 data->notify_data.data.length = len;
2700 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2702 if (!data->notify_data.data.string) {
2703 data->notify_data.data.length = 0;
2707 memcpy(data->notify_data.data.string, temp, len);
2710 /*******************************************************************
2711 * fill a notify_info_data with the comment
2712 * location = "Room 1, floor 2, building 3"
2713 ********************************************************************/
2715 void spoolss_notify_location(int snum,
2716 SPOOL_NOTIFY_INFO_DATA *data,
2717 print_queue_struct *queue,
2718 NT_PRINTER_INFO_LEVEL *printer,
2719 TALLOC_CTX *mem_ctx)
2724 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2726 data->notify_data.data.length = len;
2727 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2729 if (!data->notify_data.data.string) {
2730 data->notify_data.data.length = 0;
2734 memcpy(data->notify_data.data.string, temp, len);
2737 /*******************************************************************
2738 * fill a notify_info_data with the device mode
2739 * jfm:xxxx don't to it for know but that's a real problem !!!
2740 ********************************************************************/
2742 static void spoolss_notify_devmode(int snum,
2743 SPOOL_NOTIFY_INFO_DATA *data,
2744 print_queue_struct *queue,
2745 NT_PRINTER_INFO_LEVEL *printer,
2746 TALLOC_CTX *mem_ctx)
2750 /*******************************************************************
2751 * fill a notify_info_data with the separator file name
2752 ********************************************************************/
2754 void spoolss_notify_sepfile(int snum,
2755 SPOOL_NOTIFY_INFO_DATA *data,
2756 print_queue_struct *queue,
2757 NT_PRINTER_INFO_LEVEL *printer,
2758 TALLOC_CTX *mem_ctx)
2763 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2765 data->notify_data.data.length = len;
2766 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2768 if (!data->notify_data.data.string) {
2769 data->notify_data.data.length = 0;
2773 memcpy(data->notify_data.data.string, temp, len);
2776 /*******************************************************************
2777 * fill a notify_info_data with the print processor
2778 * jfm:xxxx return always winprint to indicate we don't do anything to it
2779 ********************************************************************/
2781 void spoolss_notify_print_processor(int snum,
2782 SPOOL_NOTIFY_INFO_DATA *data,
2783 print_queue_struct *queue,
2784 NT_PRINTER_INFO_LEVEL *printer,
2785 TALLOC_CTX *mem_ctx)
2790 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2792 data->notify_data.data.length = len;
2793 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2795 if (!data->notify_data.data.string) {
2796 data->notify_data.data.length = 0;
2800 memcpy(data->notify_data.data.string, temp, len);
2803 /*******************************************************************
2804 * fill a notify_info_data with the print processor options
2805 * jfm:xxxx send an empty string
2806 ********************************************************************/
2808 void spoolss_notify_parameters(int snum,
2809 SPOOL_NOTIFY_INFO_DATA *data,
2810 print_queue_struct *queue,
2811 NT_PRINTER_INFO_LEVEL *printer,
2812 TALLOC_CTX *mem_ctx)
2817 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2819 data->notify_data.data.length = len;
2820 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2822 if (!data->notify_data.data.string) {
2823 data->notify_data.data.length = 0;
2827 memcpy(data->notify_data.data.string, temp, len);
2830 /*******************************************************************
2831 * fill a notify_info_data with the data type
2832 * jfm:xxxx always send RAW as data type
2833 ********************************************************************/
2835 void spoolss_notify_datatype(int snum,
2836 SPOOL_NOTIFY_INFO_DATA *data,
2837 print_queue_struct *queue,
2838 NT_PRINTER_INFO_LEVEL *printer,
2839 TALLOC_CTX *mem_ctx)
2844 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2846 data->notify_data.data.length = len;
2847 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2849 if (!data->notify_data.data.string) {
2850 data->notify_data.data.length = 0;
2854 memcpy(data->notify_data.data.string, temp, len);
2857 /*******************************************************************
2858 * fill a notify_info_data with the security descriptor
2859 * jfm:xxxx send an null pointer to say no security desc
2860 * have to implement security before !
2861 ********************************************************************/
2863 static void spoolss_notify_security_desc(int snum,
2864 SPOOL_NOTIFY_INFO_DATA *data,
2865 print_queue_struct *queue,
2866 NT_PRINTER_INFO_LEVEL *printer,
2867 TALLOC_CTX *mem_ctx)
2869 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2870 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2873 /*******************************************************************
2874 * fill a notify_info_data with the attributes
2875 * jfm:xxxx a samba printer is always shared
2876 ********************************************************************/
2878 void spoolss_notify_attributes(int snum,
2879 SPOOL_NOTIFY_INFO_DATA *data,
2880 print_queue_struct *queue,
2881 NT_PRINTER_INFO_LEVEL *printer,
2882 TALLOC_CTX *mem_ctx)
2884 data->notify_data.value[0] = printer->info_2->attributes;
2885 data->notify_data.value[1] = 0;
2888 /*******************************************************************
2889 * fill a notify_info_data with the priority
2890 ********************************************************************/
2892 static void spoolss_notify_priority(int snum,
2893 SPOOL_NOTIFY_INFO_DATA *data,
2894 print_queue_struct *queue,
2895 NT_PRINTER_INFO_LEVEL *printer,
2896 TALLOC_CTX *mem_ctx)
2898 data->notify_data.value[0] = printer->info_2->priority;
2899 data->notify_data.value[1] = 0;
2902 /*******************************************************************
2903 * fill a notify_info_data with the default priority
2904 ********************************************************************/
2906 static void spoolss_notify_default_priority(int snum,
2907 SPOOL_NOTIFY_INFO_DATA *data,
2908 print_queue_struct *queue,
2909 NT_PRINTER_INFO_LEVEL *printer,
2910 TALLOC_CTX *mem_ctx)
2912 data->notify_data.value[0] = printer->info_2->default_priority;
2913 data->notify_data.value[1] = 0;
2916 /*******************************************************************
2917 * fill a notify_info_data with the start time
2918 ********************************************************************/
2920 static void spoolss_notify_start_time(int snum,
2921 SPOOL_NOTIFY_INFO_DATA *data,
2922 print_queue_struct *queue,
2923 NT_PRINTER_INFO_LEVEL *printer,
2924 TALLOC_CTX *mem_ctx)
2926 data->notify_data.value[0] = printer->info_2->starttime;
2927 data->notify_data.value[1] = 0;
2930 /*******************************************************************
2931 * fill a notify_info_data with the until time
2932 ********************************************************************/
2934 static void spoolss_notify_until_time(int snum,
2935 SPOOL_NOTIFY_INFO_DATA *data,
2936 print_queue_struct *queue,
2937 NT_PRINTER_INFO_LEVEL *printer,
2938 TALLOC_CTX *mem_ctx)
2940 data->notify_data.value[0] = printer->info_2->untiltime;
2941 data->notify_data.value[1] = 0;
2944 /*******************************************************************
2945 * fill a notify_info_data with the status
2946 ********************************************************************/
2948 static void spoolss_notify_status(int snum,
2949 SPOOL_NOTIFY_INFO_DATA *data,
2950 print_queue_struct *queue,
2951 NT_PRINTER_INFO_LEVEL *printer,
2952 TALLOC_CTX *mem_ctx)
2954 print_status_struct status;
2956 print_queue_length(snum, &status);
2957 data->notify_data.value[0]=(uint32) status.status;
2958 data->notify_data.value[1] = 0;
2961 /*******************************************************************
2962 * fill a notify_info_data with the number of jobs queued
2963 ********************************************************************/
2965 void spoolss_notify_cjobs(int snum,
2966 SPOOL_NOTIFY_INFO_DATA *data,
2967 print_queue_struct *queue,
2968 NT_PRINTER_INFO_LEVEL *printer,
2969 TALLOC_CTX *mem_ctx)
2971 data->notify_data.value[0] = print_queue_length(snum, NULL);
2972 data->notify_data.value[1] = 0;
2975 /*******************************************************************
2976 * fill a notify_info_data with the average ppm
2977 ********************************************************************/
2979 static void spoolss_notify_average_ppm(int snum,
2980 SPOOL_NOTIFY_INFO_DATA *data,
2981 print_queue_struct *queue,
2982 NT_PRINTER_INFO_LEVEL *printer,
2983 TALLOC_CTX *mem_ctx)
2985 /* always respond 8 pages per minutes */
2986 /* a little hard ! */
2987 data->notify_data.value[0] = printer->info_2->averageppm;
2988 data->notify_data.value[1] = 0;
2991 /*******************************************************************
2992 * fill a notify_info_data with username
2993 ********************************************************************/
2995 static void spoolss_notify_username(int snum,
2996 SPOOL_NOTIFY_INFO_DATA *data,
2997 print_queue_struct *queue,
2998 NT_PRINTER_INFO_LEVEL *printer,
2999 TALLOC_CTX *mem_ctx)
3004 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3006 data->notify_data.data.length = len;
3007 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3009 if (!data->notify_data.data.string) {
3010 data->notify_data.data.length = 0;
3014 memcpy(data->notify_data.data.string, temp, len);
3017 /*******************************************************************
3018 * fill a notify_info_data with job status
3019 ********************************************************************/
3021 static void spoolss_notify_job_status(int snum,
3022 SPOOL_NOTIFY_INFO_DATA *data,
3023 print_queue_struct *queue,
3024 NT_PRINTER_INFO_LEVEL *printer,
3025 TALLOC_CTX *mem_ctx)
3027 data->notify_data.value[0]=nt_printj_status(queue->status);
3028 data->notify_data.value[1] = 0;
3031 /*******************************************************************
3032 * fill a notify_info_data with job name
3033 ********************************************************************/
3035 static void spoolss_notify_job_name(int snum,
3036 SPOOL_NOTIFY_INFO_DATA *data,
3037 print_queue_struct *queue,
3038 NT_PRINTER_INFO_LEVEL *printer,
3039 TALLOC_CTX *mem_ctx)
3044 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3046 data->notify_data.data.length = len;
3047 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3049 if (!data->notify_data.data.string) {
3050 data->notify_data.data.length = 0;
3054 memcpy(data->notify_data.data.string, temp, len);
3057 /*******************************************************************
3058 * fill a notify_info_data with job status
3059 ********************************************************************/
3061 static void spoolss_notify_job_status_string(int snum,
3062 SPOOL_NOTIFY_INFO_DATA *data,
3063 print_queue_struct *queue,
3064 NT_PRINTER_INFO_LEVEL *printer,
3065 TALLOC_CTX *mem_ctx)
3068 * Now we're returning job status codes we just return a "" here. JRA.
3075 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3078 switch (queue->status) {
3083 p = ""; /* NT provides the paused string */
3092 #endif /* NO LONGER NEEDED. */
3094 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3096 data->notify_data.data.length = len;
3097 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3099 if (!data->notify_data.data.string) {
3100 data->notify_data.data.length = 0;
3104 memcpy(data->notify_data.data.string, temp, len);
3107 /*******************************************************************
3108 * fill a notify_info_data with job time
3109 ********************************************************************/
3111 static void spoolss_notify_job_time(int snum,
3112 SPOOL_NOTIFY_INFO_DATA *data,
3113 print_queue_struct *queue,
3114 NT_PRINTER_INFO_LEVEL *printer,
3115 TALLOC_CTX *mem_ctx)
3117 data->notify_data.value[0]=0x0;
3118 data->notify_data.value[1]=0;
3121 /*******************************************************************
3122 * fill a notify_info_data with job size
3123 ********************************************************************/
3125 static void spoolss_notify_job_size(int snum,
3126 SPOOL_NOTIFY_INFO_DATA *data,
3127 print_queue_struct *queue,
3128 NT_PRINTER_INFO_LEVEL *printer,
3129 TALLOC_CTX *mem_ctx)
3131 data->notify_data.value[0]=queue->size;
3132 data->notify_data.value[1]=0;
3135 /*******************************************************************
3136 * fill a notify_info_data with page info
3137 ********************************************************************/
3138 static void spoolss_notify_total_pages(int snum,
3139 SPOOL_NOTIFY_INFO_DATA *data,
3140 print_queue_struct *queue,
3141 NT_PRINTER_INFO_LEVEL *printer,
3142 TALLOC_CTX *mem_ctx)
3144 data->notify_data.value[0]=queue->page_count;
3145 data->notify_data.value[1]=0;
3148 /*******************************************************************
3149 * fill a notify_info_data with pages printed info.
3150 ********************************************************************/
3151 static void spoolss_notify_pages_printed(int snum,
3152 SPOOL_NOTIFY_INFO_DATA *data,
3153 print_queue_struct *queue,
3154 NT_PRINTER_INFO_LEVEL *printer,
3155 TALLOC_CTX *mem_ctx)
3157 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3158 data->notify_data.value[1]=0;
3161 /*******************************************************************
3162 Fill a notify_info_data with job position.
3163 ********************************************************************/
3165 static void spoolss_notify_job_position(int snum,
3166 SPOOL_NOTIFY_INFO_DATA *data,
3167 print_queue_struct *queue,
3168 NT_PRINTER_INFO_LEVEL *printer,
3169 TALLOC_CTX *mem_ctx)
3171 data->notify_data.value[0]=queue->job;
3172 data->notify_data.value[1]=0;
3175 /*******************************************************************
3176 Fill a notify_info_data with submitted time.
3177 ********************************************************************/
3179 static void spoolss_notify_submitted_time(int snum,
3180 SPOOL_NOTIFY_INFO_DATA *data,
3181 print_queue_struct *queue,
3182 NT_PRINTER_INFO_LEVEL *printer,
3183 TALLOC_CTX *mem_ctx)
3190 t=gmtime(&queue->time);
3192 len = sizeof(SYSTEMTIME);
3194 data->notify_data.data.length = len;
3195 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3197 if (!data->notify_data.data.string) {
3198 data->notify_data.data.length = 0;
3202 make_systemtime(&st, t);
3205 * Systemtime must be linearized as a set of UINT16's.
3206 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3209 p = (char *)data->notify_data.data.string;
3210 SSVAL(p, 0, st.year);
3211 SSVAL(p, 2, st.month);
3212 SSVAL(p, 4, st.dayofweek);
3213 SSVAL(p, 6, st.day);
3214 SSVAL(p, 8, st.hour);
3215 SSVAL(p, 10, st.minute);
3216 SSVAL(p, 12, st.second);
3217 SSVAL(p, 14, st.milliseconds);
3220 struct s_notify_info_data_table
3226 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3227 print_queue_struct *queue,
3228 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3231 /* A table describing the various print notification constants and
3232 whether the notification data is a pointer to a variable sized
3233 buffer, a one value uint32 or a two value uint32. */
3235 struct s_notify_info_data_table notify_info_data_table[] =
3237 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3238 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3239 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3240 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3241 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3242 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3243 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3244 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3245 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3246 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3247 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3248 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3249 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3250 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3251 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3263 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3264 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3265 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3266 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3267 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3268 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3269 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3270 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3271 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3272 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3273 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3274 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3275 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3276 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3277 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3278 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3279 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3280 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3281 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3282 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3285 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3288 /*******************************************************************
3289 Return the size of info_data structure.
3290 ********************************************************************/
3292 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3296 for (i = 0; i < sizeof(notify_info_data_table); i++)
3298 if ( (notify_info_data_table[i].type == type)
3299 && (notify_info_data_table[i].field == field) )
3301 switch(notify_info_data_table[i].size)
3303 case NOTIFY_ONE_VALUE:
3304 case NOTIFY_TWO_VALUE:
3309 /* The only pointer notify data I have seen on
3310 the wire is the submitted time and this has
3311 the notify size set to 4. -tpot */
3313 case NOTIFY_POINTER:
3316 case NOTIFY_SECDESC:
3322 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3327 /*******************************************************************
3328 Return the type of notify_info_data.
3329 ********************************************************************/
3331 static int type_of_notify_info_data(uint16 type, uint16 field)
3335 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3336 if (notify_info_data_table[i].type == type &&
3337 notify_info_data_table[i].field == field)
3338 return notify_info_data_table[i].size;
3344 /****************************************************************************
3345 ****************************************************************************/
3347 static int search_notify(uint16 type, uint16 field, int *value)
3351 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3352 if (notify_info_data_table[i].type == type &&
3353 notify_info_data_table[i].field == field &&
3354 notify_info_data_table[i].fn != NULL) {
3363 /****************************************************************************
3364 ****************************************************************************/
3366 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3368 info_data->type = type;
3369 info_data->field = field;
3370 info_data->reserved = 0;
3372 info_data->size = size_of_notify_info_data(type, field);
3373 info_data->enc_type = type_of_notify_info_data(type, field);
3380 /*******************************************************************
3382 * fill a notify_info struct with info asked
3384 ********************************************************************/
3386 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
3387 snum, SPOOL_NOTIFY_OPTION_TYPE
3388 *option_type, uint32 id,
3389 TALLOC_CTX *mem_ctx)
3395 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3396 NT_PRINTER_INFO_LEVEL *printer = NULL;
3397 print_queue_struct *queue=NULL;
3399 type=option_type->type;
3401 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3402 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3403 option_type->count, lp_servicename(snum)));
3405 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3408 for(field_num=0; field_num<option_type->count; field_num++)
3410 field = option_type->fields[field_num];
3412 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3414 if (!search_notify(type, field, &j) )
3417 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
3419 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3425 current_data = &info->data[info->count];
3427 construct_info_data(current_data, type, field, id);
3429 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3430 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3432 notify_info_data_table[j].fn(snum, current_data, queue,
3438 free_a_printer(&printer, 2);
3442 /*******************************************************************
3444 * fill a notify_info struct with info asked
3446 ********************************************************************/
3448 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3449 SPOOL_NOTIFY_INFO *info,
3450 NT_PRINTER_INFO_LEVEL *printer,
3451 int snum, SPOOL_NOTIFY_OPTION_TYPE
3452 *option_type, uint32 id,
3453 TALLOC_CTX *mem_ctx)
3459 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3461 DEBUG(4,("construct_notify_jobs_info\n"));
3463 type = option_type->type;
3465 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3466 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3467 option_type->count));
3469 for(field_num=0; field_num<option_type->count; field_num++) {
3470 field = option_type->fields[field_num];
3472 if (!search_notify(type, field, &j) )
3475 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3476 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3479 else info->data = tid;
3481 current_data=&(info->data[info->count]);
3483 construct_info_data(current_data, type, field, id);
3484 notify_info_data_table[j].fn(snum, current_data, queue,
3493 * JFM: The enumeration is not that simple, it's even non obvious.
3495 * let's take an example: I want to monitor the PRINTER SERVER for
3496 * the printer's name and the number of jobs currently queued.
3497 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3498 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3500 * I have 3 printers on the back of my server.
3502 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3505 * 1 printer 1 name 1
3506 * 2 printer 1 cjob 1
3507 * 3 printer 2 name 2
3508 * 4 printer 2 cjob 2
3509 * 5 printer 3 name 3
3510 * 6 printer 3 name 3
3512 * that's the print server case, the printer case is even worse.
3515 /*******************************************************************
3517 * enumerate all printers on the printserver
3518 * fill a notify_info struct with info asked
3520 ********************************************************************/
3522 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3523 SPOOL_NOTIFY_INFO *info,
3524 TALLOC_CTX *mem_ctx)
3527 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3528 int n_services=lp_numservices();
3531 SPOOL_NOTIFY_OPTION *option;
3532 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3534 DEBUG(4,("printserver_notify_info\n"));
3539 option=Printer->notify.option;
3545 for (i=0; i<option->count; i++) {
3546 option_type=&(option->ctr.type[i]);
3548 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3551 for (snum=0; snum<n_services; snum++)
3553 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3554 construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
3560 * Debugging information, don't delete.
3563 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3564 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3565 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3567 for (i=0; i<info->count; i++) {
3568 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3569 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3570 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3577 /*******************************************************************
3579 * fill a notify_info struct with info asked
3581 ********************************************************************/
3583 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3584 TALLOC_CTX *mem_ctx)
3587 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3590 SPOOL_NOTIFY_OPTION *option;
3591 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3593 print_queue_struct *queue=NULL;
3594 print_status_struct status;
3596 DEBUG(4,("printer_notify_info\n"));
3601 option=Printer->notify.option;
3607 get_printer_snum(p, hnd, &snum);
3609 for (i=0; i<option->count; i++) {
3610 option_type=&option->ctr.type[i];
3612 switch ( option_type->type ) {
3613 case PRINTER_NOTIFY_TYPE:
3614 if(construct_notify_printer_info(info, snum,
3620 case JOB_NOTIFY_TYPE: {
3621 NT_PRINTER_INFO_LEVEL *printer = NULL;
3623 count = print_queue_status(snum, &queue, &status);
3625 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3626 lp_servicename(snum))))
3629 for (j=0; j<count; j++) {
3630 construct_notify_jobs_info(&queue[j], info,
3637 free_a_printer(&printer, 2);
3647 * Debugging information, don't delete.
3650 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3651 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3652 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3654 for (i=0; i<info->count; i++) {
3655 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3656 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3657 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3663 /********************************************************************
3665 ********************************************************************/
3667 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3669 POLICY_HND *handle = &q_u->handle;
3670 SPOOL_NOTIFY_INFO *info = &r_u->info;
3672 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3673 WERROR result = WERR_BADFID;
3675 /* we always have a NOTIFY_INFO struct */
3679 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3680 OUR_HANDLE(handle)));
3684 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3687 * We are now using the change value, and
3688 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3689 * I don't have a global notification system, I'm sending back all the
3690 * informations even when _NOTHING_ has changed.
3693 /* We need to keep track of the change value to send back in
3694 RRPCN replies otherwise our updates are ignored. */
3696 if (Printer->notify.client_connected) {
3697 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3698 Printer->notify.change = q_u->change;
3701 /* just ignore the SPOOL_NOTIFY_OPTION */
3703 switch (Printer->printer_type) {
3704 case PRINTER_HANDLE_IS_PRINTSERVER:
3705 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3708 case PRINTER_HANDLE_IS_PRINTER:
3709 result = printer_notify_info(p, handle, info, p->mem_ctx);
3717 /********************************************************************
3718 * construct_printer_info_0
3719 * fill a printer_info_0 struct
3720 ********************************************************************/
3722 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3726 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3727 counter_printer_0 *session_counter;
3728 uint32 global_counter;
3731 print_status_struct status;
3733 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3736 count = print_queue_length(snum, &status);
3738 /* check if we already have a counter for this printer */
3739 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3741 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3742 if (session_counter->snum == snum)
3746 /* it's the first time, add it to the list */
3747 if (session_counter==NULL) {
3748 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3749 free_a_printer(&ntprinter, 2);
3752 ZERO_STRUCTP(session_counter);
3753 session_counter->snum=snum;
3754 session_counter->counter=0;
3755 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3759 session_counter->counter++;
3762 * the global_counter should be stored in a TDB as it's common to all the clients
3763 * and should be zeroed on samba startup
3765 global_counter=session_counter->counter;
3767 pstrcpy(chaine,ntprinter->info_2->printername);
3769 init_unistr(&printer->printername, chaine);
3771 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3772 init_unistr(&printer->servername, chaine);
3774 printer->cjobs = count;
3775 printer->total_jobs = 0;
3776 printer->total_bytes = 0;
3778 setuptime = (time_t)ntprinter->info_2->setuptime;
3779 t=gmtime(&setuptime);
3781 printer->year = t->tm_year+1900;
3782 printer->month = t->tm_mon+1;
3783 printer->dayofweek = t->tm_wday;
3784 printer->day = t->tm_mday;
3785 printer->hour = t->tm_hour;
3786 printer->minute = t->tm_min;
3787 printer->second = t->tm_sec;
3788 printer->milliseconds = 0;
3790 printer->global_counter = global_counter;
3791 printer->total_pages = 0;
3792 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3793 printer->major_version = 0x0004; /* NT 4 */
3794 printer->build_version = 0x0565; /* build 1381 */
3796 printer->major_version = 0x0005; /* NT 5 */
3797 printer->build_version = 0x0893; /* build 2195 */
3799 printer->unknown7 = 0x1;
3800 printer->unknown8 = 0x0;
3801 printer->unknown9 = 0x0;
3802 printer->session_counter = session_counter->counter;
3803 printer->unknown11 = 0x0;
3804 printer->printer_errors = 0x0; /* number of print failure */
3805 printer->unknown13 = 0x0;
3806 printer->unknown14 = 0x1;
3807 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3808 printer->unknown16 = 0x0;
3809 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3810 printer->unknown18 = 0x0;
3811 printer->status = nt_printq_status(status.status);
3812 printer->unknown20 = 0x0;
3813 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3814 printer->unknown22 = 0x0;
3815 printer->unknown23 = 0x6; /* 6 ???*/
3816 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3817 printer->unknown25 = 0;
3818 printer->unknown26 = 0;
3819 printer->unknown27 = 0;
3820 printer->unknown28 = 0;
3821 printer->unknown29 = 0;
3823 free_a_printer(&ntprinter,2);
3827 /********************************************************************
3828 * construct_printer_info_1
3829 * fill a printer_info_1 struct
3830 ********************************************************************/
3831 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3835 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3837 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3840 printer->flags=flags;
3842 if (*ntprinter->info_2->comment == '\0') {
3843 init_unistr(&printer->comment, lp_comment(snum));
3844 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3845 ntprinter->info_2->drivername, lp_comment(snum));
3848 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3849 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3850 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3853 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3855 init_unistr(&printer->description, chaine);
3856 init_unistr(&printer->name, chaine2);
3858 free_a_printer(&ntprinter,2);
3863 /****************************************************************************
3864 Free a DEVMODE struct.
3865 ****************************************************************************/
3867 static void free_dev_mode(DEVICEMODE *dev)
3872 SAFE_FREE(dev->private);
3877 /****************************************************************************
3878 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3879 should be valid upon entry
3880 ****************************************************************************/
3882 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
3884 if ( !devmode || !ntdevmode )
3887 init_unistr(&devmode->devicename, ntdevmode->devicename);
3889 init_unistr(&devmode->formname, ntdevmode->formname);
3891 devmode->specversion = ntdevmode->specversion;
3892 devmode->driverversion = ntdevmode->driverversion;
3893 devmode->size = ntdevmode->size;
3894 devmode->driverextra = ntdevmode->driverextra;
3895 devmode->fields = ntdevmode->fields;
3897 devmode->orientation = ntdevmode->orientation;
3898 devmode->papersize = ntdevmode->papersize;
3899 devmode->paperlength = ntdevmode->paperlength;
3900 devmode->paperwidth = ntdevmode->paperwidth;
3901 devmode->scale = ntdevmode->scale;
3902 devmode->copies = ntdevmode->copies;
3903 devmode->defaultsource = ntdevmode->defaultsource;
3904 devmode->printquality = ntdevmode->printquality;
3905 devmode->color = ntdevmode->color;
3906 devmode->duplex = ntdevmode->duplex;
3907 devmode->yresolution = ntdevmode->yresolution;
3908 devmode->ttoption = ntdevmode->ttoption;
3909 devmode->collate = ntdevmode->collate;
3910 devmode->icmmethod = ntdevmode->icmmethod;
3911 devmode->icmintent = ntdevmode->icmintent;
3912 devmode->mediatype = ntdevmode->mediatype;
3913 devmode->dithertype = ntdevmode->dithertype;
3915 if (ntdevmode->private != NULL) {
3916 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3923 /****************************************************************************
3924 Create a DEVMODE struct. Returns malloced memory.
3925 ****************************************************************************/
3927 DEVICEMODE *construct_dev_mode(int snum)
3929 NT_PRINTER_INFO_LEVEL *printer = NULL;
3930 DEVICEMODE *devmode = NULL;
3932 DEBUG(7,("construct_dev_mode\n"));
3934 DEBUGADD(8,("getting printer characteristics\n"));
3936 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3939 if ( !printer->info_2->devmode ) {
3940 DEBUG(5, ("BONG! There was no device mode!\n"));
3944 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3945 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3949 ZERO_STRUCTP(devmode);
3951 DEBUGADD(8,("loading DEVICEMODE\n"));
3953 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
3954 free_dev_mode( devmode );
3959 free_a_printer(&printer,2);
3964 /********************************************************************
3965 * construct_printer_info_2
3966 * fill a printer_info_2 struct
3967 ********************************************************************/
3969 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3972 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3974 print_status_struct status;
3976 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3979 count = print_queue_length(snum, &status);
3981 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3982 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3983 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3984 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3985 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3987 if (*ntprinter->info_2->comment == '\0')
3988 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3990 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3992 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3993 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3994 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3995 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3996 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3998 printer->attributes = ntprinter->info_2->attributes;
4000 printer->priority = ntprinter->info_2->priority; /* priority */
4001 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4002 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4003 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4004 printer->status = nt_printq_status(status.status); /* status */
4005 printer->cjobs = count; /* jobs */
4006 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4008 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4009 DEBUG(8, ("Returning NULL Devicemode!\n"));
4012 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4013 /* steal the printer info sec_desc structure. [badly done]. */
4014 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4015 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4016 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4017 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4020 printer->secdesc = NULL;
4023 free_a_printer(&ntprinter, 2);
4027 /********************************************************************
4028 * construct_printer_info_3
4029 * fill a printer_info_3 struct
4030 ********************************************************************/
4032 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
4034 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4035 PRINTER_INFO_3 *printer = NULL;
4037 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4041 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4042 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4046 ZERO_STRUCTP(printer);
4048 printer->flags = 4; /* These are the components of the SD we are returning. */
4049 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4050 /* steal the printer info sec_desc structure. [badly done]. */
4051 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4055 * Set the flags for the components we are returning.
4058 if (printer->secdesc->owner_sid)
4059 printer->flags |= OWNER_SECURITY_INFORMATION;
4061 if (printer->secdesc->grp_sid)
4062 printer->flags |= GROUP_SECURITY_INFORMATION;
4064 if (printer->secdesc->dacl)
4065 printer->flags |= DACL_SECURITY_INFORMATION;
4067 if (printer->secdesc->sacl)
4068 printer->flags |= SACL_SECURITY_INFORMATION;
4071 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4072 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4073 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4076 free_a_printer(&ntprinter, 2);
4078 *pp_printer = printer;
4082 /********************************************************************
4083 * construct_printer_info_4
4084 * fill a printer_info_4 struct
4085 ********************************************************************/
4087 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
4089 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4091 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4094 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4095 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4096 printer->attributes = ntprinter->info_2->attributes;
4098 free_a_printer(&ntprinter, 2);
4102 /********************************************************************
4103 * construct_printer_info_5
4104 * fill a printer_info_5 struct
4105 ********************************************************************/
4107 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
4109 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4111 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4114 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4115 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
4116 printer->attributes = ntprinter->info_2->attributes;
4117 printer->device_not_selected_timeout = 0x3a98;
4118 printer->transmission_retry_timeout = 0xafc8;
4120 free_a_printer(&ntprinter, 2);
4124 /********************************************************************
4125 Spoolss_enumprinters.
4126 ********************************************************************/
4128 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4132 int n_services=lp_numservices();
4133 PRINTER_INFO_1 *tp, *printers=NULL;
4134 PRINTER_INFO_1 current_prt;
4136 DEBUG(4,("enum_all_printers_info_1\n"));
4138 for (snum=0; snum<n_services; snum++) {
4139 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4140 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4142 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
4143 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4144 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4145 SAFE_FREE(printers);
4150 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4152 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4158 /* check the required size. */
4159 for (i=0; i<*returned; i++)
4160 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4162 if (!alloc_buffer_size(buffer, *needed))
4163 return WERR_INSUFFICIENT_BUFFER;
4165 /* fill the buffer with the structures */
4166 for (i=0; i<*returned; i++)
4167 smb_io_printer_info_1("", buffer, &printers[i], 0);
4170 SAFE_FREE(printers);
4172 if (*needed > offered) {
4174 return WERR_INSUFFICIENT_BUFFER;
4180 /********************************************************************
4181 enum_all_printers_info_1_local.
4182 *********************************************************************/
4184 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4186 DEBUG(4,("enum_all_printers_info_1_local\n"));
4188 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4191 /********************************************************************
4192 enum_all_printers_info_1_name.
4193 *********************************************************************/
4195 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4199 DEBUG(4,("enum_all_printers_info_1_name\n"));
4201 if ((name[0] == '\\') && (name[1] == '\\'))
4204 if (is_myname_or_ipaddr(s)) {
4205 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4208 return WERR_INVALID_NAME;
4211 /********************************************************************
4212 enum_all_printers_info_1_remote.
4213 *********************************************************************/
4215 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4217 PRINTER_INFO_1 *printer;
4218 fstring printername;
4221 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4223 /* JFM: currently it's more a place holder than anything else.
4224 * In the spooler world there is a notion of server registration.
4225 * the print servers are registring (sp ?) on the PDC (in the same domain)
4227 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4230 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4235 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4236 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4237 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4239 init_unistr(&printer->description, desc);
4240 init_unistr(&printer->name, printername);
4241 init_unistr(&printer->comment, comment);
4242 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4244 /* check the required size. */
4245 *needed += spoolss_size_printer_info_1(printer);
4247 if (!alloc_buffer_size(buffer, *needed)) {
4249 return WERR_INSUFFICIENT_BUFFER;
4252 /* fill the buffer with the structures */
4253 smb_io_printer_info_1("", buffer, printer, 0);
4258 if (*needed > offered) {
4260 return WERR_INSUFFICIENT_BUFFER;
4266 /********************************************************************
4267 enum_all_printers_info_1_network.
4268 *********************************************************************/
4270 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4274 DEBUG(4,("enum_all_printers_info_1_network\n"));
4276 /* If we respond to a enum_printers level 1 on our name with flags
4277 set to PRINTER_ENUM_REMOTE with a list of printers then these
4278 printers incorrectly appear in the APW browse list.
4279 Specifically the printers for the server appear at the workgroup
4280 level where all the other servers in the domain are
4281 listed. Windows responds to this call with a
4282 WERR_CAN_NOT_COMPLETE so we should do the same. */
4284 if (name[0] == '\\' && name[1] == '\\')
4287 if (is_myname_or_ipaddr(s))
4288 return WERR_CAN_NOT_COMPLETE;
4290 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4293 /********************************************************************
4294 * api_spoolss_enumprinters
4296 * called from api_spoolss_enumprinters (see this to understand)
4297 ********************************************************************/
4299 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4303 int n_services=lp_numservices();
4304 PRINTER_INFO_2 *tp, *printers=NULL;
4305 PRINTER_INFO_2 current_prt;
4307 for (snum=0; snum<n_services; snum++) {
4308 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4309 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4311 if (construct_printer_info_2(¤t_prt, snum)) {
4312 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4313 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4314 SAFE_FREE(printers);
4319 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4320 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4326 /* check the required size. */
4327 for (i=0; i<*returned; i++)
4328 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4330 if (!alloc_buffer_size(buffer, *needed)) {
4331 for (i=0; i<*returned; i++) {
4332 free_devmode(printers[i].devmode);
4334 SAFE_FREE(printers);
4335 return WERR_INSUFFICIENT_BUFFER;
4338 /* fill the buffer with the structures */
4339 for (i=0; i<*returned; i++)
4340 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4343 for (i=0; i<*returned; i++) {
4344 free_devmode(printers[i].devmode);
4346 SAFE_FREE(printers);
4348 if (*needed > offered) {
4350 return WERR_INSUFFICIENT_BUFFER;
4356 /********************************************************************
4357 * handle enumeration of printers at level 1
4358 ********************************************************************/
4360 static WERROR enumprinters_level1( uint32 flags, fstring name,
4361 NEW_BUFFER *buffer, uint32 offered,
4362 uint32 *needed, uint32 *returned)
4364 /* Not all the flags are equals */
4366 if (flags & PRINTER_ENUM_LOCAL)
4367 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4369 if (flags & PRINTER_ENUM_NAME)
4370 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4372 if (flags & PRINTER_ENUM_REMOTE)
4373 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4375 if (flags & PRINTER_ENUM_NETWORK)
4376 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4378 return WERR_OK; /* NT4sp5 does that */
4381 /********************************************************************
4382 * handle enumeration of printers at level 2
4383 ********************************************************************/
4385 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4386 NEW_BUFFER *buffer, uint32 offered,
4387 uint32 *needed, uint32 *returned)
4389 char *s = servername;
4391 if (flags & PRINTER_ENUM_LOCAL) {
4392 return enum_all_printers_info_2(buffer, offered, needed, returned);
4395 if (flags & PRINTER_ENUM_NAME) {
4396 if ((servername[0] == '\\') && (servername[1] == '\\'))
4398 if (is_myname_or_ipaddr(s))
4399 return enum_all_printers_info_2(buffer, offered, needed, returned);
4401 return WERR_INVALID_NAME;
4404 if (flags & PRINTER_ENUM_REMOTE)
4405 return WERR_UNKNOWN_LEVEL;
4410 /********************************************************************
4411 * handle enumeration of printers at level 5
4412 ********************************************************************/
4414 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4415 NEW_BUFFER *buffer, uint32 offered,
4416 uint32 *needed, uint32 *returned)
4418 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4422 /********************************************************************
4423 * api_spoolss_enumprinters
4425 * called from api_spoolss_enumprinters (see this to understand)
4426 ********************************************************************/
4428 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4430 uint32 flags = q_u->flags;
4431 UNISTR2 *servername = &q_u->servername;
4432 uint32 level = q_u->level;
4433 NEW_BUFFER *buffer = NULL;
4434 uint32 offered = q_u->offered;
4435 uint32 *needed = &r_u->needed;
4436 uint32 *returned = &r_u->returned;
4440 /* that's an [in out] buffer */
4441 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4442 buffer = r_u->buffer;
4444 DEBUG(4,("_spoolss_enumprinters\n"));
4451 * flags==PRINTER_ENUM_NAME
4452 * if name=="" then enumerates all printers
4453 * if name!="" then enumerate the printer
4454 * flags==PRINTER_ENUM_REMOTE
4455 * name is NULL, enumerate printers
4456 * Level 2: name!="" enumerates printers, name can't be NULL
4457 * Level 3: doesn't exist
4458 * Level 4: does a local registry lookup
4459 * Level 5: same as Level 2
4462 unistr2_to_ascii(name, servername, sizeof(name)-1);
4467 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4469 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4471 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4476 return WERR_UNKNOWN_LEVEL;
4479 /****************************************************************************
4480 ****************************************************************************/
4482 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4484 PRINTER_INFO_0 *printer=NULL;
4486 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4489 construct_printer_info_0(printer, snum);
4491 /* check the required size. */
4492 *needed += spoolss_size_printer_info_0(printer);
4494 if (!alloc_buffer_size(buffer, *needed)) {
4496 return WERR_INSUFFICIENT_BUFFER;
4499 /* fill the buffer with the structures */
4500 smb_io_printer_info_0("", buffer, printer, 0);
4505 if (*needed > offered) {
4506 return WERR_INSUFFICIENT_BUFFER;
4512 /****************************************************************************
4513 ****************************************************************************/
4515 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4517 PRINTER_INFO_1 *printer=NULL;
4519 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4522 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4524 /* check the required size. */
4525 *needed += spoolss_size_printer_info_1(printer);
4527 if (!alloc_buffer_size(buffer, *needed)) {
4529 return WERR_INSUFFICIENT_BUFFER;
4532 /* fill the buffer with the structures */
4533 smb_io_printer_info_1("", buffer, printer, 0);
4538 if (*needed > offered) {
4539 return WERR_INSUFFICIENT_BUFFER;
4545 /****************************************************************************
4546 ****************************************************************************/
4548 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4550 PRINTER_INFO_2 *printer=NULL;
4552 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4555 construct_printer_info_2(printer, snum);
4557 /* check the required size. */
4558 *needed += spoolss_size_printer_info_2(printer);
4560 if (!alloc_buffer_size(buffer, *needed)) {
4561 free_printer_info_2(printer);
4562 return WERR_INSUFFICIENT_BUFFER;
4565 /* fill the buffer with the structures */
4566 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4567 free_printer_info_2(printer);
4572 free_printer_info_2(printer);
4574 if (*needed > offered) {
4575 return WERR_INSUFFICIENT_BUFFER;
4581 /****************************************************************************
4582 ****************************************************************************/
4584 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4586 PRINTER_INFO_3 *printer=NULL;
4588 if (!construct_printer_info_3(&printer, snum))
4591 /* check the required size. */
4592 *needed += spoolss_size_printer_info_3(printer);
4594 if (!alloc_buffer_size(buffer, *needed)) {
4595 free_printer_info_3(printer);
4596 return WERR_INSUFFICIENT_BUFFER;
4599 /* fill the buffer with the structures */
4600 smb_io_printer_info_3("", buffer, printer, 0);
4603 free_printer_info_3(printer);
4605 if (*needed > offered) {
4606 return WERR_INSUFFICIENT_BUFFER;
4612 /****************************************************************************
4613 ****************************************************************************/
4615 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4617 PRINTER_INFO_4 *printer=NULL;
4619 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4622 if (!construct_printer_info_4(printer, snum))
4625 /* check the required size. */
4626 *needed += spoolss_size_printer_info_4(printer);
4628 if (!alloc_buffer_size(buffer, *needed)) {
4629 free_printer_info_4(printer);
4630 return WERR_INSUFFICIENT_BUFFER;
4633 /* fill the buffer with the structures */
4634 smb_io_printer_info_4("", buffer, printer, 0);
4637 free_printer_info_4(printer);
4639 if (*needed > offered) {
4640 return WERR_INSUFFICIENT_BUFFER;
4646 /****************************************************************************
4647 ****************************************************************************/
4649 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4651 PRINTER_INFO_5 *printer=NULL;
4653 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4656 if (!construct_printer_info_5(printer, snum))
4659 /* check the required size. */
4660 *needed += spoolss_size_printer_info_5(printer);
4662 if (!alloc_buffer_size(buffer, *needed)) {
4663 free_printer_info_5(printer);
4664 return WERR_INSUFFICIENT_BUFFER;
4667 /* fill the buffer with the structures */
4668 smb_io_printer_info_5("", buffer, printer, 0);
4671 free_printer_info_5(printer);
4673 if (*needed > offered) {
4674 return WERR_INSUFFICIENT_BUFFER;
4680 /****************************************************************************
4681 ****************************************************************************/
4683 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4685 POLICY_HND *handle = &q_u->handle;
4686 uint32 level = q_u->level;
4687 NEW_BUFFER *buffer = NULL;
4688 uint32 offered = q_u->offered;
4689 uint32 *needed = &r_u->needed;
4693 /* that's an [in out] buffer */
4694 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4695 buffer = r_u->buffer;
4699 if (!get_printer_snum(p, handle, &snum))
4704 return getprinter_level_0(snum, buffer, offered, needed);
4706 return getprinter_level_1(snum, buffer, offered, needed);
4708 return getprinter_level_2(snum, buffer, offered, needed);
4710 return getprinter_level_3(snum, buffer, offered, needed);
4712 return getprinter_level_4(snum, buffer, offered, needed);
4714 return getprinter_level_5(snum, buffer, offered, needed);
4716 return WERR_UNKNOWN_LEVEL;
4719 /********************************************************************
4720 * fill a DRIVER_INFO_1 struct
4721 ********************************************************************/
4723 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4725 init_unistr( &info->name, driver.info_3->name);
4728 /********************************************************************
4729 * construct_printer_driver_info_1
4730 ********************************************************************/
4732 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4734 NT_PRINTER_INFO_LEVEL *printer = NULL;
4735 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4737 ZERO_STRUCT(driver);
4739 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4740 return WERR_INVALID_PRINTER_NAME;
4742 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4743 return WERR_UNKNOWN_PRINTER_DRIVER;
4745 fill_printer_driver_info_1(info, driver, servername, architecture);
4747 free_a_printer(&printer,2);
4752 /********************************************************************
4753 * construct_printer_driver_info_2
4754 * fill a printer_info_2 struct
4755 ********************************************************************/
4757 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4761 info->version=driver.info_3->cversion;
4763 init_unistr( &info->name, driver.info_3->name );
4764 init_unistr( &info->architecture, driver.info_3->environment );
4767 if (strlen(driver.info_3->driverpath)) {
4768 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4769 init_unistr( &info->driverpath, temp );
4771 init_unistr( &info->driverpath, "" );
4773 if (strlen(driver.info_3->datafile)) {
4774 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4775 init_unistr( &info->datafile, temp );
4777 init_unistr( &info->datafile, "" );
4779 if (strlen(driver.info_3->configfile)) {
4780 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4781 init_unistr( &info->configfile, temp );
4783 init_unistr( &info->configfile, "" );
4786 /********************************************************************
4787 * construct_printer_driver_info_2
4788 * fill a printer_info_2 struct
4789 ********************************************************************/
4791 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4793 NT_PRINTER_INFO_LEVEL *printer = NULL;
4794 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4796 ZERO_STRUCT(printer);
4797 ZERO_STRUCT(driver);
4799 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4800 return WERR_INVALID_PRINTER_NAME;
4802 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4803 return WERR_UNKNOWN_PRINTER_DRIVER;
4805 fill_printer_driver_info_2(info, driver, servername);
4807 free_a_printer(&printer,2);
4812 /********************************************************************
4813 * copy a strings array and convert to UNICODE
4815 * convert an array of ascii string to a UNICODE string
4816 ********************************************************************/
4818 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4826 DEBUG(6,("init_unistr_array\n"));
4837 v = ""; /* hack to handle null lists */
4840 /* hack to allow this to be used in places other than when generating
4841 the list of dependent files */
4844 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4848 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4850 if ( (tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4851 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4859 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4864 (*uni_array)[j]=0x0000;
4867 DEBUGADD(6,("last one:done\n"));
4869 /* return size of array in uint16's */
4874 /********************************************************************
4875 * construct_printer_info_3
4876 * fill a printer_info_3 struct
4877 ********************************************************************/
4879 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4885 info->version=driver.info_3->cversion;
4887 init_unistr( &info->name, driver.info_3->name );
4888 init_unistr( &info->architecture, driver.info_3->environment );
4890 if (strlen(driver.info_3->driverpath)) {
4891 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4892 init_unistr( &info->driverpath, temp );
4894 init_unistr( &info->driverpath, "" );
4896 if (strlen(driver.info_3->datafile)) {
4897 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4898 init_unistr( &info->datafile, temp );
4900 init_unistr( &info->datafile, "" );
4902 if (strlen(driver.info_3->configfile)) {
4903 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4904 init_unistr( &info->configfile, temp );
4906 init_unistr( &info->configfile, "" );
4908 if (strlen(driver.info_3->helpfile)) {
4909 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4910 init_unistr( &info->helpfile, temp );
4912 init_unistr( &info->helpfile, "" );
4914 init_unistr( &info->monitorname, driver.info_3->monitorname );
4915 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4917 info->dependentfiles=NULL;
4918 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4921 /********************************************************************
4922 * construct_printer_info_3
4923 * fill a printer_info_3 struct
4924 ********************************************************************/
4926 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4928 NT_PRINTER_INFO_LEVEL *printer = NULL;
4929 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4931 ZERO_STRUCT(driver);
4933 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4934 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4935 if (!W_ERROR_IS_OK(status))
4936 return WERR_INVALID_PRINTER_NAME;
4938 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4939 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4944 * I put this code in during testing. Helpful when commenting out the
4945 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4946 * as win2k always queries the driver using an infor level of 6.
4947 * I've left it in (but ifdef'd out) because I'll probably
4948 * use it in experimentation again in the future. --jerry 22/01/2002
4951 if (!W_ERROR_IS_OK(status)) {
4953 * Is this a W2k client ?
4956 /* Yes - try again with a WinNT driver. */
4958 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4959 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4963 if (!W_ERROR_IS_OK(status)) {
4964 free_a_printer(&printer,2);
4965 return WERR_UNKNOWN_PRINTER_DRIVER;
4973 fill_printer_driver_info_3(info, driver, servername);
4975 free_a_printer(&printer,2);
4980 /********************************************************************
4981 * construct_printer_info_6
4982 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4983 ********************************************************************/
4985 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4991 memset(&nullstr, '\0', sizeof(fstring));
4993 info->version=driver.info_3->cversion;
4995 init_unistr( &info->name, driver.info_3->name );
4996 init_unistr( &info->architecture, driver.info_3->environment );
4998 if (strlen(driver.info_3->driverpath)) {
4999 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5000 init_unistr( &info->driverpath, temp );
5002 init_unistr( &info->driverpath, "" );
5004 if (strlen(driver.info_3->datafile)) {
5005 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5006 init_unistr( &info->datafile, temp );
5008 init_unistr( &info->datafile, "" );
5010 if (strlen(driver.info_3->configfile)) {
5011 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5012 init_unistr( &info->configfile, temp );
5014 init_unistr( &info->configfile, "" );
5016 if (strlen(driver.info_3->helpfile)) {
5017 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5018 init_unistr( &info->helpfile, temp );
5020 init_unistr( &info->helpfile, "" );
5022 init_unistr( &info->monitorname, driver.info_3->monitorname );
5023 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5025 info->dependentfiles = NULL;
5026 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5028 info->previousdrivernames=NULL;
5029 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5031 info->driver_date.low=0;
5032 info->driver_date.high=0;
5035 info->driver_version_low=0;
5036 info->driver_version_high=0;
5038 init_unistr( &info->mfgname, "");
5039 init_unistr( &info->oem_url, "");
5040 init_unistr( &info->hardware_id, "");
5041 init_unistr( &info->provider, "");
5044 /********************************************************************
5045 * construct_printer_info_6
5046 * fill a printer_info_6 struct
5047 ********************************************************************/
5049 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5050 fstring servername, fstring architecture, uint32 version)
5052 NT_PRINTER_INFO_LEVEL *printer = NULL;
5053 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5056 ZERO_STRUCT(driver);
5058 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5060 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5062 if (!W_ERROR_IS_OK(status))
5063 return WERR_INVALID_PRINTER_NAME;
5065 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5067 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5069 if (!W_ERROR_IS_OK(status))
5072 * Is this a W2k client ?
5076 free_a_printer(&printer,2);
5077 return WERR_UNKNOWN_PRINTER_DRIVER;
5080 /* Yes - try again with a WinNT driver. */
5082 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5083 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5084 if (!W_ERROR_IS_OK(status)) {
5085 free_a_printer(&printer,2);
5086 return WERR_UNKNOWN_PRINTER_DRIVER;
5090 fill_printer_driver_info_6(info, driver, servername);
5092 free_a_printer(&printer,2);
5097 /****************************************************************************
5098 ****************************************************************************/
5100 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5102 SAFE_FREE(info->dependentfiles);
5105 /****************************************************************************
5106 ****************************************************************************/
5108 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5110 SAFE_FREE(info->dependentfiles);
5114 /****************************************************************************
5115 ****************************************************************************/
5117 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5119 DRIVER_INFO_1 *info=NULL;
5122 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5125 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5126 if (!W_ERROR_IS_OK(status)) {
5131 /* check the required size. */
5132 *needed += spoolss_size_printer_driver_info_1(info);
5134 if (!alloc_buffer_size(buffer, *needed)) {
5136 return WERR_INSUFFICIENT_BUFFER;
5139 /* fill the buffer with the structures */
5140 smb_io_printer_driver_info_1("", buffer, info, 0);
5145 if (*needed > offered)
5146 return WERR_INSUFFICIENT_BUFFER;
5151 /****************************************************************************
5152 ****************************************************************************/
5154 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5156 DRIVER_INFO_2 *info=NULL;
5159 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5162 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5163 if (!W_ERROR_IS_OK(status)) {
5168 /* check the required size. */
5169 *needed += spoolss_size_printer_driver_info_2(info);
5171 if (!alloc_buffer_size(buffer, *needed)) {
5173 return WERR_INSUFFICIENT_BUFFER;
5176 /* fill the buffer with the structures */
5177 smb_io_printer_driver_info_2("", buffer, info, 0);
5182 if (*needed > offered)
5183 return WERR_INSUFFICIENT_BUFFER;
5188 /****************************************************************************
5189 ****************************************************************************/
5191 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5198 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5199 if (!W_ERROR_IS_OK(status)) {
5203 /* check the required size. */
5204 *needed += spoolss_size_printer_driver_info_3(&info);
5206 if (!alloc_buffer_size(buffer, *needed)) {
5207 free_printer_driver_info_3(&info);
5208 return WERR_INSUFFICIENT_BUFFER;
5211 /* fill the buffer with the structures */
5212 smb_io_printer_driver_info_3("", buffer, &info, 0);
5214 free_printer_driver_info_3(&info);
5216 if (*needed > offered)
5217 return WERR_INSUFFICIENT_BUFFER;
5222 /****************************************************************************
5223 ****************************************************************************/
5225 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5232 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5233 if (!W_ERROR_IS_OK(status)) {
5237 /* check the required size. */
5238 *needed += spoolss_size_printer_driver_info_6(&info);
5240 if (!alloc_buffer_size(buffer, *needed)) {
5241 free_printer_driver_info_6(&info);
5242 return WERR_INSUFFICIENT_BUFFER;
5245 /* fill the buffer with the structures */
5246 smb_io_printer_driver_info_6("", buffer, &info, 0);
5248 free_printer_driver_info_6(&info);
5250 if (*needed > offered)
5251 return WERR_INSUFFICIENT_BUFFER;
5256 /****************************************************************************
5257 ****************************************************************************/
5259 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5261 POLICY_HND *handle = &q_u->handle;
5262 UNISTR2 *uni_arch = &q_u->architecture;
5263 uint32 level = q_u->level;
5264 uint32 clientmajorversion = q_u->clientmajorversion;
5265 NEW_BUFFER *buffer = NULL;
5266 uint32 offered = q_u->offered;
5267 uint32 *needed = &r_u->needed;
5268 uint32 *servermajorversion = &r_u->servermajorversion;
5269 uint32 *serverminorversion = &r_u->serverminorversion;
5272 fstring architecture;
5275 /* that's an [in out] buffer */
5276 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5277 buffer = r_u->buffer;
5279 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5282 *servermajorversion = 0;
5283 *serverminorversion = 0;
5285 pstrcpy(servername, get_called_name());
5286 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5288 if (!get_printer_snum(p, handle, &snum))
5293 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5295 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5297 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5299 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5302 return WERR_UNKNOWN_LEVEL;
5305 /****************************************************************************
5306 ****************************************************************************/
5308 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5310 POLICY_HND *handle = &q_u->handle;
5312 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5315 DEBUG(3,("Error in startpageprinter printer handle\n"));
5319 Printer->page_started=True;
5323 /****************************************************************************
5324 ****************************************************************************/
5326 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5328 POLICY_HND *handle = &q_u->handle;
5331 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5334 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5338 if (!get_printer_snum(p, handle, &snum))
5341 Printer->page_started=False;
5342 print_job_endpage(snum, Printer->jobid);
5347 /********************************************************************
5348 * api_spoolss_getprinter
5349 * called from the spoolss dispatcher
5351 ********************************************************************/
5353 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5355 POLICY_HND *handle = &q_u->handle;
5356 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5357 uint32 *jobid = &r_u->jobid;
5359 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5363 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5364 struct current_user user;
5367 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5371 get_current_user(&user, p);
5374 * a nice thing with NT is it doesn't listen to what you tell it.
5375 * when asked to send _only_ RAW datas, it tries to send datas
5378 * So I add checks like in NT Server ...
5381 if (info_1->p_datatype != 0) {
5382 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5383 if (strcmp(datatype, "RAW") != 0) {
5385 return WERR_INVALID_DATATYPE;
5389 /* get the share number of the printer */
5390 if (!get_printer_snum(p, handle, &snum)) {
5394 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5396 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5398 /* An error occured in print_job_start() so return an appropriate
5401 if (Printer->jobid == -1) {
5402 return map_werror_from_unix(errno);
5405 Printer->document_started=True;
5406 (*jobid) = Printer->jobid;
5411 /********************************************************************
5412 * api_spoolss_getprinter
5413 * called from the spoolss dispatcher
5415 ********************************************************************/
5417 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5419 POLICY_HND *handle = &q_u->handle;
5421 return _spoolss_enddocprinter_internal(p, handle);
5424 /****************************************************************************
5425 ****************************************************************************/
5427 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5429 POLICY_HND *handle = &q_u->handle;
5430 uint32 buffer_size = q_u->buffer_size;
5431 uint8 *buffer = q_u->buffer;
5432 uint32 *buffer_written = &q_u->buffer_size2;
5434 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5437 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5438 r_u->buffer_written = q_u->buffer_size2;
5442 if (!get_printer_snum(p, handle, &snum))
5445 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5446 if (*buffer_written == -1) {
5447 r_u->buffer_written = 0;
5448 if (errno == ENOSPC)
5449 return WERR_NO_SPOOL_SPACE;
5451 return WERR_ACCESS_DENIED;
5454 r_u->buffer_written = q_u->buffer_size2;
5459 /********************************************************************
5460 * api_spoolss_getprinter
5461 * called from the spoolss dispatcher
5463 ********************************************************************/
5465 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5468 struct current_user user;
5470 WERROR errcode = WERR_BADFUNC;
5471 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5473 get_current_user(&user, p);
5476 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5480 if (!get_printer_snum(p, handle, &snum))
5484 case PRINTER_CONTROL_PAUSE:
5485 if (print_queue_pause(&user, snum, &errcode)) {
5489 case PRINTER_CONTROL_RESUME:
5490 case PRINTER_CONTROL_UNPAUSE:
5491 if (print_queue_resume(&user, snum, &errcode)) {
5495 case PRINTER_CONTROL_PURGE:
5496 if (print_queue_purge(&user, snum, &errcode)) {
5501 return WERR_UNKNOWN_LEVEL;
5507 /********************************************************************
5508 * api_spoolss_abortprinter
5509 * From MSDN: "Deletes printer's spool file if printer is configured
5511 ********************************************************************/
5513 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5515 POLICY_HND *handle = &q_u->handle;
5516 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5518 struct current_user user;
5519 WERROR errcode = WERR_OK;
5522 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5526 if (!get_printer_snum(p, handle, &snum))
5529 get_current_user( &user, p );
5531 print_job_delete( &user, snum, Printer->jobid, &errcode );
5536 /********************************************************************
5537 * called by spoolss_api_setprinter
5538 * when updating a printer description
5539 ********************************************************************/
5541 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5542 const SPOOL_PRINTER_INFO_LEVEL *info,
5543 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5545 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5546 struct current_user user;
5550 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5552 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5553 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5554 OUR_HANDLE(handle)));
5556 result = WERR_BADFID;
5560 /* NT seems to like setting the security descriptor even though
5561 nothing may have actually changed. This causes annoying
5562 dialog boxes when the user doesn't have permission to change
5563 the security descriptor. */
5565 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5567 if (DEBUGLEVEL >= 10) {
5571 the_acl = old_secdesc_ctr->sec->dacl;
5572 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5573 PRINTERNAME(snum), the_acl->num_aces));
5575 for (i = 0; i < the_acl->num_aces; i++) {
5578 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5580 DEBUG(10, ("%s 0x%08x\n", sid_str,
5581 the_acl->ace[i].info.mask));
5584 the_acl = secdesc_ctr->sec->dacl;
5587 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5588 PRINTERNAME(snum), the_acl->num_aces));
5590 for (i = 0; i < the_acl->num_aces; i++) {
5593 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5595 DEBUG(10, ("%s 0x%08x\n", sid_str,
5596 the_acl->ace[i].info.mask));
5599 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5603 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5605 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5610 /* Work out which user is performing the operation */
5612 get_current_user(&user, p);
5614 /* Check the user has permissions to change the security
5615 descriptor. By experimentation with two NT machines, the user
5616 requires Full Access to the printer to change security
5619 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5620 result = WERR_ACCESS_DENIED;
5624 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5631 /********************************************************************
5632 Do Samba sanity checks on a printer info struct.
5633 this has changed purpose: it now "canonicalises" printer
5634 info from a client rather than just checking it is correct
5635 ********************************************************************/
5637 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5639 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5640 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5642 /* we force some elements to "correct" values */
5643 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5644 fstrcpy(info->sharename, lp_servicename(snum));
5645 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5646 get_called_name(), info->sharename);
5647 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5652 /****************************************************************************
5653 ****************************************************************************/
5655 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5657 extern userdom_struct current_user_info;
5658 char *cmd = lp_addprinter_cmd();
5664 fstring remote_machine = "%m";
5666 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5668 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5669 cmd, printer->info_2->printername, printer->info_2->sharename,
5670 printer->info_2->portname, printer->info_2->drivername,
5671 printer->info_2->location, printer->info_2->comment, remote_machine);
5673 DEBUG(10,("Running [%s]\n", command));
5674 ret = smbrun(command, &fd);
5675 DEBUGADD(10,("returned [%d]\n", ret));
5684 /* Get lines and convert them back to dos-codepage */
5685 qlines = fd_lines_load(fd, &numlines);
5686 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5690 /* Set the portname to what the script says the portname should be. */
5691 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5692 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5694 /* Send SIGHUP to process group... is there a better way? */
5697 /* reload our services immediately */
5698 reload_services( False );
5701 file_lines_free(qlines);
5705 /********************************************************************
5706 * Called by spoolss_api_setprinter
5707 * when updating a printer description.
5708 ********************************************************************/
5710 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5711 const SPOOL_PRINTER_INFO_LEVEL *info,
5712 DEVICEMODE *devmode)
5715 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5716 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5719 DEBUG(8,("update_printer\n"));
5724 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5725 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5726 result = WERR_UNKNOWN_LEVEL;
5731 result = WERR_BADFID;
5735 if (!get_printer_snum(p, handle, &snum)) {
5736 result = WERR_BADFID;
5740 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5741 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5742 result = WERR_BADFID;
5746 DEBUGADD(8,("Converting info_2 struct\n"));
5749 * convert_printer_info converts the incoming
5750 * info from the client and overwrites the info
5751 * just read from the tdb in the pointer 'printer'.
5754 if (!convert_printer_info(info, printer, level)) {
5755 result = WERR_NOMEM;
5760 /* we have a valid devmode
5761 convert it and link it*/
5763 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5764 if (!convert_devicemode(printer->info_2->printername, devmode,
5765 &printer->info_2->devmode)) {
5766 result = WERR_NOMEM;
5771 * make sure we actually reload the services after
5772 * this as smb.conf could have a new section in it
5773 * .... shouldn't .... but could
5775 reload_services(False);
5778 /* Do sanity check on the requested changes for Samba */
5780 if (!check_printer_ok(printer->info_2, snum)) {
5781 result = WERR_INVALID_PARAM;
5785 /* Check calling user has permission to update printer description */
5787 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5788 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5789 result = WERR_ACCESS_DENIED;
5793 /* Call addprinter hook */
5794 /* Check changes to see if this is really needed */
5796 if ( *lp_addprinter_cmd()
5797 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5798 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5799 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5800 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5802 if ( !add_printer_hook(printer) ) {
5803 result = WERR_ACCESS_DENIED;
5809 * When a *new* driver is bound to a printer, the drivername is used to
5810 * lookup previously saved driver initialization info, which is then
5811 * bound to the printer, simulating what happens in the Windows arch.
5813 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5815 if (!set_driver_init(printer, 2))
5817 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5818 printer->info_2->drivername));
5821 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5822 printer->info_2->drivername));
5824 notify_printer_driver(snum, printer->info_2->drivername);
5827 /* Update printer info */
5828 result = mod_a_printer(*printer, 2);
5830 /* flag which changes actually occured. This is a small subset of
5831 all the possible changes */
5833 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5834 notify_printer_comment(snum, printer->info_2->comment);
5836 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5837 notify_printer_sharename(snum, printer->info_2->sharename);
5839 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5840 notify_printer_port(snum, printer->info_2->portname);
5842 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5843 notify_printer_location(snum, printer->info_2->location);
5846 free_a_printer(&printer, 2);
5847 free_a_printer(&old_printer, 2);
5853 /****************************************************************************
5854 ****************************************************************************/
5856 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5858 POLICY_HND *handle = &q_u->handle;
5859 uint32 level = q_u->level;
5860 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5861 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5862 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5863 uint32 command = q_u->command;
5865 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5868 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5872 /* check the level */
5875 return control_printer(handle, command, p);
5877 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5879 return update_printer_sec(handle, level, info, p,
5882 return WERR_UNKNOWN_LEVEL;
5886 /****************************************************************************
5887 ****************************************************************************/
5889 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5891 POLICY_HND *handle = &q_u->handle;
5892 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5895 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5899 if (Printer->notify.client_connected==True) {
5902 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
5904 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
5905 !get_printer_snum(p, handle, &snum) )
5908 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5911 Printer->notify.flags=0;
5912 Printer->notify.options=0;
5913 Printer->notify.localmachine[0]='\0';
5914 Printer->notify.printerlocal=0;
5915 if (Printer->notify.option)
5916 free_spool_notify_option(&Printer->notify.option);
5917 Printer->notify.client_connected=False;
5922 /****************************************************************************
5923 ****************************************************************************/
5925 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5927 /* that's an [in out] buffer (despite appearences to the contrary) */
5928 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5931 return WERR_INVALID_PARAM; /* this is what a NT server
5932 returns for AddJob. AddJob
5933 must fail on non-local
5937 /****************************************************************************
5938 ****************************************************************************/
5940 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5941 int position, int snum)
5947 t=gmtime(&queue->time);
5948 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5950 job_info->jobid=queue->job;
5951 init_unistr(&job_info->printername, lp_servicename(snum));
5952 init_unistr(&job_info->machinename, temp_name);
5953 init_unistr(&job_info->username, queue->fs_user);
5954 init_unistr(&job_info->document, queue->fs_file);
5955 init_unistr(&job_info->datatype, "RAW");
5956 init_unistr(&job_info->text_status, "");
5957 job_info->status=nt_printj_status(queue->status);
5958 job_info->priority=queue->priority;
5959 job_info->position=position;
5960 job_info->totalpages=queue->page_count;
5961 job_info->pagesprinted=0;
5963 make_systemtime(&job_info->submitted, t);
5966 /****************************************************************************
5967 ****************************************************************************/
5969 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5970 int position, int snum,
5971 NT_PRINTER_INFO_LEVEL *ntprinter,
5972 DEVICEMODE *devmode)
5978 t=gmtime(&queue->time);
5979 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5981 job_info->jobid=queue->job;
5983 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5985 init_unistr(&job_info->printername, chaine);
5987 init_unistr(&job_info->machinename, temp_name);
5988 init_unistr(&job_info->username, queue->fs_user);
5989 init_unistr(&job_info->document, queue->fs_file);
5990 init_unistr(&job_info->notifyname, queue->fs_user);
5991 init_unistr(&job_info->datatype, "RAW");
5992 init_unistr(&job_info->printprocessor, "winprint");
5993 init_unistr(&job_info->parameters, "");
5994 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5995 init_unistr(&job_info->text_status, "");
5997 /* and here the security descriptor */
5999 job_info->status=nt_printj_status(queue->status);
6000 job_info->priority=queue->priority;
6001 job_info->position=position;
6002 job_info->starttime=0;
6003 job_info->untiltime=0;
6004 job_info->totalpages=queue->page_count;
6005 job_info->size=queue->size;
6006 make_systemtime(&(job_info->submitted), t);
6007 job_info->timeelapsed=0;
6008 job_info->pagesprinted=0;
6010 job_info->devmode = devmode;
6015 /****************************************************************************
6016 Enumjobs at level 1.
6017 ****************************************************************************/
6019 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6020 NEW_BUFFER *buffer, uint32 offered,
6021 uint32 *needed, uint32 *returned)
6026 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6033 for (i=0; i<*returned; i++)
6034 fill_job_info_1(&info[i], &queue[i], i, snum);
6038 /* check the required size. */
6039 for (i=0; i<*returned; i++)
6040 (*needed) += spoolss_size_job_info_1(&info[i]);
6042 if (!alloc_buffer_size(buffer, *needed)) {
6044 return WERR_INSUFFICIENT_BUFFER;
6047 /* fill the buffer with the structures */
6048 for (i=0; i<*returned; i++)
6049 smb_io_job_info_1("", buffer, &info[i], 0);
6054 if (*needed > offered) {
6056 return WERR_INSUFFICIENT_BUFFER;
6062 /****************************************************************************
6063 Enumjobs at level 2.
6064 ****************************************************************************/
6066 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6067 NEW_BUFFER *buffer, uint32 offered,
6068 uint32 *needed, uint32 *returned)
6070 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6071 JOB_INFO_2 *info = NULL;
6074 DEVICEMODE *devmode = NULL;
6076 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6079 result = WERR_NOMEM;
6083 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6084 if (!W_ERROR_IS_OK(result)) {
6089 /* this should not be a failure condition if the devmode is NULL */
6091 devmode = construct_dev_mode(snum);
6093 for (i=0; i<*returned; i++)
6094 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6097 free_a_printer(&ntprinter, 2);
6100 /* check the required size. */
6101 for (i=0; i<*returned; i++)
6102 (*needed) += spoolss_size_job_info_2(&info[i]);
6104 if (*needed > offered) {
6106 result = WERR_INSUFFICIENT_BUFFER;
6110 if (!alloc_buffer_size(buffer, *needed)) {
6112 result = WERR_INSUFFICIENT_BUFFER;
6116 /* fill the buffer with the structures */
6117 for (i=0; i<*returned; i++)
6118 smb_io_job_info_2("", buffer, &info[i], 0);
6123 free_a_printer(&ntprinter, 2);
6124 free_devmode(devmode);
6132 /****************************************************************************
6134 ****************************************************************************/
6136 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6138 POLICY_HND *handle = &q_u->handle;
6139 uint32 level = q_u->level;
6140 NEW_BUFFER *buffer = NULL;
6141 uint32 offered = q_u->offered;
6142 uint32 *needed = &r_u->needed;
6143 uint32 *returned = &r_u->returned;
6146 print_status_struct prt_status;
6147 print_queue_struct *queue=NULL;
6149 /* that's an [in out] buffer */
6150 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6151 buffer = r_u->buffer;
6153 DEBUG(4,("_spoolss_enumjobs\n"));
6158 if (!get_printer_snum(p, handle, &snum))
6161 *returned = print_queue_status(snum, &queue, &prt_status);
6162 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6164 if (*returned == 0) {
6171 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6173 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6177 return WERR_UNKNOWN_LEVEL;
6181 /****************************************************************************
6182 ****************************************************************************/
6184 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6189 /****************************************************************************
6190 ****************************************************************************/
6192 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6194 POLICY_HND *handle = &q_u->handle;
6195 uint32 jobid = q_u->jobid;
6196 uint32 command = q_u->command;
6198 struct current_user user;
6200 WERROR errcode = WERR_BADFUNC;
6202 if (!get_printer_snum(p, handle, &snum)) {
6206 if (!print_job_exists(snum, jobid)) {
6207 return WERR_INVALID_PRINTER_NAME;
6210 get_current_user(&user, p);
6213 case JOB_CONTROL_CANCEL:
6214 case JOB_CONTROL_DELETE:
6215 if (print_job_delete(&user, snum, jobid, &errcode)) {
6219 case JOB_CONTROL_PAUSE:
6220 if (print_job_pause(&user, snum, jobid, &errcode)) {
6224 case JOB_CONTROL_RESTART:
6225 case JOB_CONTROL_RESUME:
6226 if (print_job_resume(&user, snum, jobid, &errcode)) {
6231 return WERR_UNKNOWN_LEVEL;
6237 /****************************************************************************
6238 Enumerates all printer drivers at level 1.
6239 ****************************************************************************/
6241 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6246 fstring *list = NULL;
6248 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6249 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6253 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6255 ndrivers=get_ntdrivers(&list, architecture, version);
6256 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6262 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6263 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6264 SAFE_FREE(driver_info_1);
6268 else driver_info_1 = tdi1;
6271 for (i=0; i<ndrivers; i++) {
6273 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6274 ZERO_STRUCT(driver);
6275 status = get_a_printer_driver(&driver, 3, list[i],
6276 architecture, version);
6277 if (!W_ERROR_IS_OK(status)) {
6281 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6282 free_a_printer_driver(driver, 3);
6285 *returned+=ndrivers;
6289 /* check the required size. */
6290 for (i=0; i<*returned; i++) {
6291 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6292 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6295 if (!alloc_buffer_size(buffer, *needed)) {
6296 SAFE_FREE(driver_info_1);
6297 return WERR_INSUFFICIENT_BUFFER;
6300 /* fill the buffer with the driver structures */
6301 for (i=0; i<*returned; i++) {
6302 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6303 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6306 SAFE_FREE(driver_info_1);
6308 if (*needed > offered) {
6310 return WERR_INSUFFICIENT_BUFFER;
6316 /****************************************************************************
6317 Enumerates all printer drivers at level 2.
6318 ****************************************************************************/
6320 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6325 fstring *list = NULL;
6327 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6328 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6332 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6334 ndrivers=get_ntdrivers(&list, architecture, version);
6335 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6341 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6342 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6343 SAFE_FREE(driver_info_2);
6347 else driver_info_2 = tdi2;
6350 for (i=0; i<ndrivers; i++) {
6353 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6354 ZERO_STRUCT(driver);
6355 status = get_a_printer_driver(&driver, 3, list[i],
6356 architecture, version);
6357 if (!W_ERROR_IS_OK(status)) {
6361 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6362 free_a_printer_driver(driver, 3);
6365 *returned+=ndrivers;
6369 /* check the required size. */
6370 for (i=0; i<*returned; i++) {
6371 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6372 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6375 if (!alloc_buffer_size(buffer, *needed)) {
6376 SAFE_FREE(driver_info_2);
6377 return WERR_INSUFFICIENT_BUFFER;
6380 /* fill the buffer with the form structures */
6381 for (i=0; i<*returned; i++) {
6382 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6383 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6386 SAFE_FREE(driver_info_2);
6388 if (*needed > offered) {
6390 return WERR_INSUFFICIENT_BUFFER;
6396 /****************************************************************************
6397 Enumerates all printer drivers at level 3.
6398 ****************************************************************************/
6400 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6405 fstring *list = NULL;
6407 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6408 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6412 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6414 ndrivers=get_ntdrivers(&list, architecture, version);
6415 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6421 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6422 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6423 SAFE_FREE(driver_info_3);
6427 else driver_info_3 = tdi3;
6430 for (i=0; i<ndrivers; i++) {
6433 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6434 ZERO_STRUCT(driver);
6435 status = get_a_printer_driver(&driver, 3, list[i],
6436 architecture, version);
6437 if (!W_ERROR_IS_OK(status)) {
6441 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6442 free_a_printer_driver(driver, 3);
6445 *returned+=ndrivers;
6449 /* check the required size. */
6450 for (i=0; i<*returned; i++) {
6451 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6452 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6455 if (!alloc_buffer_size(buffer, *needed)) {
6456 SAFE_FREE(driver_info_3);
6457 return WERR_INSUFFICIENT_BUFFER;
6460 /* fill the buffer with the driver structures */
6461 for (i=0; i<*returned; i++) {
6462 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6463 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6466 for (i=0; i<*returned; i++)
6467 SAFE_FREE(driver_info_3[i].dependentfiles);
6469 SAFE_FREE(driver_info_3);
6471 if (*needed > offered) {
6473 return WERR_INSUFFICIENT_BUFFER;
6479 /****************************************************************************
6480 Enumerates all printer drivers.
6481 ****************************************************************************/
6483 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6485 UNISTR2 *environment = &q_u->environment;
6486 uint32 level = q_u->level;
6487 NEW_BUFFER *buffer = NULL;
6488 uint32 offered = q_u->offered;
6489 uint32 *needed = &r_u->needed;
6490 uint32 *returned = &r_u->returned;
6492 fstring *list = NULL;
6494 fstring architecture;
6496 /* that's an [in out] buffer */
6497 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6498 buffer = r_u->buffer;
6500 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6501 fstrcpy(servername, get_called_name());
6505 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6509 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6511 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6513 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6517 return WERR_UNKNOWN_LEVEL;
6521 /****************************************************************************
6522 ****************************************************************************/
6524 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6526 form->flag=list->flag;
6527 init_unistr(&form->name, list->name);
6528 form->width=list->width;
6529 form->length=list->length;
6530 form->left=list->left;
6531 form->top=list->top;
6532 form->right=list->right;
6533 form->bottom=list->bottom;
6536 /****************************************************************************
6537 ****************************************************************************/
6539 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6541 uint32 level = q_u->level;
6542 NEW_BUFFER *buffer = NULL;
6543 uint32 offered = q_u->offered;
6544 uint32 *needed = &r_u->needed;
6545 uint32 *numofforms = &r_u->numofforms;
6546 uint32 numbuiltinforms;
6548 nt_forms_struct *list=NULL;
6549 nt_forms_struct *builtinlist=NULL;
6554 /* that's an [in out] buffer */
6555 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6556 buffer = r_u->buffer;
6558 DEBUG(4,("_spoolss_enumforms\n"));
6559 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6560 DEBUGADD(5,("Info level [%d]\n", level));
6562 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6563 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6564 *numofforms = get_ntforms(&list);
6565 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6566 *numofforms += numbuiltinforms;
6568 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6572 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6577 /* construct the list of form structures */
6578 for (i=0; i<numbuiltinforms; i++) {
6579 DEBUGADD(6,("Filling form number [%d]\n",i));
6580 fill_form_1(&forms_1[i], &builtinlist[i]);
6583 SAFE_FREE(builtinlist);
6585 for (; i<*numofforms; i++) {
6586 DEBUGADD(6,("Filling form number [%d]\n",i));
6587 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6592 /* check the required size. */
6593 for (i=0; i<numbuiltinforms; i++) {
6594 DEBUGADD(6,("adding form [%d]'s size\n",i));
6595 buffer_size += spoolss_size_form_1(&forms_1[i]);
6597 for (; i<*numofforms; i++) {
6598 DEBUGADD(6,("adding form [%d]'s size\n",i));
6599 buffer_size += spoolss_size_form_1(&forms_1[i]);
6602 *needed=buffer_size;
6604 if (!alloc_buffer_size(buffer, buffer_size)){
6606 return WERR_INSUFFICIENT_BUFFER;
6609 /* fill the buffer with the form structures */
6610 for (i=0; i<numbuiltinforms; i++) {
6611 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6612 smb_io_form_1("", buffer, &forms_1[i], 0);
6614 for (; i<*numofforms; i++) {
6615 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6616 smb_io_form_1("", buffer, &forms_1[i], 0);
6621 if (*needed > offered) {
6623 return WERR_INSUFFICIENT_BUFFER;
6630 SAFE_FREE(builtinlist);
6631 return WERR_UNKNOWN_LEVEL;
6636 /****************************************************************************
6637 ****************************************************************************/
6639 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6641 uint32 level = q_u->level;
6642 UNISTR2 *uni_formname = &q_u->formname;
6643 NEW_BUFFER *buffer = NULL;
6644 uint32 offered = q_u->offered;
6645 uint32 *needed = &r_u->needed;
6647 nt_forms_struct *list=NULL;
6648 nt_forms_struct builtin_form;
6653 int numofforms=0, i=0;
6655 /* that's an [in out] buffer */
6656 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6657 buffer = r_u->buffer;
6659 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6661 DEBUG(4,("_spoolss_getform\n"));
6662 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6663 DEBUGADD(5,("Info level [%d]\n", level));
6665 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6666 if (!foundBuiltin) {
6667 numofforms = get_ntforms(&list);
6668 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6670 if (numofforms == 0)
6677 fill_form_1(&form_1, &builtin_form);
6680 /* Check if the requested name is in the list of form structures */
6681 for (i=0; i<numofforms; i++) {
6683 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6685 if (strequal(form_name, list[i].name)) {
6686 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6687 fill_form_1(&form_1, &list[i]);
6693 if (i == numofforms) {
6697 /* check the required size. */
6699 *needed=spoolss_size_form_1(&form_1);
6701 if (!alloc_buffer_size(buffer, buffer_size)){
6702 return WERR_INSUFFICIENT_BUFFER;
6705 if (*needed > offered) {
6706 return WERR_INSUFFICIENT_BUFFER;
6709 /* fill the buffer with the form structures */
6710 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6711 smb_io_form_1("", buffer, &form_1, 0);
6717 return WERR_UNKNOWN_LEVEL;
6721 /****************************************************************************
6722 ****************************************************************************/
6724 static void fill_port_1(PORT_INFO_1 *port, char *name)
6726 init_unistr(&port->port_name, name);
6729 /****************************************************************************
6730 ****************************************************************************/
6732 static void fill_port_2(PORT_INFO_2 *port, char *name)
6734 init_unistr(&port->port_name, name);
6735 init_unistr(&port->monitor_name, "Local Monitor");
6736 init_unistr(&port->description, "Local Port");
6737 #define PORT_TYPE_WRITE 1
6738 port->port_type=PORT_TYPE_WRITE;
6742 /****************************************************************************
6744 ****************************************************************************/
6746 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6748 PORT_INFO_1 *ports=NULL;
6751 if (*lp_enumports_cmd()) {
6752 char *cmd = lp_enumports_cmd();
6759 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6761 DEBUG(10,("Running [%s]\n", command));
6762 ret = smbrun(command, &fd);
6763 DEBUG(10,("Returned [%d]\n", ret));
6767 /* Is this the best error to return here? */
6768 return WERR_ACCESS_DENIED;
6772 qlines = fd_lines_load(fd, &numlines);
6773 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6777 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6778 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6779 dos_errstr(WERR_NOMEM)));
6780 file_lines_free(qlines);
6784 for (i=0; i<numlines; i++) {
6785 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6786 fill_port_1(&ports[i], qlines[i]);
6789 file_lines_free(qlines);
6792 *returned = numlines;
6795 *returned = 1; /* Sole Samba port returned. */
6797 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6800 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6802 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6805 /* check the required size. */
6806 for (i=0; i<*returned; i++) {
6807 DEBUGADD(6,("adding port [%d]'s size\n", i));
6808 *needed += spoolss_size_port_info_1(&ports[i]);
6811 if (!alloc_buffer_size(buffer, *needed)) {
6813 return WERR_INSUFFICIENT_BUFFER;
6816 /* fill the buffer with the ports structures */
6817 for (i=0; i<*returned; i++) {
6818 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6819 smb_io_port_1("", buffer, &ports[i], 0);
6824 if (*needed > offered) {
6826 return WERR_INSUFFICIENT_BUFFER;
6832 /****************************************************************************
6834 ****************************************************************************/
6836 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6838 PORT_INFO_2 *ports=NULL;
6841 if (*lp_enumports_cmd()) {
6842 char *cmd = lp_enumports_cmd();
6851 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6852 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6854 path = lp_lockdir();
6856 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6857 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6860 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6861 ret = smbrun(command, &fd);
6862 DEBUGADD(10,("returned [%d]\n", ret));
6866 /* Is this the best error to return here? */
6867 return WERR_ACCESS_DENIED;
6871 qlines = fd_lines_load(fd, &numlines);
6872 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6876 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6877 file_lines_free(qlines);
6881 for (i=0; i<numlines; i++) {
6882 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6883 fill_port_2(&(ports[i]), qlines[i]);
6886 file_lines_free(qlines);
6889 *returned = numlines;
6895 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6898 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6900 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6903 /* check the required size. */
6904 for (i=0; i<*returned; i++) {
6905 DEBUGADD(6,("adding port [%d]'s size\n", i));
6906 *needed += spoolss_size_port_info_2(&ports[i]);
6909 if (!alloc_buffer_size(buffer, *needed)) {
6911 return WERR_INSUFFICIENT_BUFFER;
6914 /* fill the buffer with the ports structures */
6915 for (i=0; i<*returned; i++) {
6916 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6917 smb_io_port_2("", buffer, &ports[i], 0);
6922 if (*needed > offered) {
6924 return WERR_INSUFFICIENT_BUFFER;
6930 /****************************************************************************
6932 ****************************************************************************/
6934 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6936 uint32 level = q_u->level;
6937 NEW_BUFFER *buffer = NULL;
6938 uint32 offered = q_u->offered;
6939 uint32 *needed = &r_u->needed;
6940 uint32 *returned = &r_u->returned;
6942 /* that's an [in out] buffer */
6943 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6944 buffer = r_u->buffer;
6946 DEBUG(4,("_spoolss_enumports\n"));
6953 return enumports_level_1(buffer, offered, needed, returned);
6955 return enumports_level_2(buffer, offered, needed, returned);
6957 return WERR_UNKNOWN_LEVEL;
6961 /****************************************************************************
6962 ****************************************************************************/
6964 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6965 const SPOOL_PRINTER_INFO_LEVEL *info,
6966 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6967 uint32 user_switch, const SPOOL_USER_CTR *user,
6970 NT_PRINTER_INFO_LEVEL *printer = NULL;
6973 WERROR err = WERR_OK;
6975 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6976 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6980 ZERO_STRUCTP(printer);
6982 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6983 if (!convert_printer_info(info, printer, 2)) {
6984 free_a_printer(&printer, 2);
6988 /* check to see if the printer already exists */
6990 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6991 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6992 printer->info_2->sharename));
6993 free_a_printer(&printer, 2);
6994 return WERR_PRINTER_ALREADY_EXISTS;
6997 if (*lp_addprinter_cmd() ) {
6998 if ( !add_printer_hook(printer) ) {
6999 free_a_printer(&printer,2);
7000 return WERR_ACCESS_DENIED;
7004 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7005 printer->info_2->sharename);
7008 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7009 free_a_printer(&printer,2);
7010 return WERR_ACCESS_DENIED;
7013 /* you must be a printer admin to add a new printer */
7014 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7015 free_a_printer(&printer,2);
7016 return WERR_ACCESS_DENIED;
7020 * Do sanity check on the requested changes for Samba.
7023 if (!check_printer_ok(printer->info_2, snum)) {
7024 free_a_printer(&printer,2);
7025 return WERR_INVALID_PARAM;
7029 * When a printer is created, the drivername bound to the printer is used
7030 * to lookup previously saved driver initialization info, which is then
7031 * bound to the new printer, simulating what happens in the Windows arch.
7036 set_driver_init(printer, 2);
7040 /* A valid devmode was included, convert and link it
7042 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7044 if (!convert_devicemode(printer->info_2->printername, devmode,
7045 &printer->info_2->devmode))
7049 /* write the ASCII on disk */
7050 err = mod_a_printer(*printer, 2);
7051 if (!W_ERROR_IS_OK(err)) {
7052 free_a_printer(&printer,2);
7056 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7057 /* Handle open failed - remove addition. */
7058 del_a_printer(printer->info_2->sharename);
7059 free_a_printer(&printer,2);
7060 return WERR_ACCESS_DENIED;
7063 update_c_setprinter(False);
7064 free_a_printer(&printer,2);
7069 /****************************************************************************
7070 ****************************************************************************/
7072 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7074 UNISTR2 *uni_srv_name = &q_u->server_name;
7075 uint32 level = q_u->level;
7076 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7077 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7078 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7079 uint32 user_switch = q_u->user_switch;
7080 SPOOL_USER_CTR *user = &q_u->user_ctr;
7081 POLICY_HND *handle = &r_u->handle;
7085 /* we don't handle yet */
7086 /* but I know what to do ... */
7087 return WERR_UNKNOWN_LEVEL;
7089 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7091 user_switch, user, handle);
7093 return WERR_UNKNOWN_LEVEL;
7097 /****************************************************************************
7098 ****************************************************************************/
7100 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7102 uint32 level = q_u->level;
7103 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7104 WERROR err = WERR_OK;
7105 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7106 struct current_user user;
7107 fstring driver_name;
7110 ZERO_STRUCT(driver);
7112 get_current_user(&user, p);
7114 if (!convert_printer_driver_info(info, &driver, level)) {
7119 DEBUG(5,("Cleaning driver's information\n"));
7120 err = clean_up_driver_struct(driver, level, &user);
7121 if (!W_ERROR_IS_OK(err))
7124 DEBUG(5,("Moving driver to final destination\n"));
7125 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7126 if (W_ERROR_IS_OK(err))
7127 err = WERR_ACCESS_DENIED;
7131 if (add_a_printer_driver(driver, level)!=0) {
7132 err = WERR_ACCESS_DENIED;
7136 /* BEGIN_ADMIN_LOG */
7139 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7140 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7141 fstrcpy(driver_name, driver.info_3->name);
7144 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7145 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7146 fstrcpy(driver_name, driver.info_6->name);
7152 * I think this is where he DrvUpgradePrinter() hook would be
7153 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7154 * server. Right now, we just need to send ourselves a message
7155 * to update each printer bound to this driver. --jerry
7158 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7159 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7164 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7165 * decide if the driver init data should be deleted. The rules are:
7166 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7167 * 2) delete init data only if there is no 2k/Xp driver
7168 * 3) always delete init data
7169 * The generalized rule is always use init data from the highest order driver.
7170 * It is necessary to follow the driver install by an initialization step to
7171 * finish off this process.
7174 version = driver.info_3->cversion;
7175 else if (level == 6)
7176 version = driver.info_6->version;
7181 * 9x printer driver - never delete init data
7184 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7189 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7190 * there is no 2k/Xp driver init data for this driver name.
7194 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7196 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7198 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7200 if (!del_driver_init(driver_name))
7201 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7204 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7206 free_a_printer_driver(driver1,3);
7207 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7214 * 2k or Xp printer driver - always delete init data
7217 if (!del_driver_init(driver_name))
7218 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7222 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7228 free_a_printer_driver(driver, level);
7232 /********************************************************************
7233 * spoolss_addprinterdriverex
7234 ********************************************************************/
7236 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7238 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7239 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7242 * we only support the semantics of AddPrinterDriver()
7243 * i.e. only copy files that are newer than existing ones
7246 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7247 return WERR_ACCESS_DENIED;
7249 ZERO_STRUCT(q_u_local);
7250 ZERO_STRUCT(r_u_local);
7252 /* just pass the information off to _spoolss_addprinterdriver() */
7253 q_u_local.server_name_ptr = q_u->server_name_ptr;
7254 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7255 q_u_local.level = q_u->level;
7256 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7258 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7261 /****************************************************************************
7262 ****************************************************************************/
7264 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7266 init_unistr(&info->name, name);
7269 /****************************************************************************
7270 ****************************************************************************/
7272 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7276 pstring short_archi;
7277 DRIVER_DIRECTORY_1 *info=NULL;
7279 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7281 if (get_short_archi(short_archi, long_archi)==False)
7282 return WERR_INVALID_ENVIRONMENT;
7284 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7287 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7289 DEBUG(4,("printer driver directory: [%s]\n", path));
7291 fill_driverdir_1(info, path);
7293 *needed += spoolss_size_driverdir_info_1(info);
7295 if (!alloc_buffer_size(buffer, *needed)) {
7297 return WERR_INSUFFICIENT_BUFFER;
7300 smb_io_driverdir_1("", buffer, info, 0);
7304 if (*needed > offered)
7305 return WERR_INSUFFICIENT_BUFFER;
7310 /****************************************************************************
7311 ****************************************************************************/
7313 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7315 UNISTR2 *name = &q_u->name;
7316 UNISTR2 *uni_environment = &q_u->environment;
7317 uint32 level = q_u->level;
7318 NEW_BUFFER *buffer = NULL;
7319 uint32 offered = q_u->offered;
7320 uint32 *needed = &r_u->needed;
7322 /* that's an [in out] buffer */
7323 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7324 buffer = r_u->buffer;
7326 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7332 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7334 return WERR_UNKNOWN_LEVEL;
7338 /****************************************************************************
7339 ****************************************************************************/
7341 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7343 POLICY_HND *handle = &q_u->handle;
7344 uint32 idx = q_u->index;
7345 uint32 in_value_len = q_u->valuesize;
7346 uint32 in_data_len = q_u->datasize;
7347 uint32 *out_max_value_len = &r_u->valuesize;
7348 uint16 **out_value = &r_u->value;
7349 uint32 *out_value_len = &r_u->realvaluesize;
7350 uint32 *out_type = &r_u->type;
7351 uint32 *out_max_data_len = &r_u->datasize;
7352 uint8 **data_out = &r_u->data;
7353 uint32 *out_data_len = &r_u->realdatasize;
7355 NT_PRINTER_INFO_LEVEL *printer = NULL;
7358 uint32 biggest_valuesize;
7359 uint32 biggest_datasize;
7361 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7364 REGISTRY_VALUE *val;
7365 NT_PRINTER_DATA *p_data;
7366 int i, key_index, num_values;
7369 ZERO_STRUCT( printer );
7373 *out_max_data_len = 0;
7377 DEBUG(5,("spoolss_enumprinterdata\n"));
7380 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7384 if (!get_printer_snum(p,handle, &snum))
7387 result = get_a_printer(&printer, 2, lp_servicename(snum));
7388 if (!W_ERROR_IS_OK(result))
7391 p_data = &printer->info_2->data;
7392 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7397 * The NT machine wants to know the biggest size of value and data
7399 * cf: MSDN EnumPrinterData remark section
7402 if ( !in_value_len && !in_data_len )
7404 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7407 biggest_valuesize = 0;
7408 biggest_datasize = 0;
7410 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7412 for ( i=0; i<num_values; i++ )
7414 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7416 name_length = strlen(val->valuename);
7417 if ( strlen(val->valuename) > biggest_valuesize )
7418 biggest_valuesize = name_length;
7420 if ( val->size > biggest_datasize )
7421 biggest_datasize = val->size;
7423 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7427 /* the value is an UNICODE string but real_value_size is the length
7428 in bytes including the trailing 0 */
7430 *out_value_len = 2 * (1+biggest_valuesize);
7431 *out_data_len = biggest_datasize;
7433 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7439 * the value len is wrong in NT sp3
7440 * that's the number of bytes not the number of unicode chars
7443 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7448 /* out_value should default to "" or else NT4 has
7449 problems unmarshalling the response */
7451 *out_max_value_len = (in_value_len/sizeof(uint16));
7453 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7455 result = WERR_NOMEM;
7459 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7461 /* the data is counted in bytes */
7463 *out_max_data_len = in_data_len;
7464 *out_data_len = in_data_len;
7466 /* only allocate when given a non-zero data_len */
7468 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7470 result = WERR_NOMEM;
7474 result = WERR_NO_MORE_ITEMS;
7480 * - counted in bytes in the request
7481 * - counted in UNICODE chars in the max reply
7482 * - counted in bytes in the real size
7484 * take a pause *before* coding not *during* coding
7488 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7489 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7491 result = WERR_NOMEM;
7495 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7499 *out_type = regval_type( val );
7501 /* data - counted in bytes */
7503 *out_max_data_len = in_data_len;
7504 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7506 result = WERR_NOMEM;
7509 data_len = (size_t)regval_size(val);
7510 memcpy( *data_out, regval_data_p(val), data_len );
7511 *out_data_len = data_len;
7515 free_a_printer(&printer, 2);
7519 /****************************************************************************
7520 ****************************************************************************/
7522 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7524 POLICY_HND *handle = &q_u->handle;
7525 UNISTR2 *value = &q_u->value;
7526 uint32 type = q_u->type;
7527 uint8 *data = q_u->data;
7528 uint32 real_len = q_u->real_len;
7530 NT_PRINTER_INFO_LEVEL *printer = NULL;
7532 WERROR status = WERR_OK;
7533 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7536 DEBUG(5,("spoolss_setprinterdata\n"));
7539 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7543 if (!get_printer_snum(p,handle, &snum))
7547 * Access check : NT returns "access denied" if you make a
7548 * SetPrinterData call without the necessary privildge.
7549 * we were originally returning OK if nothing changed
7550 * which made Win2k issue **a lot** of SetPrinterData
7551 * when connecting to a printer --jerry
7554 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7556 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7557 status = WERR_ACCESS_DENIED;
7561 status = get_a_printer(&printer, 2, lp_servicename(snum));
7562 if (!W_ERROR_IS_OK(status))
7565 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7568 * When client side code sets a magic printer data key, detect it and save
7569 * the current printer data and the magic key's data (its the DEVMODE) for
7570 * future printer/driver initializations.
7572 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7574 /* Set devmode and printer initialization info */
7575 status = save_driver_init( printer, 2, data, real_len );
7577 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7581 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7582 type, data, real_len );
7583 if ( W_ERROR_IS_OK(status) )
7584 status = mod_a_printer(*printer, 2);
7588 free_a_printer(&printer, 2);
7593 /****************************************************************************
7594 ****************************************************************************/
7596 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7598 POLICY_HND *handle = &q_u->handle;
7599 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7602 DEBUG(5,("_spoolss_resetprinter\n"));
7605 * All we do is to check to see if the handle and queue is valid.
7606 * This call really doesn't mean anything to us because we only
7607 * support RAW printing. --jerry
7611 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7615 if (!get_printer_snum(p,handle, &snum))
7619 /* blindly return success */
7624 /****************************************************************************
7625 ****************************************************************************/
7627 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7629 POLICY_HND *handle = &q_u->handle;
7630 UNISTR2 *value = &q_u->valuename;
7632 NT_PRINTER_INFO_LEVEL *printer = NULL;
7634 WERROR status = WERR_OK;
7635 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7638 DEBUG(5,("spoolss_deleteprinterdata\n"));
7641 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7645 if (!get_printer_snum(p, handle, &snum))
7648 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7649 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7650 return WERR_ACCESS_DENIED;
7653 status = get_a_printer(&printer, 2, lp_servicename(snum));
7654 if (!W_ERROR_IS_OK(status))
7657 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7659 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7661 free_a_printer(&printer, 2);
7666 /****************************************************************************
7667 ****************************************************************************/
7669 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7671 POLICY_HND *handle = &q_u->handle;
7672 FORM *form = &q_u->form;
7673 nt_forms_struct tmpForm;
7675 WERROR status = WERR_OK;
7676 NT_PRINTER_INFO_LEVEL *printer = NULL;
7679 nt_forms_struct *list=NULL;
7680 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7682 DEBUG(5,("spoolss_addform\n"));
7685 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7690 /* forms can be added on printer of on the print server handle */
7692 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7694 if (!get_printer_snum(p,handle, &snum))
7697 status = get_a_printer(&printer, 2, lp_servicename(snum));
7698 if (!W_ERROR_IS_OK(status))
7702 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7703 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7704 status = WERR_ACCESS_DENIED;
7708 /* can't add if builtin */
7710 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7711 status = WERR_ALREADY_EXISTS;
7715 count = get_ntforms(&list);
7717 if(!add_a_form(&list, form, &count)) {
7718 status = WERR_NOMEM;
7722 write_ntforms(&list, count);
7725 * ChangeID must always be set if this is a printer
7728 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7729 status = mod_a_printer(*printer, 2);
7733 free_a_printer(&printer, 2);
7739 /****************************************************************************
7740 ****************************************************************************/
7742 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7744 POLICY_HND *handle = &q_u->handle;
7745 UNISTR2 *form_name = &q_u->name;
7746 nt_forms_struct tmpForm;
7748 nt_forms_struct *list=NULL;
7749 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7751 WERROR status = WERR_OK;
7752 NT_PRINTER_INFO_LEVEL *printer = NULL;
7754 DEBUG(5,("spoolss_deleteform\n"));
7757 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7761 /* forms can be deleted on printer of on the print server handle */
7763 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7765 if (!get_printer_snum(p,handle, &snum))
7768 status = get_a_printer(&printer, 2, lp_servicename(snum));
7769 if (!W_ERROR_IS_OK(status))
7773 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7774 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7775 status = WERR_ACCESS_DENIED;
7779 /* can't delete if builtin */
7781 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7782 status = WERR_INVALID_PARAM;
7786 count = get_ntforms(&list);
7788 if ( !delete_a_form(&list, form_name, &count, &status ))
7792 * ChangeID must always be set if this is a printer
7795 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7796 status = mod_a_printer(*printer, 2);
7800 free_a_printer(&printer, 2);
7806 /****************************************************************************
7807 ****************************************************************************/
7809 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7811 POLICY_HND *handle = &q_u->handle;
7812 FORM *form = &q_u->form;
7813 nt_forms_struct tmpForm;
7815 WERROR status = WERR_OK;
7816 NT_PRINTER_INFO_LEVEL *printer = NULL;
7819 nt_forms_struct *list=NULL;
7820 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7822 DEBUG(5,("spoolss_setform\n"));
7825 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7829 /* forms can be modified on printer of on the print server handle */
7831 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7833 if (!get_printer_snum(p,handle, &snum))
7836 status = get_a_printer(&printer, 2, lp_servicename(snum));
7837 if (!W_ERROR_IS_OK(status))
7841 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7842 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7843 status = WERR_ACCESS_DENIED;
7847 /* can't set if builtin */
7848 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7849 status = WERR_INVALID_PARAM;
7853 count = get_ntforms(&list);
7854 update_a_form(&list, form, count);
7855 write_ntforms(&list, count);
7858 * ChangeID must always be set if this is a printer
7861 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7862 status = mod_a_printer(*printer, 2);
7867 free_a_printer(&printer, 2);
7873 /****************************************************************************
7874 enumprintprocessors level 1.
7875 ****************************************************************************/
7877 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7879 PRINTPROCESSOR_1 *info_1=NULL;
7881 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7886 init_unistr(&info_1->name, "winprint");
7888 *needed += spoolss_size_printprocessor_info_1(info_1);
7890 if (!alloc_buffer_size(buffer, *needed))
7891 return WERR_INSUFFICIENT_BUFFER;
7893 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7897 if (*needed > offered) {
7899 return WERR_INSUFFICIENT_BUFFER;
7905 /****************************************************************************
7906 ****************************************************************************/
7908 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7910 uint32 level = q_u->level;
7911 NEW_BUFFER *buffer = NULL;
7912 uint32 offered = q_u->offered;
7913 uint32 *needed = &r_u->needed;
7914 uint32 *returned = &r_u->returned;
7916 /* that's an [in out] buffer */
7917 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7918 buffer = r_u->buffer;
7920 DEBUG(5,("spoolss_enumprintprocessors\n"));
7923 * Enumerate the print processors ...
7925 * Just reply with "winprint", to keep NT happy
7926 * and I can use my nice printer checker.
7934 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7936 return WERR_UNKNOWN_LEVEL;
7940 /****************************************************************************
7941 enumprintprocdatatypes level 1.
7942 ****************************************************************************/
7944 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7946 PRINTPROCDATATYPE_1 *info_1=NULL;
7948 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7953 init_unistr(&info_1->name, "RAW");
7955 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7957 if (!alloc_buffer_size(buffer, *needed))
7958 return WERR_INSUFFICIENT_BUFFER;
7960 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7964 if (*needed > offered) {
7966 return WERR_INSUFFICIENT_BUFFER;
7972 /****************************************************************************
7973 ****************************************************************************/
7975 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7977 uint32 level = q_u->level;
7978 NEW_BUFFER *buffer = NULL;
7979 uint32 offered = q_u->offered;
7980 uint32 *needed = &r_u->needed;
7981 uint32 *returned = &r_u->returned;
7983 /* that's an [in out] buffer */
7984 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7985 buffer = r_u->buffer;
7987 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7994 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7996 return WERR_UNKNOWN_LEVEL;
8000 /****************************************************************************
8001 enumprintmonitors level 1.
8002 ****************************************************************************/
8004 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8006 PRINTMONITOR_1 *info_1=NULL;
8008 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8013 init_unistr(&info_1->name, "Local Port");
8015 *needed += spoolss_size_printmonitor_info_1(info_1);
8017 if (!alloc_buffer_size(buffer, *needed))
8018 return WERR_INSUFFICIENT_BUFFER;
8020 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8024 if (*needed > offered) {
8026 return WERR_INSUFFICIENT_BUFFER;
8032 /****************************************************************************
8033 enumprintmonitors level 2.
8034 ****************************************************************************/
8036 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8038 PRINTMONITOR_2 *info_2=NULL;
8040 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8045 init_unistr(&info_2->name, "Local Port");
8046 init_unistr(&info_2->environment, "Windows NT X86");
8047 init_unistr(&info_2->dll_name, "localmon.dll");
8049 *needed += spoolss_size_printmonitor_info_2(info_2);
8051 if (!alloc_buffer_size(buffer, *needed))
8052 return WERR_INSUFFICIENT_BUFFER;
8054 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8058 if (*needed > offered) {
8060 return WERR_INSUFFICIENT_BUFFER;
8066 /****************************************************************************
8067 ****************************************************************************/
8069 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8071 uint32 level = q_u->level;
8072 NEW_BUFFER *buffer = NULL;
8073 uint32 offered = q_u->offered;
8074 uint32 *needed = &r_u->needed;
8075 uint32 *returned = &r_u->returned;
8077 /* that's an [in out] buffer */
8078 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8079 buffer = r_u->buffer;
8081 DEBUG(5,("spoolss_enumprintmonitors\n"));
8084 * Enumerate the print monitors ...
8086 * Just reply with "Local Port", to keep NT happy
8087 * and I can use my nice printer checker.
8095 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8097 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8099 return WERR_UNKNOWN_LEVEL;
8103 /****************************************************************************
8104 ****************************************************************************/
8106 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8110 JOB_INFO_1 *info_1=NULL;
8112 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8114 if (info_1 == NULL) {
8119 for (i=0; i<count && found==False; i++) {
8120 if (queue[i].job==(int)jobid)
8127 /* NT treats not found as bad param... yet another bad choice */
8128 return WERR_INVALID_PARAM;
8131 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8133 *needed += spoolss_size_job_info_1(info_1);
8135 if (!alloc_buffer_size(buffer, *needed)) {
8137 return WERR_INSUFFICIENT_BUFFER;
8140 smb_io_job_info_1("", buffer, info_1, 0);
8144 if (*needed > offered)
8145 return WERR_INSUFFICIENT_BUFFER;
8150 /****************************************************************************
8151 ****************************************************************************/
8153 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8158 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8160 DEVICEMODE *devmode = NULL;
8161 NT_DEVICEMODE *nt_devmode = NULL;
8163 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8165 ZERO_STRUCTP(info_2);
8167 if (info_2 == NULL) {
8172 for ( i=0; i<count && found==False; i++ )
8174 if (queue[i].job == (int)jobid)
8180 /* NT treats not found as bad param... yet another bad
8182 ret = WERR_INVALID_PARAM;
8186 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
8187 if (!W_ERROR_IS_OK(ret))
8191 * if the print job does not have a DEVMODE associated with it,
8192 * just use the one for the printer. A NULL devicemode is not
8193 * a failure condition
8196 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8197 devmode = construct_dev_mode(snum);
8199 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8200 ZERO_STRUCTP( devmode );
8201 convert_nt_devicemode( devmode, nt_devmode );
8205 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8207 *needed += spoolss_size_job_info_2(info_2);
8209 if (!alloc_buffer_size(buffer, *needed)) {
8210 ret = WERR_INSUFFICIENT_BUFFER;
8214 smb_io_job_info_2("", buffer, info_2, 0);
8216 if (*needed > offered) {
8217 ret = WERR_INSUFFICIENT_BUFFER;
8224 /* Cleanup allocated memory */
8226 free_job_info_2(info_2); /* Also frees devmode */
8228 free_a_printer(&ntprinter, 2);
8233 /****************************************************************************
8234 ****************************************************************************/
8236 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8238 POLICY_HND *handle = &q_u->handle;
8239 uint32 jobid = q_u->jobid;
8240 uint32 level = q_u->level;
8241 NEW_BUFFER *buffer = NULL;
8242 uint32 offered = q_u->offered;
8243 uint32 *needed = &r_u->needed;
8244 WERROR wstatus = WERR_OK;
8248 print_queue_struct *queue = NULL;
8249 print_status_struct prt_status;
8251 /* that's an [in out] buffer */
8252 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8253 buffer = r_u->buffer;
8255 DEBUG(5,("spoolss_getjob\n"));
8259 if (!get_printer_snum(p, handle, &snum))
8262 count = print_queue_status(snum, &queue, &prt_status);
8264 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8265 count, prt_status.status, prt_status.message));
8269 wstatus = getjob_level_1(queue, count, snum, jobid,
8270 buffer, offered, needed);
8273 wstatus = getjob_level_2(queue, count, snum, jobid,
8274 buffer, offered, needed);
8277 wstatus = WERR_UNKNOWN_LEVEL;
8285 /********************************************************************
8286 spoolss_getprinterdataex
8288 From MSDN documentation of GetPrinterDataEx: pass request
8289 to GetPrinterData if key is "PrinterDriverData".
8290 ********************************************************************/
8292 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8294 POLICY_HND *handle = &q_u->handle;
8295 uint32 in_size = q_u->size;
8296 uint32 *type = &r_u->type;
8297 uint32 *out_size = &r_u->size;
8298 uint8 **data = &r_u->data;
8299 uint32 *needed = &r_u->needed;
8300 fstring keyname, valuename;
8302 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8304 NT_PRINTER_INFO_LEVEL *printer = NULL;
8306 WERROR status = WERR_OK;
8308 DEBUG(4,("_spoolss_getprinterdataex\n"));
8310 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8311 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8313 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8314 keyname, valuename));
8316 /* in case of problem, return some default values */
8320 *out_size = in_size;
8323 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8324 status = WERR_BADFID;
8328 /* Is the handle to a printer or to the server? */
8330 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8331 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8332 status = WERR_INVALID_PARAM;
8336 if ( !get_printer_snum(p,handle, &snum) )
8339 status = get_a_printer(&printer, 2, lp_servicename(snum));
8340 if ( !W_ERROR_IS_OK(status) )
8343 /* check to see if the keyname is valid */
8344 if ( !strlen(keyname) ) {
8345 status = WERR_INVALID_PARAM;
8349 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8350 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8351 free_a_printer( &printer, 2 );
8352 status = WERR_BADFILE;
8356 /* When given a new keyname, we should just create it */
8358 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8360 if (*needed > *out_size)
8361 status = WERR_MORE_DATA;
8364 if ( !W_ERROR_IS_OK(status) )
8366 DEBUG(5, ("error: allocating %d\n", *out_size));
8368 /* reply this param doesn't exist */
8372 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8373 status = WERR_NOMEM;
8383 free_a_printer( &printer, 2 );
8388 /********************************************************************
8389 * spoolss_setprinterdataex
8390 ********************************************************************/
8392 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8394 POLICY_HND *handle = &q_u->handle;
8395 uint32 type = q_u->type;
8396 uint8 *data = q_u->data;
8397 uint32 real_len = q_u->real_len;
8399 NT_PRINTER_INFO_LEVEL *printer = NULL;
8401 WERROR status = WERR_OK;
8402 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8407 DEBUG(4,("_spoolss_setprinterdataex\n"));
8409 /* From MSDN documentation of SetPrinterDataEx: pass request to
8410 SetPrinterData if key is "PrinterDriverData" */
8413 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8417 if ( !get_printer_snum(p,handle, &snum) )
8421 * Access check : NT returns "access denied" if you make a
8422 * SetPrinterData call without the necessary privildge.
8423 * we were originally returning OK if nothing changed
8424 * which made Win2k issue **a lot** of SetPrinterData
8425 * when connecting to a printer --jerry
8428 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8430 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8431 return WERR_ACCESS_DENIED;
8434 status = get_a_printer(&printer, 2, lp_servicename(snum));
8435 if (!W_ERROR_IS_OK(status))
8438 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8439 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8441 /* check for OID in valuename */
8443 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8449 /* save the registry data */
8451 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8453 /* save the OID if one was specified and the previous set call succeeded */
8455 if ( W_ERROR_IS_OK(status) && oid_string )
8458 fstrcat( keyname, "\\" );
8459 fstrcat( keyname, SPOOL_OID_KEY );
8462 * I'm not checking the status here on purpose. Don't know
8463 * if this is right, but I'm returning the status from the
8464 * previous set_printer_dataex() call. I have no idea if
8465 * this is right. --jerry
8468 set_printer_dataex( printer, keyname, valuename,
8469 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8472 free_a_printer(&printer, 2);
8478 /********************************************************************
8479 * spoolss_deleteprinterdataex
8480 ********************************************************************/
8482 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8484 POLICY_HND *handle = &q_u->handle;
8485 UNISTR2 *value = &q_u->valuename;
8486 UNISTR2 *key = &q_u->keyname;
8488 NT_PRINTER_INFO_LEVEL *printer = NULL;
8490 WERROR status = WERR_OK;
8491 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8492 pstring valuename, keyname;
8494 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8497 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8501 if (!get_printer_snum(p, handle, &snum))
8504 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8505 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8506 return WERR_ACCESS_DENIED;
8509 status = get_a_printer(&printer, 2, lp_servicename(snum));
8510 if (!W_ERROR_IS_OK(status))
8513 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8514 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8516 status = delete_printer_dataex( printer, keyname, valuename );
8518 free_a_printer(&printer, 2);
8523 /********************************************************************
8524 * spoolss_enumprinterkey
8525 ********************************************************************/
8528 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8531 fstring *keynames = NULL;
8532 uint16 *enumkeys = NULL;
8535 POLICY_HND *handle = &q_u->handle;
8536 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8537 NT_PRINTER_DATA *data;
8538 NT_PRINTER_INFO_LEVEL *printer = NULL;
8540 WERROR status = WERR_BADFILE;
8543 DEBUG(4,("_spoolss_enumprinterkey\n"));
8546 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8550 if ( !get_printer_snum(p,handle, &snum) )
8553 status = get_a_printer(&printer, 2, lp_servicename(snum));
8554 if (!W_ERROR_IS_OK(status))
8557 /* get the list of subkey names */
8559 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8560 data = &printer->info_2->data;
8562 num_keys = get_printer_subkeys( data, key, &keynames );
8564 if ( num_keys == -1 ) {
8565 status = WERR_BADFILE;
8569 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8571 r_u->needed = printerkey_len*2;
8573 if ( q_u->size < r_u->needed ) {
8574 status = WERR_MORE_DATA;
8578 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8579 status = WERR_NOMEM;
8585 if ( q_u->size < r_u->needed )
8586 status = WERR_MORE_DATA;
8589 free_a_printer( &printer, 2 );
8590 SAFE_FREE( keynames );
8595 /********************************************************************
8596 * spoolss_deleteprinterkey
8597 ********************************************************************/
8599 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8601 POLICY_HND *handle = &q_u->handle;
8602 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8604 NT_PRINTER_INFO_LEVEL *printer = NULL;
8608 DEBUG(5,("spoolss_deleteprinterkey\n"));
8611 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8615 /* if keyname == NULL, return error */
8617 if ( !q_u->keyname.buffer )
8618 return WERR_INVALID_PARAM;
8620 if (!get_printer_snum(p, handle, &snum))
8623 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8624 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8625 return WERR_ACCESS_DENIED;
8628 status = get_a_printer(&printer, 2, lp_servicename(snum));
8629 if (!W_ERROR_IS_OK(status))
8632 /* delete the key and all subneys */
8634 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8636 status = delete_all_printer_data( printer->info_2, key );
8638 if ( W_ERROR_IS_OK(status) )
8639 status = mod_a_printer(*printer, 2);
8641 free_a_printer( &printer, 2 );
8647 /********************************************************************
8648 * spoolss_enumprinterdataex
8649 ********************************************************************/
8651 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8653 POLICY_HND *handle = &q_u->handle;
8654 uint32 in_size = q_u->size;
8657 NT_PRINTER_INFO_LEVEL *printer = NULL;
8658 PRINTER_ENUM_VALUES *enum_values = NULL;
8659 NT_PRINTER_DATA *p_data;
8661 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8666 REGISTRY_VALUE *val;
8671 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8674 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8678 /* first get the printer off of disk */
8680 if (!get_printer_snum(p,handle, &snum))
8683 ZERO_STRUCT(printer);
8684 result = get_a_printer(&printer, 2, lp_servicename(snum));
8685 if (!W_ERROR_IS_OK(result))
8688 /* now look for a match on the key name */
8690 p_data = &printer->info_2->data;
8692 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8693 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8695 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8696 result = WERR_INVALID_PARAM;
8703 /* allocate the memory for the array of pointers -- if necessary */
8705 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8708 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8710 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8711 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8712 result = WERR_NOMEM;
8716 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8720 * loop through all params and build the array to pass
8721 * back to the client
8724 for ( i=0; i<num_entries; i++ )
8726 /* lookup the registry value */
8728 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8729 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8733 value_name = regval_name( val );
8734 init_unistr( &enum_values[i].valuename, value_name );
8735 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8736 enum_values[i].type = regval_type( val );
8738 data_len = regval_size( val );
8740 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8742 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8744 result = WERR_NOMEM;
8748 enum_values[i].data_len = data_len;
8750 /* keep track of the size of the array in bytes */
8752 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8755 /* housekeeping information in the reply */
8757 r_u->needed = needed;
8758 r_u->returned = num_entries;
8760 if (needed > in_size) {
8761 result = WERR_MORE_DATA;
8765 /* copy data into the reply */
8767 r_u->ctr.size = r_u->needed;
8768 r_u->ctr.size_of_array = r_u->returned;
8769 r_u->ctr.values = enum_values;
8774 free_a_printer(&printer, 2);
8779 /****************************************************************************
8780 ****************************************************************************/
8782 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8784 init_unistr(&info->name, name);
8787 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8788 UNISTR2 *environment,
8795 pstring short_archi;
8796 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8798 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8800 if (get_short_archi(short_archi, long_archi)==False)
8801 return WERR_INVALID_ENVIRONMENT;
8803 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8806 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8808 fill_printprocessordirectory_1(info, path);
8810 *needed += spoolss_size_printprocessordirectory_info_1(info);
8812 if (!alloc_buffer_size(buffer, *needed)) {
8814 return WERR_INSUFFICIENT_BUFFER;
8817 smb_io_printprocessordirectory_1("", buffer, info, 0);
8821 if (*needed > offered)
8822 return WERR_INSUFFICIENT_BUFFER;
8827 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8829 uint32 level = q_u->level;
8830 NEW_BUFFER *buffer = NULL;
8831 uint32 offered = q_u->offered;
8832 uint32 *needed = &r_u->needed;
8835 /* that's an [in out] buffer */
8836 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8837 buffer = r_u->buffer;
8839 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8845 result = getprintprocessordirectory_level_1
8846 (&q_u->name, &q_u->environment, buffer, offered, needed);
8849 result = WERR_UNKNOWN_LEVEL;
8857 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
8858 SPOOL_R_REPLYOPENPRINTER *r_u)
8860 DEBUG(5,("_spoolss_replyopenprinter\n"));
8862 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
8867 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
8868 SPOOL_R_REPLYCLOSEPRINTER *r_u)
8870 DEBUG(5,("_spoolss_replycloseprinter\n"));