2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2002,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
40 #define PRINTER_HANDLE_IS_PRINTER 0
41 #define PRINTER_HANDLE_IS_PRINTSERVER 1
43 /* Table to map the driver version */
45 char * drv_ver_to_os[] = {
46 "WIN9X", /* driver version/cversion 0 */
48 "WINNT", /* driver version/cversion 2 */
49 "WIN2K", /* driver version/cversion 3 */
59 /* structure to store the printer handles */
60 /* and a reference to what it's pointing to */
61 /* and the notify info asked about */
62 /* that's the central struct */
63 typedef struct _Printer{
64 struct _Printer *prev, *next;
65 BOOL document_started;
67 uint32 jobid; /* jobid in printing backend */
71 fstring printerservername;
74 uint32 access_granted;
80 SPOOL_NOTIFY_OPTION *option;
81 POLICY_HND client_hnd;
82 uint32 client_connected;
90 /* devmode sent in the OpenPrinter() call */
91 NT_DEVICEMODE *nt_devmode;
95 static Printer_entry *printers_list;
97 typedef struct _counter_printer_0 {
105 static ubi_dlList counter_list;
107 static struct cli_state notify_cli; /* print notify back-channel */
108 static uint32 smb_connections=0;
111 /* in printing/nt_printing.c */
113 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
115 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
116 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
118 /* translate between internal status numbers and NT status numbers */
119 static int nt_printj_status(int v)
125 return JOB_STATUS_PAUSED;
127 return JOB_STATUS_SPOOLING;
129 return JOB_STATUS_PRINTING;
131 return JOB_STATUS_ERROR;
133 return JOB_STATUS_DELETING;
135 return JOB_STATUS_OFFLINE;
137 return JOB_STATUS_PAPEROUT;
139 return JOB_STATUS_PRINTED;
141 return JOB_STATUS_DELETED;
143 return JOB_STATUS_BLOCKED;
144 case LPQ_USER_INTERVENTION:
145 return JOB_STATUS_USER_INTERVENTION;
150 static int nt_printq_status(int v)
154 return PRINTER_STATUS_PAUSED;
163 /****************************************************************************
164 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
165 ****************************************************************************/
167 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
172 SAFE_FREE((*pp)->ctr.type);
176 /***************************************************************************
177 Disconnect from the client
178 ****************************************************************************/
180 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
185 * Tell the specific printing tdb we no longer want messages for this printer
186 * by deregistering our PID.
189 if (!print_notify_deregister_pid(snum))
190 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
192 /* weird if the test succeds !!! */
193 if (smb_connections==0) {
194 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
198 result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle);
200 if (!W_ERROR_IS_OK(result))
201 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
202 dos_errstr(result)));
204 /* if it's the last connection, deconnect the IPC$ share */
205 if (smb_connections==1) {
206 cli_nt_session_close(¬ify_cli);
207 cli_ulogoff(¬ify_cli);
208 cli_shutdown(¬ify_cli);
209 message_deregister(MSG_PRINTER_NOTIFY2);
211 /* Tell the connections db we're no longer interested in
212 * printer notify messages. */
214 register_message_flags( False, FLAG_MSG_PRINTING );
220 /****************************************************************************
221 Functions to free a printer entry datastruct.
222 ****************************************************************************/
224 static void free_printer_entry(void *ptr)
226 Printer_entry *Printer = (Printer_entry *)ptr;
228 if (Printer->notify.client_connected==True) {
231 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
233 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
234 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
235 snum = print_queue_snum(Printer->dev.handlename);
237 srv_spoolss_replycloseprinter(snum,
238 &Printer->notify.client_hnd);
242 Printer->notify.flags=0;
243 Printer->notify.options=0;
244 Printer->notify.localmachine[0]='\0';
245 Printer->notify.printerlocal=0;
246 free_spool_notify_option(&Printer->notify.option);
247 Printer->notify.option=NULL;
248 Printer->notify.client_connected=False;
250 free_nt_devicemode( &Printer->nt_devmode );
252 /* Remove from the internal list. */
253 DLIST_REMOVE(printers_list, Printer);
258 /****************************************************************************
259 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
260 ****************************************************************************/
262 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
264 SPOOL_NOTIFY_OPTION *new_sp = NULL;
269 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
276 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
278 if (!new_sp->ctr.type) {
287 /****************************************************************************
288 find printer index by handle
289 ****************************************************************************/
291 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
293 Printer_entry *find_printer = NULL;
295 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
296 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
303 /****************************************************************************
304 Close printer index by handle.
305 ****************************************************************************/
307 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
309 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
312 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
316 close_policy_hnd(p, hnd);
321 /****************************************************************************
322 Delete a printer given a handle.
323 ****************************************************************************/
325 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
327 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
330 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
335 * It turns out that Windows allows delete printer on a handle
336 * opened by an admin user, then used on a pipe handle created
337 * by an anonymous user..... but they're working on security.... riiight !
341 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
342 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
343 return WERR_ACCESS_DENIED;
347 /* Check calling user has permission to delete printer. Note that
348 since we set the snum parameter to -1 only administrators can
349 delete the printer. This stops people with the Full Control
350 permission from deleting the printer. */
352 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
353 DEBUG(3, ("printer delete denied by security descriptor\n"));
354 return WERR_ACCESS_DENIED;
358 if (del_a_printer(Printer->dev.handlename) != 0) {
359 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
363 if (*lp_deleteprinter_cmd()) {
365 char *cmd = lp_deleteprinter_cmd();
370 /* Printer->dev.handlename equals portname equals sharename */
371 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
372 Printer->dev.handlename);
374 DEBUG(10,("Running [%s]\n", command));
375 ret = smbrun(command, NULL);
377 return WERR_BADFID; /* What to return here? */
379 DEBUGADD(10,("returned [%d]\n", ret));
381 /* Send SIGHUP to process group... is there a better way? */
384 /* go ahead and re-read the services immediately */
385 reload_services( False );
387 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
388 return WERR_ACCESS_DENIED;
394 /****************************************************************************
395 Return the snum of a printer corresponding to an handle.
396 ****************************************************************************/
398 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
400 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
403 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
407 switch (Printer->printer_type) {
408 case PRINTER_HANDLE_IS_PRINTER:
409 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
410 *number = print_queue_snum(Printer->dev.handlename);
411 return (*number != -1);
412 case PRINTER_HANDLE_IS_PRINTSERVER:
419 /****************************************************************************
420 Set printer handle type.
421 Check if it's \\server or \\server\printer
422 ****************************************************************************/
424 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
426 DEBUG(3,("Setting printer type=%s\n", handlename));
428 if ( strlen(handlename) < 3 ) {
429 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
433 /* it's a print server */
434 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
435 DEBUGADD(4,("Printer is a print server\n"));
436 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
440 DEBUGADD(4,("Printer is a printer\n"));
441 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
447 /****************************************************************************
448 Set printer handle name.
449 ****************************************************************************/
451 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
454 int n_services=lp_numservices();
459 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
461 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
462 ZERO_STRUCT(Printer->dev.printerservername);
463 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
467 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
470 if (*handlename=='\\') {
471 aprinter=strchr_m(handlename+2, '\\');
478 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
481 * The original code allowed smbd to store a printer name that
482 * was different from the share name. This is not possible
483 * anymore, so I've simplified this loop greatly. Here
484 * we are just verifying that the printer name is a valid
485 * printer service defined in smb.conf
486 * --jerry [Fri Feb 15 11:17:46 CST 2002]
489 for (snum=0; snum<n_services; snum++) {
491 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
494 fstrcpy(sname, lp_servicename(snum));
496 DEBUGADD(5,("share:%s\n",sname));
498 if (! StrCaseCmp(sname, aprinter)) {
507 DEBUGADD(4,("Printer not found\n"));
511 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
513 ZERO_STRUCT(Printer->dev.handlename);
514 fstrcpy(Printer->dev.handlename, sname);
519 /****************************************************************************
520 Find first available printer slot. creates a printer handle for you.
521 ****************************************************************************/
523 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
525 Printer_entry *new_printer;
527 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
529 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
532 ZERO_STRUCTP(new_printer);
534 new_printer->notify.option=NULL;
536 /* Add to the internal list. */
537 DLIST_ADD(printers_list, new_printer);
539 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
540 SAFE_FREE(new_printer);
544 if (!set_printer_hnd_printertype(new_printer, name)) {
545 close_printer_handle(p, hnd);
549 if (!set_printer_hnd_name(new_printer, name)) {
550 close_printer_handle(p, hnd);
554 new_printer->access_granted = access_granted;
556 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
561 /****************************************************************************
562 Allocate more memory for a BUFFER.
563 ****************************************************************************/
565 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
573 /* damn, I'm doing the reverse operation of prs_grow() :) */
574 if (buffer_size < prs_data_size(ps))
577 extra_space = buffer_size - prs_data_size(ps);
580 * save the offset and move to the end of the buffer
581 * prs_grow() checks the extra_space against the offset
583 old_offset=prs_offset(ps);
584 prs_set_offset(ps, prs_data_size(ps));
586 if (!prs_grow(ps, extra_space))
589 prs_set_offset(ps, old_offset);
591 buffer->string_at_end=prs_data_size(ps);
596 /***************************************************************************
597 check to see if the client motify handle is monitoring the notification
598 given by (notify_type, notify_field).
599 **************************************************************************/
601 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
607 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
610 SPOOL_NOTIFY_OPTION *option = p->notify.option;
614 * Flags should always be zero when the change notify
615 * is registered by the cliebnt's spooler. A user Win32 app
616 * might use the flags though instead of the NOTIFY_OPTION_INFO
621 return is_monitoring_event_flags(
622 p->notify.flags, notify_type, notify_field);
624 for (i = 0; i < option->count; i++) {
626 /* Check match for notify_type */
628 if (option->ctr.type[i].type != notify_type)
631 /* Check match for field */
633 for (j = 0; j < option->ctr.type[i].count; j++) {
634 if (option->ctr.type[i].fields[j] == notify_field) {
640 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
641 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
642 p->dev.handlename : p->dev.printerservername,
643 notify_type, notify_field));
648 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
650 static void notify_one_value(struct spoolss_notify_msg *msg,
651 SPOOL_NOTIFY_INFO_DATA *data,
654 data->notify_data.value[0] = msg->notify.value[0];
655 data->notify_data.value[1] = 0;
658 static void notify_string(struct spoolss_notify_msg *msg,
659 SPOOL_NOTIFY_INFO_DATA *data,
664 /* The length of the message includes the trailing \0 */
666 init_unistr2(&unistr, msg->notify.data, msg->len);
668 data->notify_data.data.length = msg->len * 2;
669 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
671 if (!data->notify_data.data.string) {
672 data->notify_data.data.length = 0;
676 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
679 static void notify_system_time(struct spoolss_notify_msg *msg,
680 SPOOL_NOTIFY_INFO_DATA *data,
686 if (msg->len != sizeof(time_t)) {
687 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
692 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
693 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
697 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
698 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
702 if (!spoolss_io_system_time("", &ps, 0, &systime))
705 data->notify_data.data.length = prs_offset(&ps);
706 data->notify_data.data.string =
707 talloc(mem_ctx, prs_offset(&ps));
709 memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
714 struct notify2_message_table {
716 void (*fn)(struct spoolss_notify_msg *msg,
717 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
720 static struct notify2_message_table printer_notify_table[] = {
721 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
722 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
723 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
724 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
725 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
726 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
727 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
728 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
729 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
730 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
731 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
732 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
733 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
734 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
735 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
736 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
737 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
738 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
739 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
742 static struct notify2_message_table job_notify_table[] = {
743 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
744 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
745 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
746 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
747 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
748 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
749 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
750 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
751 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
752 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
753 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
754 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
755 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
756 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
757 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
758 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
759 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
760 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
761 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
762 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
763 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
764 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
765 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
766 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
770 /***********************************************************************
771 Allocate talloc context for container object
772 **********************************************************************/
774 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
779 ctr->ctx = talloc_init();
784 /***********************************************************************
785 release all allocated memory and zero out structure
786 **********************************************************************/
788 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
794 talloc_destroy(ctr->ctx);
801 /***********************************************************************
802 **********************************************************************/
804 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 /***********************************************************************
813 **********************************************************************/
815 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
817 if ( !ctr || !ctr->msg_groups )
820 if ( idx >= ctr->num_groups )
823 return &ctr->msg_groups[idx];
827 /***********************************************************************
828 How many groups of change messages do we have ?
829 **********************************************************************/
831 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
836 return ctr->num_groups;
839 /***********************************************************************
840 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
841 **********************************************************************/
843 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
845 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
846 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
847 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
853 /* loop over all groups looking for a matching printer name */
855 for ( i=0; i<ctr->num_groups; i++ ) {
856 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
860 /* add a new group? */
862 if ( i == ctr->num_groups )
866 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
867 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
870 ctr->msg_groups = groups;
872 /* clear the new entry and set the printer name */
874 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
875 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
878 /* add the change messages; 'i' is the correct index now regardless */
880 msg_grp = &ctr->msg_groups[i];
884 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
885 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
888 msg_grp->msgs = msg_list;
890 new_slot = msg_grp->num_msgs-1;
891 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
893 /* need to allocate own copy of data */
896 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
898 return ctr->num_groups;
901 /***********************************************************************
902 Send a change notication message on all handles which have a call
904 **********************************************************************/
906 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
909 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
910 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
911 SPOOLSS_NOTIFY_MSG *messages;
915 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
919 messages = msg_group->msgs;
922 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
926 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
928 /* loop over all printers */
930 for (p = printers_list; p; p = p->next)
932 SPOOL_NOTIFY_INFO_DATA *data;
937 /* Is there notification on this handle? */
939 if ( !p->notify.client_connected )
942 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
944 /* For this printer? Print servers always receive
947 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
948 ( !strequal(msg_group->printername, p->dev.handlename) ) )
951 DEBUG(10,("Our printer\n"));
953 /* allocate the max entries possible */
955 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
958 /* build the array of change notifications */
960 for ( i=0; i<msg_group->num_msgs; i++ )
962 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
964 /* Are we monitoring this event? */
966 if (!is_monitoring_event(p, msg->type, msg->field))
970 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
971 msg->type, msg->field, p->dev.handlename));
974 * if the is a printer notification handle and not a job notification
975 * type, then set the id to 0. Other wise just use what was specified
978 * When registering change notification on a print server handle
979 * we always need to send back the id (snum) matching the printer
980 * for which the change took place. For change notify registered
981 * on a printer handle, this does not matter and the id should be 0.
986 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
992 /* Convert unix jobid to smb jobid */
994 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID)
996 id = sysjob_to_jobid(msg->id);
999 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1004 construct_info_data( &data[data_len], msg->type, msg->field, id );
1007 case PRINTER_NOTIFY_TYPE:
1008 if ( !printer_notify_table[msg->field].fn )
1010 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1014 case JOB_NOTIFY_TYPE:
1015 if ( !job_notify_table[msg->field].fn )
1017 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1022 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1029 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1030 data_len, data, p->notify.change, 0 );
1034 DEBUG(8,("send_notify2_changes: Exit...\n"));
1038 /***********************************************************************
1039 **********************************************************************/
1041 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
1046 /* Unpack message */
1048 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1051 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
1052 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1055 tdb_unpack((char *)buf + offset, len - offset, "dd",
1056 &msg->notify.value[0], &msg->notify.value[1]);
1058 tdb_unpack((char *)buf + offset, len - offset, "B",
1059 &msg->len, &msg->notify.data);
1061 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1062 msg->type, msg->field, msg->flags));
1065 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1066 msg->notify.value[1]));
1068 dump_data(3, msg->notify.data, msg->len);
1073 /********************************************************************
1074 Receive a notify2 message list
1075 ********************************************************************/
1077 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1079 size_t msg_count, i;
1080 char *buf = (char *)msg;
1083 SPOOLSS_NOTIFY_MSG notify;
1084 SPOOLSS_NOTIFY_MSG_CTR messages;
1088 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1092 msg_count = IVAL(buf, 0);
1095 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1097 if (msg_count == 0) {
1098 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1102 /* initialize the container */
1104 ZERO_STRUCT( messages );
1105 notify_msg_ctr_init( &messages );
1108 * build message groups for each printer identified
1109 * in a change_notify msg. Remember that a PCN message
1110 * includes the handle returned for the srv_spoolss_replyopenprinter()
1111 * call. Therefore messages are grouped according to printer handle.
1114 for ( i=0; i<msg_count; i++ )
1116 if (msg_ptr + 4 - buf > len) {
1117 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1121 msg_len = IVAL(msg_ptr,0);
1124 if (msg_ptr + msg_len - buf > len) {
1125 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1129 /* unpack messages */
1131 ZERO_STRUCT( notify );
1132 notify2_unpack_msg( ¬ify, msg_ptr, msg_len );
1135 /* add to correct list in container */
1137 notify_msg_ctr_addmsg( &messages, ¬ify );
1139 /* free memory that might have been allocated by notify2_unpack_msg() */
1141 if ( notify.len != 0 )
1142 SAFE_FREE( notify.notify.data );
1145 /* process each group of messages */
1147 num_groups = notify_msg_ctr_numgroups( &messages );
1148 for ( i=0; i<num_groups; i++ )
1149 send_notify2_changes( &messages, i );
1154 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1156 notify_msg_ctr_destroy( &messages );
1161 /********************************************************************
1162 Send a message to ourself about new driver being installed
1163 so we can upgrade the information for each printer bound to this
1165 ********************************************************************/
1167 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1169 int len = strlen(drivername);
1174 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1177 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1182 /**********************************************************************
1183 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1184 over all printers, upgrading ones as neessary
1185 **********************************************************************/
1187 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1191 int n_services = lp_numservices();
1193 len = MIN(len,sizeof(drivername)-1);
1194 strncpy(drivername, buf, len);
1196 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1198 /* Iterate the printer list */
1200 for (snum=0; snum<n_services; snum++)
1202 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1205 NT_PRINTER_INFO_LEVEL *printer = NULL;
1207 result = get_a_printer(&printer, 2, lp_servicename(snum));
1208 if (!W_ERROR_IS_OK(result))
1211 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1213 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1215 /* all we care about currently is the change_id */
1217 result = mod_a_printer(*printer, 2);
1218 if (!W_ERROR_IS_OK(result)) {
1219 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1220 dos_errstr(result)));
1224 free_a_printer(&printer, 2);
1231 /********************************************************************
1232 Send a message to ourself about new driver being installed
1233 so we can upgrade the information for each printer bound to this
1235 ********************************************************************/
1237 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1239 int len = strlen(drivername);
1244 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1247 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1252 /**********************************************************************
1253 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1254 over all printers, resetting printer data as neessary
1255 **********************************************************************/
1257 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1261 int n_services = lp_numservices();
1263 len = MIN( len, sizeof(drivername)-1 );
1264 strncpy( drivername, buf, len );
1266 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1268 /* Iterate the printer list */
1270 for ( snum=0; snum<n_services; snum++ )
1272 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1275 NT_PRINTER_INFO_LEVEL *printer = NULL;
1277 result = get_a_printer( &printer, 2, lp_servicename(snum) );
1278 if ( !W_ERROR_IS_OK(result) )
1282 * if the printer is bound to the driver,
1283 * then reset to the new driver initdata
1286 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1288 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1290 if ( !set_driver_init(printer, 2) ) {
1291 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1292 printer->info_2->printername, printer->info_2->drivername));
1295 result = mod_a_printer( *printer, 2 );
1296 if ( !W_ERROR_IS_OK(result) ) {
1297 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1298 get_dos_error_msg(result)));
1302 free_a_printer( &printer, 2 );
1311 /********************************************************************
1312 Copy routines used by convert_to_openprinterex()
1313 *******************************************************************/
1315 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1323 DEBUG (8,("dup_devmode\n"));
1325 /* bulk copy first */
1327 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1331 /* dup the pointer members separately */
1333 len = unistrlen(devmode->devicename.buffer);
1335 d->devicename.buffer = talloc(ctx, len*2);
1336 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1341 len = unistrlen(devmode->formname.buffer);
1343 d->devicename.buffer = talloc(ctx, len*2);
1344 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1348 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1353 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1355 if (!new_ctr || !ctr)
1358 DEBUG(8,("copy_devmode_ctr\n"));
1360 new_ctr->size = ctr->size;
1361 new_ctr->devmode_ptr = ctr->devmode_ptr;
1363 if(ctr->devmode_ptr)
1364 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1367 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1369 if (!new_def || !def)
1372 DEBUG(8,("copy_printer_defaults\n"));
1374 new_def->datatype_ptr = def->datatype_ptr;
1376 if (def->datatype_ptr)
1377 copy_unistr2(&new_def->datatype, &def->datatype);
1379 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1381 new_def->access_required = def->access_required;
1384 /********************************************************************
1385 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1386 * SPOOL_Q_OPEN_PRINTER_EX structure
1387 ********************************************************************/
1389 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1391 if (!q_u_ex || !q_u)
1394 DEBUG(8,("convert_to_openprinterex\n"));
1396 q_u_ex->printername_ptr = q_u->printername_ptr;
1398 if (q_u->printername_ptr)
1399 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1401 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1404 /********************************************************************
1405 * spoolss_open_printer
1407 * called from the spoolss dispatcher
1408 ********************************************************************/
1410 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1412 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1413 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1418 ZERO_STRUCT(q_u_ex);
1419 ZERO_STRUCT(r_u_ex);
1421 /* convert the OpenPrinter() call to OpenPrinterEx() */
1423 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1425 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1427 /* convert back to OpenPrinter() */
1429 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1434 /********************************************************************
1435 * spoolss_open_printer
1437 * If the openprinterex rpc call contains a devmode,
1438 * it's a per-user one. This per-user devmode is derivated
1439 * from the global devmode. Openprinterex() contains a per-user
1440 * devmode for when you do EMF printing and spooling.
1441 * In the EMF case, the NT workstation is only doing half the job
1442 * of rendering the page. The other half is done by running the printer
1443 * driver on the server.
1444 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1445 * The EMF file only contains what is to be printed on the page.
1446 * So in order for the server to know how to print, the NT client sends
1447 * a devicemode attached to the openprinterex call.
1448 * But this devicemode is short lived, it's only valid for the current print job.
1450 * If Samba would have supported EMF spooling, this devicemode would
1451 * have been attached to the handle, to sent it to the driver to correctly
1452 * rasterize the EMF file.
1454 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1455 * we just act as a pass-thru between windows and the printer.
1457 * In order to know that Samba supports only RAW spooling, NT has to call
1458 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1459 * and until NT sends a RAW job, we refuse it.
1461 * But to call getprinter() or startdoc(), you first need a valid handle,
1462 * and to get an handle you have to call openprintex(). Hence why you have
1463 * a devicemode in the openprinterex() call.
1466 * Differences between NT4 and NT 2000.
1469 * On NT4, you only have a global devicemode. This global devicemode can be changed
1470 * by the administrator (or by a user with enough privs). Everytime a user
1471 * wants to print, the devicemode is resetted to the default. In Word, everytime
1472 * you print, the printer's characteristics are always reset to the global devicemode.
1476 * In W2K, there is the notion of per-user devicemode. The first time you use
1477 * a printer, a per-user devicemode is build from the global devicemode.
1478 * If you change your per-user devicemode, it is saved in the registry, under the
1479 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1480 * printer preferences available.
1482 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1483 * on the General Tab of the printer properties windows.
1485 * To change the global devicemode: it's the "Printing Defaults..." button
1486 * on the Advanced Tab of the printer properties window.
1489 ********************************************************************/
1491 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1493 UNISTR2 *printername = NULL;
1494 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1495 POLICY_HND *handle = &r_u->handle;
1499 struct current_user user;
1500 Printer_entry *Printer=NULL;
1502 if (q_u->printername_ptr != 0)
1503 printername = &q_u->printername;
1505 if (printername == NULL)
1506 return WERR_INVALID_PRINTER_NAME;
1508 /* some sanity check because you can open a printer or a print server */
1509 /* aka: \\server\printer or \\server */
1510 unistr2_to_ascii(name, printername, sizeof(name)-1);
1512 DEBUGADD(3,("checking name: %s\n",name));
1514 if (!open_printer_hnd(p, handle, name, 0))
1515 return WERR_INVALID_PRINTER_NAME;
1517 Printer=find_printer_index_by_hnd(p, handle);
1519 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1520 Can't find printer handle we created for printer %s\n", name ));
1521 close_printer_handle(p,handle);
1522 return WERR_INVALID_PRINTER_NAME;
1525 get_current_user(&user, p);
1528 * First case: the user is opening the print server:
1530 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1531 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1533 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1534 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1535 * or if the user is listed in the smb.conf printer admin parameter.
1537 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1538 * client view printer folder, but does not show the MSAPW.
1540 * Note: this test needs code to check access rights here too. Jeremy
1541 * could you look at this?
1543 * Second case: the user is opening a printer:
1544 * NT doesn't let us connect to a printer if the connecting user
1545 * doesn't have print permission.
1548 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1550 /* Printserver handles use global struct... */
1554 /* Map standard access rights to object specific access rights */
1556 se_map_standard(&printer_default->access_required,
1557 &printserver_std_mapping);
1559 /* Deny any object specific bits that don't apply to print
1560 servers (i.e printer and job specific bits) */
1562 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1564 if (printer_default->access_required &
1565 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1566 DEBUG(3, ("access DENIED for non-printserver bits"));
1567 close_printer_handle(p, handle);
1568 return WERR_ACCESS_DENIED;
1571 /* Allow admin access */
1573 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1575 if (!lp_ms_add_printer_wizard()) {
1576 close_printer_handle(p, handle);
1577 return WERR_ACCESS_DENIED;
1580 /* if the user is not root and not a printer admin, then fail */
1583 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
1585 close_printer_handle(p, handle);
1586 return WERR_ACCESS_DENIED;
1589 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1593 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1596 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1597 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1599 /* We fall through to return WERR_OK */
1604 /* NT doesn't let us connect to a printer if the connecting user
1605 doesn't have print permission. */
1607 if (!get_printer_snum(p, handle, &snum))
1610 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1612 /* map an empty access mask to the minimum access mask */
1613 if (printer_default->access_required == 0x0)
1614 printer_default->access_required = PRINTER_ACCESS_USE;
1617 * If we are not serving the printer driver for this printer,
1618 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1619 * will keep NT clients happy --jerry
1622 if (lp_use_client_driver(snum)
1623 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1625 printer_default->access_required = PRINTER_ACCESS_USE;
1628 /* check smb.conf parameters and the the sec_desc */
1630 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1631 DEBUG(3, ("access DENIED for printer open\n"));
1632 close_printer_handle(p, handle);
1633 return WERR_ACCESS_DENIED;
1636 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1637 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1638 close_printer_handle(p, handle);
1639 return WERR_ACCESS_DENIED;
1642 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1643 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1645 printer_default->access_required = PRINTER_ACCESS_USE;
1647 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1648 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1652 Printer->access_granted = printer_default->access_required;
1655 * If the client sent a devmode in the OpenPrinter() call, then
1656 * save it here in case we get a job submission on this handle
1659 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1660 && q_u->printer_default.devmode_cont.devmode_ptr )
1662 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1663 &Printer->nt_devmode );
1669 /****************************************************************************
1670 ****************************************************************************/
1672 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1673 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1679 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1688 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1689 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1695 printer->info_3=NULL;
1696 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1700 printer->info_6=NULL;
1701 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1711 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1712 NT_DEVICEMODE **pp_nt_devmode)
1714 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1717 * Ensure nt_devmode is a valid pointer
1718 * as we will be overwriting it.
1721 if (nt_devmode == NULL) {
1722 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1723 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1727 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1728 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1730 nt_devmode->specversion=devmode->specversion;
1731 nt_devmode->driverversion=devmode->driverversion;
1732 nt_devmode->size=devmode->size;
1733 nt_devmode->fields=devmode->fields;
1734 nt_devmode->orientation=devmode->orientation;
1735 nt_devmode->papersize=devmode->papersize;
1736 nt_devmode->paperlength=devmode->paperlength;
1737 nt_devmode->paperwidth=devmode->paperwidth;
1738 nt_devmode->scale=devmode->scale;
1739 nt_devmode->copies=devmode->copies;
1740 nt_devmode->defaultsource=devmode->defaultsource;
1741 nt_devmode->printquality=devmode->printquality;
1742 nt_devmode->color=devmode->color;
1743 nt_devmode->duplex=devmode->duplex;
1744 nt_devmode->yresolution=devmode->yresolution;
1745 nt_devmode->ttoption=devmode->ttoption;
1746 nt_devmode->collate=devmode->collate;
1748 nt_devmode->logpixels=devmode->logpixels;
1749 nt_devmode->bitsperpel=devmode->bitsperpel;
1750 nt_devmode->pelswidth=devmode->pelswidth;
1751 nt_devmode->pelsheight=devmode->pelsheight;
1752 nt_devmode->displayflags=devmode->displayflags;
1753 nt_devmode->displayfrequency=devmode->displayfrequency;
1754 nt_devmode->icmmethod=devmode->icmmethod;
1755 nt_devmode->icmintent=devmode->icmintent;
1756 nt_devmode->mediatype=devmode->mediatype;
1757 nt_devmode->dithertype=devmode->dithertype;
1758 nt_devmode->reserved1=devmode->reserved1;
1759 nt_devmode->reserved2=devmode->reserved2;
1760 nt_devmode->panningwidth=devmode->panningwidth;
1761 nt_devmode->panningheight=devmode->panningheight;
1764 * Only change private and driverextra if the incoming devmode
1765 * has a new one. JRA.
1768 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1769 SAFE_FREE(nt_devmode->private);
1770 nt_devmode->driverextra=devmode->driverextra;
1771 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1773 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1776 *pp_nt_devmode = nt_devmode;
1781 /********************************************************************
1782 * _spoolss_enddocprinter_internal.
1783 ********************************************************************/
1785 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1787 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1791 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1795 if (!get_printer_snum(p, handle, &snum))
1798 Printer->document_started=False;
1799 print_job_end(snum, Printer->jobid,True);
1800 /* error codes unhandled so far ... */
1805 /********************************************************************
1806 * api_spoolss_closeprinter
1807 ********************************************************************/
1809 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1811 POLICY_HND *handle = &q_u->handle;
1813 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1815 if (Printer && Printer->document_started)
1816 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1818 if (!close_printer_handle(p, handle))
1821 /* clear the returned printer handle. Observed behavior
1822 from Win2k server. Don't think this really matters.
1823 Previous code just copied the value of the closed
1826 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1831 /********************************************************************
1832 * api_spoolss_deleteprinter
1834 ********************************************************************/
1836 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1838 POLICY_HND *handle = &q_u->handle;
1839 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1842 if (Printer && Printer->document_started)
1843 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1845 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1847 result = delete_printer_handle(p, handle);
1849 update_c_setprinter(False);
1854 /*******************************************************************
1855 * static function to lookup the version id corresponding to an
1856 * long architecture string
1857 ******************************************************************/
1859 static int get_version_id (char * arch)
1862 struct table_node archi_table[]= {
1864 {"Windows 4.0", "WIN40", 0 },
1865 {"Windows NT x86", "W32X86", 2 },
1866 {"Windows NT R4000", "W32MIPS", 2 },
1867 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1868 {"Windows NT PowerPC", "W32PPC", 2 },
1872 for (i=0; archi_table[i].long_archi != NULL; i++)
1874 if (strcmp(arch, archi_table[i].long_archi) == 0)
1875 return (archi_table[i].version);
1881 /********************************************************************
1882 * _spoolss_deleteprinterdriver
1883 ********************************************************************/
1885 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1889 NT_PRINTER_DRIVER_INFO_LEVEL info;
1890 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1892 struct current_user user;
1894 WERROR status_win2k = WERR_ACCESS_DENIED;
1896 get_current_user(&user, p);
1898 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1899 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1901 /* check that we have a valid driver name first */
1903 if ((version=get_version_id(arch)) == -1)
1904 return WERR_INVALID_ENVIRONMENT;
1907 ZERO_STRUCT(info_win2k);
1909 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1911 /* try for Win2k driver if "Windows NT x86" */
1913 if ( version == 2 ) {
1915 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1916 status = WERR_UNKNOWN_PRINTER_DRIVER;
1920 /* otherwise it was a failure */
1922 status = WERR_UNKNOWN_PRINTER_DRIVER;
1928 if (printer_driver_in_use(info.info_3)) {
1929 status = WERR_PRINTER_DRIVER_IN_USE;
1935 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1937 /* if we get to here, we now have 2 driver info structures to remove */
1938 /* remove the Win2k driver first*/
1940 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1941 free_a_printer_driver( info_win2k, 3 );
1943 /* this should not have failed---if it did, report to client */
1944 if ( !W_ERROR_IS_OK(status_win2k) )
1949 status = delete_printer_driver(info.info_3, &user, version, False);
1951 /* if at least one of the deletes succeeded return OK */
1953 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1957 free_a_printer_driver( info, 3 );
1962 /********************************************************************
1963 * spoolss_deleteprinterdriverex
1964 ********************************************************************/
1966 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1970 NT_PRINTER_DRIVER_INFO_LEVEL info;
1971 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1973 uint32 flags = q_u->delete_flags;
1975 struct current_user user;
1977 WERROR status_win2k = WERR_ACCESS_DENIED;
1979 get_current_user(&user, p);
1981 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1982 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1984 /* check that we have a valid driver name first */
1985 if ((version=get_version_id(arch)) == -1) {
1986 /* this is what NT returns */
1987 return WERR_INVALID_ENVIRONMENT;
1990 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
1991 version = q_u->version;
1994 ZERO_STRUCT(info_win2k);
1996 status = get_a_printer_driver(&info, 3, driver, arch, version);
1998 if ( !W_ERROR_IS_OK(status) )
2001 * if the client asked for a specific version,
2002 * or this is something other than Windows NT x86,
2006 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2009 /* try for Win2k driver if "Windows NT x86" */
2012 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2013 status = WERR_UNKNOWN_PRINTER_DRIVER;
2018 if ( printer_driver_in_use(info.info_3) ) {
2019 status = WERR_PRINTER_DRIVER_IN_USE;
2024 * we have a couple of cases to consider.
2025 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2026 * then the delete should fail if **any** files overlap with
2028 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2029 * non-overlapping files
2030 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2031 * is set, the do not delete any files
2032 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2035 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2037 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2039 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2040 /* no idea of the correct error here */
2041 status = WERR_ACCESS_DENIED;
2046 /* also check for W32X86/3 if necessary; maybe we already have? */
2048 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2049 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2052 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2053 /* no idea of the correct error here */
2054 free_a_printer_driver( info_win2k, 3 );
2055 status = WERR_ACCESS_DENIED;
2059 /* if we get to here, we now have 2 driver info structures to remove */
2060 /* remove the Win2k driver first*/
2062 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2063 free_a_printer_driver( info_win2k, 3 );
2065 /* this should not have failed---if it did, report to client */
2067 if ( !W_ERROR_IS_OK(status_win2k) )
2072 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2074 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2077 free_a_printer_driver( info, 3 );
2083 /****************************************************************************
2084 Internal routine for retreiving printerdata
2085 ***************************************************************************/
2087 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2088 char *key, char *value, uint32 *type, uint8 **data,
2089 uint32 *needed, uint32 in_size )
2091 REGISTRY_VALUE *val;
2094 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2095 return WERR_BADFILE;
2097 *type = regval_type( val );
2099 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2101 size = regval_size( val );
2103 /* copy the min(in_size, len) */
2106 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2107 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2115 DEBUG(5,("get_printer_dataex: copy done\n"));
2120 /****************************************************************************
2121 Internal routine for removing printerdata
2122 ***************************************************************************/
2124 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value )
2126 delete_printer_data( printer->info_2, key, value );
2128 return mod_a_printer(*printer, 2);
2131 /****************************************************************************
2132 Internal routine for storing printerdata
2133 ***************************************************************************/
2135 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value,
2136 uint32 type, uint8 *data, int real_len )
2138 delete_printer_data( printer->info_2, key, value );
2140 add_printer_data( printer->info_2, key, value, type, data, real_len );
2142 return mod_a_printer(*printer, 2);
2145 /********************************************************************
2146 GetPrinterData on a printer server Handle.
2147 ********************************************************************/
2149 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2153 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2155 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2157 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2163 if (!StrCaseCmp(value, "BeepEnabled")) {
2165 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2167 SIVAL(*data, 0, 0x00);
2172 if (!StrCaseCmp(value, "EventLog")) {
2174 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2176 /* formally was 0x1b */
2177 SIVAL(*data, 0, 0x0);
2182 if (!StrCaseCmp(value, "NetPopup")) {
2184 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2186 SIVAL(*data, 0, 0x00);
2191 if (!StrCaseCmp(value, "MajorVersion")) {
2193 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2204 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2207 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2209 *needed = 2*(strlen(string)+1);
2210 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2212 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2214 /* it's done by hand ready to go on the wire */
2215 for (i=0; i<strlen(string); i++) {
2216 (*data)[2*i]=string[i];
2217 (*data)[2*i+1]='\0';
2222 if (!StrCaseCmp(value, "Architecture")) {
2223 pstring string="Windows NT x86";
2225 *needed = 2*(strlen(string)+1);
2226 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2228 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2229 for (i=0; i<strlen(string); i++) {
2230 (*data)[2*i]=string[i];
2231 (*data)[2*i+1]='\0';
2236 if (!StrCaseCmp(value, "DsPresent")) {
2238 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2240 SIVAL(*data, 0, 0x01);
2245 if (!StrCaseCmp(value, "DNSMachineName")) {
2248 if (!get_myfullname(hostname))
2249 return WERR_BADFILE;
2251 *needed = 2*(strlen(hostname)+1);
2252 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2254 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2255 for (i=0; i<strlen(hostname); i++) {
2256 (*data)[2*i]=hostname[i];
2257 (*data)[2*i+1]='\0';
2263 return WERR_BADFILE;
2266 /********************************************************************
2267 * spoolss_getprinterdata
2268 ********************************************************************/
2270 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2272 POLICY_HND *handle = &q_u->handle;
2273 UNISTR2 *valuename = &q_u->valuename;
2274 uint32 in_size = q_u->size;
2275 uint32 *type = &r_u->type;
2276 uint32 *out_size = &r_u->size;
2277 uint8 **data = &r_u->data;
2278 uint32 *needed = &r_u->needed;
2281 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2282 NT_PRINTER_INFO_LEVEL *printer = NULL;
2286 * Reminder: when it's a string, the length is in BYTES
2287 * even if UNICODE is negociated.
2292 *out_size = in_size;
2294 /* in case of problem, return some default values */
2299 DEBUG(4,("_spoolss_getprinterdata\n"));
2302 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2303 status = WERR_BADFID;
2307 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2309 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2310 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2313 if ( !get_printer_snum(p,handle, &snum) ) {
2314 status = WERR_BADFID;
2318 status = get_a_printer(&printer, 2, lp_servicename(snum));
2319 if ( !W_ERROR_IS_OK(status) )
2322 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2324 if ( strequal(value, "ChangeId") ) {
2326 *needed = sizeof(uint32);
2327 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2328 status = WERR_NOMEM;
2331 **data = printer->info_2->changeid;
2335 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2338 if (*needed > *out_size)
2339 status = WERR_MORE_DATA;
2342 if ( !W_ERROR_IS_OK(status) )
2344 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2346 /* reply this param doesn't exist */
2349 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2351 free_a_printer( &printer, 2 );
2360 /* cleanup & exit */
2363 free_a_printer( &printer, 2 );
2368 /*********************************************************
2369 Connect to the client machine.
2370 **********************************************************/
2372 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, const char *remote_machine)
2374 ZERO_STRUCTP(the_cli);
2375 if(cli_initialise(the_cli) == NULL) {
2376 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2380 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2381 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2382 cli_shutdown(the_cli);
2386 if (ismyip(the_cli->dest_ip)) {
2387 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2388 cli_shutdown(the_cli);
2392 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2393 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2394 cli_shutdown(the_cli);
2398 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2399 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2401 cli_shutdown(the_cli);
2405 the_cli->protocol = PROTOCOL_NT1;
2407 if (!cli_negprot(the_cli)) {
2408 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2409 cli_shutdown(the_cli);
2413 if (the_cli->protocol != PROTOCOL_NT1) {
2414 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2415 cli_shutdown(the_cli);
2420 * Do an anonymous session setup.
2423 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2424 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2425 cli_shutdown(the_cli);
2429 if (!(the_cli->sec_mode & 1)) {
2430 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2431 cli_shutdown(the_cli);
2435 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2436 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2437 cli_shutdown(the_cli);
2442 * Ok - we have an anonymous connection to the IPC$ share.
2443 * Now start the NT Domain stuff :-).
2446 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2447 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)));
2448 cli_nt_session_close(the_cli);
2449 cli_ulogoff(the_cli);
2450 cli_shutdown(the_cli);
2457 /***************************************************************************
2458 Connect to the client.
2459 ****************************************************************************/
2461 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2466 * If it's the first connection, contact the client
2467 * and connect to the IPC$ share anonumously
2469 if (smb_connections==0) {
2470 fstring unix_printer;
2472 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2474 if(!spoolss_connect_to_client(¬ify_cli, unix_printer))
2477 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2478 /* Tell the connections db we're now interested in printer
2479 * notify messages. */
2480 register_message_flags( True, FLAG_MSG_PRINTING );
2484 * Tell the specific printing tdb we want messages for this printer
2485 * by registering our PID.
2488 if (!print_notify_register_pid(snum))
2489 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2493 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2496 if (!W_ERROR_IS_OK(result))
2497 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2498 dos_errstr(result)));
2500 return (W_ERROR_IS_OK(result));
2503 /********************************************************************
2505 * ReplyFindFirstPrinterChangeNotifyEx
2507 * before replying OK: status=0 a rpc call is made to the workstation
2508 * asking ReplyOpenPrinter
2510 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2511 * called from api_spoolss_rffpcnex
2512 ********************************************************************/
2514 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2516 POLICY_HND *handle = &q_u->handle;
2517 uint32 flags = q_u->flags;
2518 uint32 options = q_u->options;
2519 UNISTR2 *localmachine = &q_u->localmachine;
2520 uint32 printerlocal = q_u->printerlocal;
2522 SPOOL_NOTIFY_OPTION *option = q_u->option;
2524 /* store the notify value in the printer struct */
2526 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2529 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2533 Printer->notify.flags=flags;
2534 Printer->notify.options=options;
2535 Printer->notify.printerlocal=printerlocal;
2537 if (Printer->notify.option)
2538 free_spool_notify_option(&Printer->notify.option);
2540 Printer->notify.option=dup_spool_notify_option(option);
2542 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2543 sizeof(Printer->notify.localmachine)-1);
2545 /* Connect to the client machine and send a ReplyOpenPrinter */
2547 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2549 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2550 !get_printer_snum(p, handle, &snum) )
2553 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2554 Printer->notify.printerlocal, 1,
2555 &Printer->notify.client_hnd))
2556 return WERR_SERVER_UNAVAILABLE;
2558 Printer->notify.client_connected=True;
2563 /*******************************************************************
2564 * fill a notify_info_data with the servername
2565 ********************************************************************/
2567 void spoolss_notify_server_name(int snum,
2568 SPOOL_NOTIFY_INFO_DATA *data,
2569 print_queue_struct *queue,
2570 NT_PRINTER_INFO_LEVEL *printer,
2571 TALLOC_CTX *mem_ctx)
2573 pstring temp_name, temp;
2576 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2578 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2580 data->notify_data.data.length = len;
2581 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2583 if (!data->notify_data.data.string) {
2584 data->notify_data.data.length = 0;
2588 memcpy(data->notify_data.data.string, temp, len);
2591 /*******************************************************************
2592 * fill a notify_info_data with the printername (not including the servername).
2593 ********************************************************************/
2595 void spoolss_notify_printer_name(int snum,
2596 SPOOL_NOTIFY_INFO_DATA *data,
2597 print_queue_struct *queue,
2598 NT_PRINTER_INFO_LEVEL *printer,
2599 TALLOC_CTX *mem_ctx)
2604 /* the notify name should not contain the \\server\ part */
2605 char *p = strrchr(printer->info_2->printername, '\\');
2608 p = printer->info_2->printername;
2613 len = rpcstr_push(temp, p, 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 servicename
2628 ********************************************************************/
2630 void spoolss_notify_share_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 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2641 data->notify_data.data.length = len;
2642 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2644 if (!data->notify_data.data.string) {
2645 data->notify_data.data.length = 0;
2649 memcpy(data->notify_data.data.string, temp, len);
2652 /*******************************************************************
2653 * fill a notify_info_data with the port name
2654 ********************************************************************/
2656 void spoolss_notify_port_name(int snum,
2657 SPOOL_NOTIFY_INFO_DATA *data,
2658 print_queue_struct *queue,
2659 NT_PRINTER_INFO_LEVEL *printer,
2660 TALLOC_CTX *mem_ctx)
2665 /* even if it's strange, that's consistant in all the code */
2667 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2669 data->notify_data.data.length = len;
2670 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2672 if (!data->notify_data.data.string) {
2673 data->notify_data.data.length = 0;
2677 memcpy(data->notify_data.data.string, temp, len);
2680 /*******************************************************************
2681 * fill a notify_info_data with the printername
2682 * but it doesn't exist, have to see what to do
2683 ********************************************************************/
2685 void spoolss_notify_driver_name(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 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2696 data->notify_data.data.length = len;
2697 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2699 if (!data->notify_data.data.string) {
2700 data->notify_data.data.length = 0;
2704 memcpy(data->notify_data.data.string, temp, len);
2707 /*******************************************************************
2708 * fill a notify_info_data with the comment
2709 ********************************************************************/
2711 void spoolss_notify_comment(int snum,
2712 SPOOL_NOTIFY_INFO_DATA *data,
2713 print_queue_struct *queue,
2714 NT_PRINTER_INFO_LEVEL *printer,
2715 TALLOC_CTX *mem_ctx)
2720 if (*printer->info_2->comment == '\0')
2721 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2723 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2725 data->notify_data.data.length = len;
2726 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2728 if (!data->notify_data.data.string) {
2729 data->notify_data.data.length = 0;
2733 memcpy(data->notify_data.data.string, temp, len);
2736 /*******************************************************************
2737 * fill a notify_info_data with the comment
2738 * location = "Room 1, floor 2, building 3"
2739 ********************************************************************/
2741 void spoolss_notify_location(int snum,
2742 SPOOL_NOTIFY_INFO_DATA *data,
2743 print_queue_struct *queue,
2744 NT_PRINTER_INFO_LEVEL *printer,
2745 TALLOC_CTX *mem_ctx)
2750 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2752 data->notify_data.data.length = len;
2753 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2755 if (!data->notify_data.data.string) {
2756 data->notify_data.data.length = 0;
2760 memcpy(data->notify_data.data.string, temp, len);
2763 /*******************************************************************
2764 * fill a notify_info_data with the device mode
2765 * jfm:xxxx don't to it for know but that's a real problem !!!
2766 ********************************************************************/
2768 static void spoolss_notify_devmode(int snum,
2769 SPOOL_NOTIFY_INFO_DATA *data,
2770 print_queue_struct *queue,
2771 NT_PRINTER_INFO_LEVEL *printer,
2772 TALLOC_CTX *mem_ctx)
2776 /*******************************************************************
2777 * fill a notify_info_data with the separator file name
2778 ********************************************************************/
2780 void spoolss_notify_sepfile(int snum,
2781 SPOOL_NOTIFY_INFO_DATA *data,
2782 print_queue_struct *queue,
2783 NT_PRINTER_INFO_LEVEL *printer,
2784 TALLOC_CTX *mem_ctx)
2789 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2791 data->notify_data.data.length = len;
2792 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2794 if (!data->notify_data.data.string) {
2795 data->notify_data.data.length = 0;
2799 memcpy(data->notify_data.data.string, temp, len);
2802 /*******************************************************************
2803 * fill a notify_info_data with the print processor
2804 * jfm:xxxx return always winprint to indicate we don't do anything to it
2805 ********************************************************************/
2807 void spoolss_notify_print_processor(int snum,
2808 SPOOL_NOTIFY_INFO_DATA *data,
2809 print_queue_struct *queue,
2810 NT_PRINTER_INFO_LEVEL *printer,
2811 TALLOC_CTX *mem_ctx)
2816 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2818 data->notify_data.data.length = len;
2819 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2821 if (!data->notify_data.data.string) {
2822 data->notify_data.data.length = 0;
2826 memcpy(data->notify_data.data.string, temp, len);
2829 /*******************************************************************
2830 * fill a notify_info_data with the print processor options
2831 * jfm:xxxx send an empty string
2832 ********************************************************************/
2834 void spoolss_notify_parameters(int snum,
2835 SPOOL_NOTIFY_INFO_DATA *data,
2836 print_queue_struct *queue,
2837 NT_PRINTER_INFO_LEVEL *printer,
2838 TALLOC_CTX *mem_ctx)
2843 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2845 data->notify_data.data.length = len;
2846 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2848 if (!data->notify_data.data.string) {
2849 data->notify_data.data.length = 0;
2853 memcpy(data->notify_data.data.string, temp, len);
2856 /*******************************************************************
2857 * fill a notify_info_data with the data type
2858 * jfm:xxxx always send RAW as data type
2859 ********************************************************************/
2861 void spoolss_notify_datatype(int snum,
2862 SPOOL_NOTIFY_INFO_DATA *data,
2863 print_queue_struct *queue,
2864 NT_PRINTER_INFO_LEVEL *printer,
2865 TALLOC_CTX *mem_ctx)
2870 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2872 data->notify_data.data.length = len;
2873 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2875 if (!data->notify_data.data.string) {
2876 data->notify_data.data.length = 0;
2880 memcpy(data->notify_data.data.string, temp, len);
2883 /*******************************************************************
2884 * fill a notify_info_data with the security descriptor
2885 * jfm:xxxx send an null pointer to say no security desc
2886 * have to implement security before !
2887 ********************************************************************/
2889 static void spoolss_notify_security_desc(int snum,
2890 SPOOL_NOTIFY_INFO_DATA *data,
2891 print_queue_struct *queue,
2892 NT_PRINTER_INFO_LEVEL *printer,
2893 TALLOC_CTX *mem_ctx)
2895 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2896 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2899 /*******************************************************************
2900 * fill a notify_info_data with the attributes
2901 * jfm:xxxx a samba printer is always shared
2902 ********************************************************************/
2904 void spoolss_notify_attributes(int snum,
2905 SPOOL_NOTIFY_INFO_DATA *data,
2906 print_queue_struct *queue,
2907 NT_PRINTER_INFO_LEVEL *printer,
2908 TALLOC_CTX *mem_ctx)
2910 data->notify_data.value[0] = printer->info_2->attributes;
2911 data->notify_data.value[1] = 0;
2914 /*******************************************************************
2915 * fill a notify_info_data with the priority
2916 ********************************************************************/
2918 static void spoolss_notify_priority(int snum,
2919 SPOOL_NOTIFY_INFO_DATA *data,
2920 print_queue_struct *queue,
2921 NT_PRINTER_INFO_LEVEL *printer,
2922 TALLOC_CTX *mem_ctx)
2924 data->notify_data.value[0] = printer->info_2->priority;
2925 data->notify_data.value[1] = 0;
2928 /*******************************************************************
2929 * fill a notify_info_data with the default priority
2930 ********************************************************************/
2932 static void spoolss_notify_default_priority(int snum,
2933 SPOOL_NOTIFY_INFO_DATA *data,
2934 print_queue_struct *queue,
2935 NT_PRINTER_INFO_LEVEL *printer,
2936 TALLOC_CTX *mem_ctx)
2938 data->notify_data.value[0] = printer->info_2->default_priority;
2939 data->notify_data.value[1] = 0;
2942 /*******************************************************************
2943 * fill a notify_info_data with the start time
2944 ********************************************************************/
2946 static void spoolss_notify_start_time(int snum,
2947 SPOOL_NOTIFY_INFO_DATA *data,
2948 print_queue_struct *queue,
2949 NT_PRINTER_INFO_LEVEL *printer,
2950 TALLOC_CTX *mem_ctx)
2952 data->notify_data.value[0] = printer->info_2->starttime;
2953 data->notify_data.value[1] = 0;
2956 /*******************************************************************
2957 * fill a notify_info_data with the until time
2958 ********************************************************************/
2960 static void spoolss_notify_until_time(int snum,
2961 SPOOL_NOTIFY_INFO_DATA *data,
2962 print_queue_struct *queue,
2963 NT_PRINTER_INFO_LEVEL *printer,
2964 TALLOC_CTX *mem_ctx)
2966 data->notify_data.value[0] = printer->info_2->untiltime;
2967 data->notify_data.value[1] = 0;
2970 /*******************************************************************
2971 * fill a notify_info_data with the status
2972 ********************************************************************/
2974 static void spoolss_notify_status(int snum,
2975 SPOOL_NOTIFY_INFO_DATA *data,
2976 print_queue_struct *queue,
2977 NT_PRINTER_INFO_LEVEL *printer,
2978 TALLOC_CTX *mem_ctx)
2980 print_status_struct status;
2982 print_queue_length(snum, &status);
2983 data->notify_data.value[0]=(uint32) status.status;
2984 data->notify_data.value[1] = 0;
2987 /*******************************************************************
2988 * fill a notify_info_data with the number of jobs queued
2989 ********************************************************************/
2991 void spoolss_notify_cjobs(int snum,
2992 SPOOL_NOTIFY_INFO_DATA *data,
2993 print_queue_struct *queue,
2994 NT_PRINTER_INFO_LEVEL *printer,
2995 TALLOC_CTX *mem_ctx)
2997 data->notify_data.value[0] = print_queue_length(snum, NULL);
2998 data->notify_data.value[1] = 0;
3001 /*******************************************************************
3002 * fill a notify_info_data with the average ppm
3003 ********************************************************************/
3005 static void spoolss_notify_average_ppm(int snum,
3006 SPOOL_NOTIFY_INFO_DATA *data,
3007 print_queue_struct *queue,
3008 NT_PRINTER_INFO_LEVEL *printer,
3009 TALLOC_CTX *mem_ctx)
3011 /* always respond 8 pages per minutes */
3012 /* a little hard ! */
3013 data->notify_data.value[0] = printer->info_2->averageppm;
3014 data->notify_data.value[1] = 0;
3017 /*******************************************************************
3018 * fill a notify_info_data with username
3019 ********************************************************************/
3021 static void spoolss_notify_username(int snum,
3022 SPOOL_NOTIFY_INFO_DATA *data,
3023 print_queue_struct *queue,
3024 NT_PRINTER_INFO_LEVEL *printer,
3025 TALLOC_CTX *mem_ctx)
3030 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3032 data->notify_data.data.length = len;
3033 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3035 if (!data->notify_data.data.string) {
3036 data->notify_data.data.length = 0;
3040 memcpy(data->notify_data.data.string, temp, len);
3043 /*******************************************************************
3044 * fill a notify_info_data with job status
3045 ********************************************************************/
3047 static void spoolss_notify_job_status(int snum,
3048 SPOOL_NOTIFY_INFO_DATA *data,
3049 print_queue_struct *queue,
3050 NT_PRINTER_INFO_LEVEL *printer,
3051 TALLOC_CTX *mem_ctx)
3053 data->notify_data.value[0]=nt_printj_status(queue->status);
3054 data->notify_data.value[1] = 0;
3057 /*******************************************************************
3058 * fill a notify_info_data with job name
3059 ********************************************************************/
3061 static void spoolss_notify_job_name(int snum,
3062 SPOOL_NOTIFY_INFO_DATA *data,
3063 print_queue_struct *queue,
3064 NT_PRINTER_INFO_LEVEL *printer,
3065 TALLOC_CTX *mem_ctx)
3070 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3072 data->notify_data.data.length = len;
3073 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3075 if (!data->notify_data.data.string) {
3076 data->notify_data.data.length = 0;
3080 memcpy(data->notify_data.data.string, temp, len);
3083 /*******************************************************************
3084 * fill a notify_info_data with job status
3085 ********************************************************************/
3087 static void spoolss_notify_job_status_string(int snum,
3088 SPOOL_NOTIFY_INFO_DATA *data,
3089 print_queue_struct *queue,
3090 NT_PRINTER_INFO_LEVEL *printer,
3091 TALLOC_CTX *mem_ctx)
3094 * Now we're returning job status codes we just return a "" here. JRA.
3101 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3104 switch (queue->status) {
3109 p = ""; /* NT provides the paused string */
3118 #endif /* NO LONGER NEEDED. */
3120 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3122 data->notify_data.data.length = len;
3123 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3125 if (!data->notify_data.data.string) {
3126 data->notify_data.data.length = 0;
3130 memcpy(data->notify_data.data.string, temp, len);
3133 /*******************************************************************
3134 * fill a notify_info_data with job time
3135 ********************************************************************/
3137 static void spoolss_notify_job_time(int snum,
3138 SPOOL_NOTIFY_INFO_DATA *data,
3139 print_queue_struct *queue,
3140 NT_PRINTER_INFO_LEVEL *printer,
3141 TALLOC_CTX *mem_ctx)
3143 data->notify_data.value[0]=0x0;
3144 data->notify_data.value[1]=0;
3147 /*******************************************************************
3148 * fill a notify_info_data with job size
3149 ********************************************************************/
3151 static void spoolss_notify_job_size(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]=queue->size;
3158 data->notify_data.value[1]=0;
3161 /*******************************************************************
3162 * fill a notify_info_data with page info
3163 ********************************************************************/
3164 static void spoolss_notify_total_pages(int snum,
3165 SPOOL_NOTIFY_INFO_DATA *data,
3166 print_queue_struct *queue,
3167 NT_PRINTER_INFO_LEVEL *printer,
3168 TALLOC_CTX *mem_ctx)
3170 data->notify_data.value[0]=queue->page_count;
3171 data->notify_data.value[1]=0;
3174 /*******************************************************************
3175 * fill a notify_info_data with pages printed info.
3176 ********************************************************************/
3177 static void spoolss_notify_pages_printed(int snum,
3178 SPOOL_NOTIFY_INFO_DATA *data,
3179 print_queue_struct *queue,
3180 NT_PRINTER_INFO_LEVEL *printer,
3181 TALLOC_CTX *mem_ctx)
3183 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3184 data->notify_data.value[1]=0;
3187 /*******************************************************************
3188 Fill a notify_info_data with job position.
3189 ********************************************************************/
3191 static void spoolss_notify_job_position(int snum,
3192 SPOOL_NOTIFY_INFO_DATA *data,
3193 print_queue_struct *queue,
3194 NT_PRINTER_INFO_LEVEL *printer,
3195 TALLOC_CTX *mem_ctx)
3197 data->notify_data.value[0]=queue->job;
3198 data->notify_data.value[1]=0;
3201 /*******************************************************************
3202 Fill a notify_info_data with submitted time.
3203 ********************************************************************/
3205 static void spoolss_notify_submitted_time(int snum,
3206 SPOOL_NOTIFY_INFO_DATA *data,
3207 print_queue_struct *queue,
3208 NT_PRINTER_INFO_LEVEL *printer,
3209 TALLOC_CTX *mem_ctx)
3216 t=gmtime(&queue->time);
3218 len = sizeof(SYSTEMTIME);
3220 data->notify_data.data.length = len;
3221 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3223 if (!data->notify_data.data.string) {
3224 data->notify_data.data.length = 0;
3228 make_systemtime(&st, t);
3231 * Systemtime must be linearized as a set of UINT16's.
3232 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3235 p = (char *)data->notify_data.data.string;
3236 SSVAL(p, 0, st.year);
3237 SSVAL(p, 2, st.month);
3238 SSVAL(p, 4, st.dayofweek);
3239 SSVAL(p, 6, st.day);
3240 SSVAL(p, 8, st.hour);
3241 SSVAL(p, 10, st.minute);
3242 SSVAL(p, 12, st.second);
3243 SSVAL(p, 14, st.milliseconds);
3246 struct s_notify_info_data_table
3252 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3253 print_queue_struct *queue,
3254 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3257 /* A table describing the various print notification constants and
3258 whether the notification data is a pointer to a variable sized
3259 buffer, a one value uint32 or a two value uint32. */
3261 struct s_notify_info_data_table notify_info_data_table[] =
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3289 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3290 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3291 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3314 /*******************************************************************
3315 Return the size of info_data structure.
3316 ********************************************************************/
3318 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3322 for (i = 0; i < sizeof(notify_info_data_table); i++)
3324 if ( (notify_info_data_table[i].type == type)
3325 && (notify_info_data_table[i].field == field) )
3327 switch(notify_info_data_table[i].size)
3329 case NOTIFY_ONE_VALUE:
3330 case NOTIFY_TWO_VALUE:
3335 /* The only pointer notify data I have seen on
3336 the wire is the submitted time and this has
3337 the notify size set to 4. -tpot */
3339 case NOTIFY_POINTER:
3342 case NOTIFY_SECDESC:
3348 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3353 /*******************************************************************
3354 Return the type of notify_info_data.
3355 ********************************************************************/
3357 static int type_of_notify_info_data(uint16 type, uint16 field)
3361 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3362 if (notify_info_data_table[i].type == type &&
3363 notify_info_data_table[i].field == field)
3364 return notify_info_data_table[i].size;
3370 /****************************************************************************
3371 ****************************************************************************/
3373 static int search_notify(uint16 type, uint16 field, int *value)
3377 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3378 if (notify_info_data_table[i].type == type &&
3379 notify_info_data_table[i].field == field &&
3380 notify_info_data_table[i].fn != NULL) {
3389 /****************************************************************************
3390 ****************************************************************************/
3392 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3394 info_data->type = type;
3395 info_data->field = field;
3396 info_data->reserved = 0;
3398 info_data->size = size_of_notify_info_data(type, field);
3399 info_data->enc_type = type_of_notify_info_data(type, field);
3406 /*******************************************************************
3408 * fill a notify_info struct with info asked
3410 ********************************************************************/
3412 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
3413 snum, SPOOL_NOTIFY_OPTION_TYPE
3414 *option_type, uint32 id,
3415 TALLOC_CTX *mem_ctx)
3421 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3422 NT_PRINTER_INFO_LEVEL *printer = NULL;
3423 print_queue_struct *queue=NULL;
3425 type=option_type->type;
3427 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3428 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3429 option_type->count, lp_servicename(snum)));
3431 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3434 for(field_num=0; field_num<option_type->count; field_num++)
3436 field = option_type->fields[field_num];
3438 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3440 if (!search_notify(type, field, &j) )
3443 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
3445 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3451 current_data = &info->data[info->count];
3453 construct_info_data(current_data, type, field, id);
3455 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3456 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3458 notify_info_data_table[j].fn(snum, current_data, queue,
3464 free_a_printer(&printer, 2);
3468 /*******************************************************************
3470 * fill a notify_info struct with info asked
3472 ********************************************************************/
3474 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3475 SPOOL_NOTIFY_INFO *info,
3476 NT_PRINTER_INFO_LEVEL *printer,
3477 int snum, SPOOL_NOTIFY_OPTION_TYPE
3478 *option_type, uint32 id,
3479 TALLOC_CTX *mem_ctx)
3485 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3487 DEBUG(4,("construct_notify_jobs_info\n"));
3489 type = option_type->type;
3491 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3492 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3493 option_type->count));
3495 for(field_num=0; field_num<option_type->count; field_num++) {
3496 field = option_type->fields[field_num];
3498 if (!search_notify(type, field, &j) )
3501 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3502 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3505 else info->data = tid;
3507 current_data=&(info->data[info->count]);
3509 construct_info_data(current_data, type, field, id);
3510 notify_info_data_table[j].fn(snum, current_data, queue,
3519 * JFM: The enumeration is not that simple, it's even non obvious.
3521 * let's take an example: I want to monitor the PRINTER SERVER for
3522 * the printer's name and the number of jobs currently queued.
3523 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3524 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3526 * I have 3 printers on the back of my server.
3528 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3531 * 1 printer 1 name 1
3532 * 2 printer 1 cjob 1
3533 * 3 printer 2 name 2
3534 * 4 printer 2 cjob 2
3535 * 5 printer 3 name 3
3536 * 6 printer 3 name 3
3538 * that's the print server case, the printer case is even worse.
3541 /*******************************************************************
3543 * enumerate all printers on the printserver
3544 * fill a notify_info struct with info asked
3546 ********************************************************************/
3548 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3549 SPOOL_NOTIFY_INFO *info,
3550 TALLOC_CTX *mem_ctx)
3553 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3554 int n_services=lp_numservices();
3557 SPOOL_NOTIFY_OPTION *option;
3558 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3560 DEBUG(4,("printserver_notify_info\n"));
3565 option=Printer->notify.option;
3571 for (i=0; i<option->count; i++) {
3572 option_type=&(option->ctr.type[i]);
3574 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3577 for (snum=0; snum<n_services; snum++)
3579 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3580 construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
3586 * Debugging information, don't delete.
3589 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3590 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3591 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3593 for (i=0; i<info->count; i++) {
3594 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3595 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3596 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3603 /*******************************************************************
3605 * fill a notify_info struct with info asked
3607 ********************************************************************/
3609 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3610 TALLOC_CTX *mem_ctx)
3613 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3616 SPOOL_NOTIFY_OPTION *option;
3617 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3619 print_queue_struct *queue=NULL;
3620 print_status_struct status;
3622 DEBUG(4,("printer_notify_info\n"));
3627 option=Printer->notify.option;
3633 get_printer_snum(p, hnd, &snum);
3635 for (i=0; i<option->count; i++) {
3636 option_type=&option->ctr.type[i];
3638 switch ( option_type->type ) {
3639 case PRINTER_NOTIFY_TYPE:
3640 if(construct_notify_printer_info(info, snum,
3646 case JOB_NOTIFY_TYPE: {
3647 NT_PRINTER_INFO_LEVEL *printer = NULL;
3649 count = print_queue_status(snum, &queue, &status);
3651 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3652 lp_servicename(snum))))
3655 for (j=0; j<count; j++) {
3656 construct_notify_jobs_info(&queue[j], info,
3663 free_a_printer(&printer, 2);
3673 * Debugging information, don't delete.
3676 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3677 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3678 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3680 for (i=0; i<info->count; i++) {
3681 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3682 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3683 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3689 /********************************************************************
3691 ********************************************************************/
3693 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3695 POLICY_HND *handle = &q_u->handle;
3696 SPOOL_NOTIFY_INFO *info = &r_u->info;
3698 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3699 WERROR result = WERR_BADFID;
3701 /* we always have a NOTIFY_INFO struct */
3705 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3706 OUR_HANDLE(handle)));
3710 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3713 * We are now using the change value, and
3714 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3715 * I don't have a global notification system, I'm sending back all the
3716 * informations even when _NOTHING_ has changed.
3719 /* We need to keep track of the change value to send back in
3720 RRPCN replies otherwise our updates are ignored. */
3722 if (Printer->notify.client_connected) {
3723 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3724 Printer->notify.change = q_u->change;
3727 /* just ignore the SPOOL_NOTIFY_OPTION */
3729 switch (Printer->printer_type) {
3730 case PRINTER_HANDLE_IS_PRINTSERVER:
3731 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3734 case PRINTER_HANDLE_IS_PRINTER:
3735 result = printer_notify_info(p, handle, info, p->mem_ctx);
3743 /********************************************************************
3744 * construct_printer_info_0
3745 * fill a printer_info_0 struct
3746 ********************************************************************/
3748 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3752 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3753 counter_printer_0 *session_counter;
3754 uint32 global_counter;
3757 print_status_struct status;
3759 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3762 count = print_queue_length(snum, &status);
3764 /* check if we already have a counter for this printer */
3765 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3767 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3768 if (session_counter->snum == snum)
3772 /* it's the first time, add it to the list */
3773 if (session_counter==NULL) {
3774 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3775 free_a_printer(&ntprinter, 2);
3778 ZERO_STRUCTP(session_counter);
3779 session_counter->snum=snum;
3780 session_counter->counter=0;
3781 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3785 session_counter->counter++;
3788 * the global_counter should be stored in a TDB as it's common to all the clients
3789 * and should be zeroed on samba startup
3791 global_counter=session_counter->counter;
3793 pstrcpy(chaine,ntprinter->info_2->printername);
3795 init_unistr(&printer->printername, chaine);
3797 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3798 init_unistr(&printer->servername, chaine);
3800 printer->cjobs = count;
3801 printer->total_jobs = 0;
3802 printer->total_bytes = 0;
3804 setuptime = (time_t)ntprinter->info_2->setuptime;
3805 t=gmtime(&setuptime);
3807 printer->year = t->tm_year+1900;
3808 printer->month = t->tm_mon+1;
3809 printer->dayofweek = t->tm_wday;
3810 printer->day = t->tm_mday;
3811 printer->hour = t->tm_hour;
3812 printer->minute = t->tm_min;
3813 printer->second = t->tm_sec;
3814 printer->milliseconds = 0;
3816 printer->global_counter = global_counter;
3817 printer->total_pages = 0;
3819 printer->major_version = 0x0005; /* NT 5 */
3820 printer->build_version = 0x0893; /* build 2195 */
3822 printer->major_version = 0x0004; /* NT 4 */
3823 printer->build_version = 0x0565; /* build 1381 */
3825 printer->unknown7 = 0x1;
3826 printer->unknown8 = 0x0;
3827 printer->unknown9 = 0x0;
3828 printer->session_counter = session_counter->counter;
3829 printer->unknown11 = 0x0;
3830 printer->printer_errors = 0x0; /* number of print failure */
3831 printer->unknown13 = 0x0;
3832 printer->unknown14 = 0x1;
3833 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3834 printer->unknown16 = 0x0;
3835 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3836 printer->unknown18 = 0x0;
3837 printer->status = nt_printq_status(status.status);
3838 printer->unknown20 = 0x0;
3839 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3840 printer->unknown22 = 0x0;
3841 printer->unknown23 = 0x6; /* 6 ???*/
3842 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3843 printer->unknown25 = 0;
3844 printer->unknown26 = 0;
3845 printer->unknown27 = 0;
3846 printer->unknown28 = 0;
3847 printer->unknown29 = 0;
3849 free_a_printer(&ntprinter,2);
3853 /********************************************************************
3854 * construct_printer_info_1
3855 * fill a printer_info_1 struct
3856 ********************************************************************/
3857 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3861 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3863 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3866 printer->flags=flags;
3868 if (*ntprinter->info_2->comment == '\0') {
3869 init_unistr(&printer->comment, lp_comment(snum));
3870 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3871 ntprinter->info_2->drivername, lp_comment(snum));
3874 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3875 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3876 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3879 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3881 init_unistr(&printer->description, chaine);
3882 init_unistr(&printer->name, chaine2);
3884 free_a_printer(&ntprinter,2);
3889 /****************************************************************************
3890 Free a DEVMODE struct.
3891 ****************************************************************************/
3893 static void free_dev_mode(DEVICEMODE *dev)
3898 SAFE_FREE(dev->private);
3903 /****************************************************************************
3904 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3905 should be valid upon entry
3906 ****************************************************************************/
3908 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
3910 if ( !devmode || !ntdevmode )
3913 init_unistr(&devmode->devicename, ntdevmode->devicename);
3915 init_unistr(&devmode->formname, ntdevmode->formname);
3917 devmode->specversion = ntdevmode->specversion;
3918 devmode->driverversion = ntdevmode->driverversion;
3919 devmode->size = ntdevmode->size;
3920 devmode->driverextra = ntdevmode->driverextra;
3921 devmode->fields = ntdevmode->fields;
3923 devmode->orientation = ntdevmode->orientation;
3924 devmode->papersize = ntdevmode->papersize;
3925 devmode->paperlength = ntdevmode->paperlength;
3926 devmode->paperwidth = ntdevmode->paperwidth;
3927 devmode->scale = ntdevmode->scale;
3928 devmode->copies = ntdevmode->copies;
3929 devmode->defaultsource = ntdevmode->defaultsource;
3930 devmode->printquality = ntdevmode->printquality;
3931 devmode->color = ntdevmode->color;
3932 devmode->duplex = ntdevmode->duplex;
3933 devmode->yresolution = ntdevmode->yresolution;
3934 devmode->ttoption = ntdevmode->ttoption;
3935 devmode->collate = ntdevmode->collate;
3936 devmode->icmmethod = ntdevmode->icmmethod;
3937 devmode->icmintent = ntdevmode->icmintent;
3938 devmode->mediatype = ntdevmode->mediatype;
3939 devmode->dithertype = ntdevmode->dithertype;
3941 if (ntdevmode->private != NULL) {
3942 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3949 /****************************************************************************
3950 Create a DEVMODE struct. Returns malloced memory.
3951 ****************************************************************************/
3953 DEVICEMODE *construct_dev_mode(int snum)
3955 NT_PRINTER_INFO_LEVEL *printer = NULL;
3956 DEVICEMODE *devmode = NULL;
3958 DEBUG(7,("construct_dev_mode\n"));
3960 DEBUGADD(8,("getting printer characteristics\n"));
3962 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3965 if ( !printer->info_2->devmode ) {
3966 DEBUG(5, ("BONG! There was no device mode!\n"));
3970 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3971 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3975 ZERO_STRUCTP(devmode);
3977 DEBUGADD(8,("loading DEVICEMODE\n"));
3979 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
3980 free_dev_mode( devmode );
3985 free_a_printer(&printer,2);
3990 /********************************************************************
3991 * construct_printer_info_2
3992 * fill a printer_info_2 struct
3993 ********************************************************************/
3995 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3998 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4000 print_status_struct status;
4002 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4005 count = print_queue_length(snum, &status);
4007 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4008 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4009 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4010 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4011 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4013 if (*ntprinter->info_2->comment == '\0')
4014 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4016 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4018 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4019 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4020 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4021 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4022 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4024 printer->attributes = ntprinter->info_2->attributes;
4026 printer->priority = ntprinter->info_2->priority; /* priority */
4027 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4028 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4029 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4030 printer->status = nt_printq_status(status.status); /* status */
4031 printer->cjobs = count; /* jobs */
4032 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4034 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4035 DEBUG(8, ("Returning NULL Devicemode!\n"));
4038 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4039 /* steal the printer info sec_desc structure. [badly done]. */
4040 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4041 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4042 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4043 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4046 printer->secdesc = NULL;
4049 free_a_printer(&ntprinter, 2);
4053 /********************************************************************
4054 * construct_printer_info_3
4055 * fill a printer_info_3 struct
4056 ********************************************************************/
4058 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
4060 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4061 PRINTER_INFO_3 *printer = NULL;
4063 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4067 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4068 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4072 ZERO_STRUCTP(printer);
4074 printer->flags = 4; /* These are the components of the SD we are returning. */
4075 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4076 /* steal the printer info sec_desc structure. [badly done]. */
4077 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4081 * Set the flags for the components we are returning.
4084 if (printer->secdesc->owner_sid)
4085 printer->flags |= OWNER_SECURITY_INFORMATION;
4087 if (printer->secdesc->grp_sid)
4088 printer->flags |= GROUP_SECURITY_INFORMATION;
4090 if (printer->secdesc->dacl)
4091 printer->flags |= DACL_SECURITY_INFORMATION;
4093 if (printer->secdesc->sacl)
4094 printer->flags |= SACL_SECURITY_INFORMATION;
4097 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4098 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4099 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4102 free_a_printer(&ntprinter, 2);
4104 *pp_printer = printer;
4108 /********************************************************************
4109 * construct_printer_info_4
4110 * fill a printer_info_4 struct
4111 ********************************************************************/
4113 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
4115 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4117 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4120 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4121 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4122 printer->attributes = ntprinter->info_2->attributes;
4124 free_a_printer(&ntprinter, 2);
4128 /********************************************************************
4129 * construct_printer_info_5
4130 * fill a printer_info_5 struct
4131 ********************************************************************/
4133 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
4135 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4137 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4140 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4141 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
4142 printer->attributes = ntprinter->info_2->attributes;
4143 printer->device_not_selected_timeout = 0x3a98;
4144 printer->transmission_retry_timeout = 0xafc8;
4146 free_a_printer(&ntprinter, 2);
4150 /********************************************************************
4151 * construct_printer_info_7
4152 * fill a printer_info_7 struct
4153 ********************************************************************/
4155 static BOOL construct_printer_info_7(PRINTER_INFO_7 *printer, int snum)
4157 char *guid_str = NULL;
4160 if (is_printer_published(snum, &guid)) {
4161 asprintf(&guid_str, "{%s}", uuid_string_static(guid));
4163 init_unistr(&printer->guid, guid_str);
4164 printer->action = SPOOL_DS_PUBLISH;
4166 init_unistr(&printer->guid, "");
4167 printer->action = SPOOL_DS_UNPUBLISH;
4173 /********************************************************************
4174 Spoolss_enumprinters.
4175 ********************************************************************/
4177 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4181 int n_services=lp_numservices();
4182 PRINTER_INFO_1 *tp, *printers=NULL;
4183 PRINTER_INFO_1 current_prt;
4185 DEBUG(4,("enum_all_printers_info_1\n"));
4187 for (snum=0; snum<n_services; snum++) {
4188 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4189 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4191 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
4192 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4193 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4194 SAFE_FREE(printers);
4199 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4201 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4207 /* check the required size. */
4208 for (i=0; i<*returned; i++)
4209 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4211 if (!alloc_buffer_size(buffer, *needed))
4212 return WERR_INSUFFICIENT_BUFFER;
4214 /* fill the buffer with the structures */
4215 for (i=0; i<*returned; i++)
4216 smb_io_printer_info_1("", buffer, &printers[i], 0);
4219 SAFE_FREE(printers);
4221 if (*needed > offered) {
4223 return WERR_INSUFFICIENT_BUFFER;
4229 /********************************************************************
4230 enum_all_printers_info_1_local.
4231 *********************************************************************/
4233 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4235 DEBUG(4,("enum_all_printers_info_1_local\n"));
4237 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4240 /********************************************************************
4241 enum_all_printers_info_1_name.
4242 *********************************************************************/
4244 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4248 DEBUG(4,("enum_all_printers_info_1_name\n"));
4250 if ((name[0] == '\\') && (name[1] == '\\'))
4253 if (is_myname_or_ipaddr(s)) {
4254 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4257 return WERR_INVALID_NAME;
4260 /********************************************************************
4261 enum_all_printers_info_1_remote.
4262 *********************************************************************/
4264 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4266 PRINTER_INFO_1 *printer;
4267 fstring printername;
4270 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4272 /* JFM: currently it's more a place holder than anything else.
4273 * In the spooler world there is a notion of server registration.
4274 * the print servers are registring (sp ?) on the PDC (in the same domain)
4276 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4279 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4284 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4285 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4286 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4288 init_unistr(&printer->description, desc);
4289 init_unistr(&printer->name, printername);
4290 init_unistr(&printer->comment, comment);
4291 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4293 /* check the required size. */
4294 *needed += spoolss_size_printer_info_1(printer);
4296 if (!alloc_buffer_size(buffer, *needed)) {
4298 return WERR_INSUFFICIENT_BUFFER;
4301 /* fill the buffer with the structures */
4302 smb_io_printer_info_1("", buffer, printer, 0);
4307 if (*needed > offered) {
4309 return WERR_INSUFFICIENT_BUFFER;
4315 /********************************************************************
4316 enum_all_printers_info_1_network.
4317 *********************************************************************/
4319 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4323 DEBUG(4,("enum_all_printers_info_1_network\n"));
4325 /* If we respond to a enum_printers level 1 on our name with flags
4326 set to PRINTER_ENUM_REMOTE with a list of printers then these
4327 printers incorrectly appear in the APW browse list.
4328 Specifically the printers for the server appear at the workgroup
4329 level where all the other servers in the domain are
4330 listed. Windows responds to this call with a
4331 WERR_CAN_NOT_COMPLETE so we should do the same. */
4333 if (name[0] == '\\' && name[1] == '\\')
4336 if (is_myname_or_ipaddr(s))
4337 return WERR_CAN_NOT_COMPLETE;
4339 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4342 /********************************************************************
4343 * api_spoolss_enumprinters
4345 * called from api_spoolss_enumprinters (see this to understand)
4346 ********************************************************************/
4348 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4352 int n_services=lp_numservices();
4353 PRINTER_INFO_2 *tp, *printers=NULL;
4354 PRINTER_INFO_2 current_prt;
4356 for (snum=0; snum<n_services; snum++) {
4357 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4358 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4360 if (construct_printer_info_2(¤t_prt, snum)) {
4361 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4362 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4363 SAFE_FREE(printers);
4368 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4369 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4375 /* check the required size. */
4376 for (i=0; i<*returned; i++)
4377 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4379 if (!alloc_buffer_size(buffer, *needed)) {
4380 for (i=0; i<*returned; i++) {
4381 free_devmode(printers[i].devmode);
4383 SAFE_FREE(printers);
4384 return WERR_INSUFFICIENT_BUFFER;
4387 /* fill the buffer with the structures */
4388 for (i=0; i<*returned; i++)
4389 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4392 for (i=0; i<*returned; i++) {
4393 free_devmode(printers[i].devmode);
4395 SAFE_FREE(printers);
4397 if (*needed > offered) {
4399 return WERR_INSUFFICIENT_BUFFER;
4405 /********************************************************************
4406 * handle enumeration of printers at level 1
4407 ********************************************************************/
4409 static WERROR enumprinters_level1( uint32 flags, fstring name,
4410 NEW_BUFFER *buffer, uint32 offered,
4411 uint32 *needed, uint32 *returned)
4413 /* Not all the flags are equals */
4415 if (flags & PRINTER_ENUM_LOCAL)
4416 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4418 if (flags & PRINTER_ENUM_NAME)
4419 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4421 if (flags & PRINTER_ENUM_REMOTE)
4422 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4424 if (flags & PRINTER_ENUM_NETWORK)
4425 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4427 return WERR_OK; /* NT4sp5 does that */
4430 /********************************************************************
4431 * handle enumeration of printers at level 2
4432 ********************************************************************/
4434 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4435 NEW_BUFFER *buffer, uint32 offered,
4436 uint32 *needed, uint32 *returned)
4438 char *s = servername;
4440 if (flags & PRINTER_ENUM_LOCAL) {
4441 return enum_all_printers_info_2(buffer, offered, needed, returned);
4444 if (flags & PRINTER_ENUM_NAME) {
4445 if ((servername[0] == '\\') && (servername[1] == '\\'))
4447 if (is_myname_or_ipaddr(s))
4448 return enum_all_printers_info_2(buffer, offered, needed, returned);
4450 return WERR_INVALID_NAME;
4453 if (flags & PRINTER_ENUM_REMOTE)
4454 return WERR_UNKNOWN_LEVEL;
4459 /********************************************************************
4460 * handle enumeration of printers at level 5
4461 ********************************************************************/
4463 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4464 NEW_BUFFER *buffer, uint32 offered,
4465 uint32 *needed, uint32 *returned)
4467 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4471 /********************************************************************
4472 * api_spoolss_enumprinters
4474 * called from api_spoolss_enumprinters (see this to understand)
4475 ********************************************************************/
4477 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4479 uint32 flags = q_u->flags;
4480 UNISTR2 *servername = &q_u->servername;
4481 uint32 level = q_u->level;
4482 NEW_BUFFER *buffer = NULL;
4483 uint32 offered = q_u->offered;
4484 uint32 *needed = &r_u->needed;
4485 uint32 *returned = &r_u->returned;
4489 /* that's an [in out] buffer */
4490 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4491 buffer = r_u->buffer;
4493 DEBUG(4,("_spoolss_enumprinters\n"));
4500 * flags==PRINTER_ENUM_NAME
4501 * if name=="" then enumerates all printers
4502 * if name!="" then enumerate the printer
4503 * flags==PRINTER_ENUM_REMOTE
4504 * name is NULL, enumerate printers
4505 * Level 2: name!="" enumerates printers, name can't be NULL
4506 * Level 3: doesn't exist
4507 * Level 4: does a local registry lookup
4508 * Level 5: same as Level 2
4511 unistr2_to_ascii(name, servername, sizeof(name)-1);
4516 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4518 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4520 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4525 return WERR_UNKNOWN_LEVEL;
4528 /****************************************************************************
4529 ****************************************************************************/
4531 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4533 PRINTER_INFO_0 *printer=NULL;
4535 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4538 construct_printer_info_0(printer, snum);
4540 /* check the required size. */
4541 *needed += spoolss_size_printer_info_0(printer);
4543 if (!alloc_buffer_size(buffer, *needed)) {
4545 return WERR_INSUFFICIENT_BUFFER;
4548 /* fill the buffer with the structures */
4549 smb_io_printer_info_0("", buffer, printer, 0);
4554 if (*needed > offered) {
4555 return WERR_INSUFFICIENT_BUFFER;
4561 /****************************************************************************
4562 ****************************************************************************/
4564 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4566 PRINTER_INFO_1 *printer=NULL;
4568 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4571 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4573 /* check the required size. */
4574 *needed += spoolss_size_printer_info_1(printer);
4576 if (!alloc_buffer_size(buffer, *needed)) {
4578 return WERR_INSUFFICIENT_BUFFER;
4581 /* fill the buffer with the structures */
4582 smb_io_printer_info_1("", buffer, printer, 0);
4587 if (*needed > offered) {
4588 return WERR_INSUFFICIENT_BUFFER;
4594 /****************************************************************************
4595 ****************************************************************************/
4597 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4599 PRINTER_INFO_2 *printer=NULL;
4601 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4604 construct_printer_info_2(printer, snum);
4606 /* check the required size. */
4607 *needed += spoolss_size_printer_info_2(printer);
4609 if (!alloc_buffer_size(buffer, *needed)) {
4610 free_printer_info_2(printer);
4611 return WERR_INSUFFICIENT_BUFFER;
4614 /* fill the buffer with the structures */
4615 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4616 free_printer_info_2(printer);
4621 free_printer_info_2(printer);
4623 if (*needed > offered) {
4624 return WERR_INSUFFICIENT_BUFFER;
4630 /****************************************************************************
4631 ****************************************************************************/
4633 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4635 PRINTER_INFO_3 *printer=NULL;
4637 if (!construct_printer_info_3(&printer, snum))
4640 /* check the required size. */
4641 *needed += spoolss_size_printer_info_3(printer);
4643 if (!alloc_buffer_size(buffer, *needed)) {
4644 free_printer_info_3(printer);
4645 return WERR_INSUFFICIENT_BUFFER;
4648 /* fill the buffer with the structures */
4649 smb_io_printer_info_3("", buffer, printer, 0);
4652 free_printer_info_3(printer);
4654 if (*needed > offered) {
4655 return WERR_INSUFFICIENT_BUFFER;
4661 /****************************************************************************
4662 ****************************************************************************/
4664 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4666 PRINTER_INFO_4 *printer=NULL;
4668 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4671 if (!construct_printer_info_4(printer, snum))
4674 /* check the required size. */
4675 *needed += spoolss_size_printer_info_4(printer);
4677 if (!alloc_buffer_size(buffer, *needed)) {
4678 free_printer_info_4(printer);
4679 return WERR_INSUFFICIENT_BUFFER;
4682 /* fill the buffer with the structures */
4683 smb_io_printer_info_4("", buffer, printer, 0);
4686 free_printer_info_4(printer);
4688 if (*needed > offered) {
4689 return WERR_INSUFFICIENT_BUFFER;
4695 /****************************************************************************
4696 ****************************************************************************/
4698 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4700 PRINTER_INFO_5 *printer=NULL;
4702 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4705 if (!construct_printer_info_5(printer, snum))
4708 /* check the required size. */
4709 *needed += spoolss_size_printer_info_5(printer);
4711 if (!alloc_buffer_size(buffer, *needed)) {
4712 free_printer_info_5(printer);
4713 return WERR_INSUFFICIENT_BUFFER;
4716 /* fill the buffer with the structures */
4717 smb_io_printer_info_5("", buffer, printer, 0);
4720 free_printer_info_5(printer);
4722 if (*needed > offered) {
4723 return WERR_INSUFFICIENT_BUFFER;
4729 static WERROR getprinter_level_7(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4731 PRINTER_INFO_7 *printer=NULL;
4733 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4736 if (!construct_printer_info_7(printer, snum))
4739 /* check the required size. */
4740 *needed += spoolss_size_printer_info_7(printer);
4742 if (!alloc_buffer_size(buffer, *needed)) {
4743 free_printer_info_7(printer);
4744 return WERR_INSUFFICIENT_BUFFER;
4747 /* fill the buffer with the structures */
4748 smb_io_printer_info_7("", buffer, printer, 0);
4751 free_printer_info_7(printer);
4753 if (*needed > offered) {
4754 return WERR_INSUFFICIENT_BUFFER;
4760 /****************************************************************************
4761 ****************************************************************************/
4763 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4765 POLICY_HND *handle = &q_u->handle;
4766 uint32 level = q_u->level;
4767 NEW_BUFFER *buffer = NULL;
4768 uint32 offered = q_u->offered;
4769 uint32 *needed = &r_u->needed;
4773 /* that's an [in out] buffer */
4774 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4775 buffer = r_u->buffer;
4779 if (!get_printer_snum(p, handle, &snum))
4784 return getprinter_level_0(snum, buffer, offered, needed);
4786 return getprinter_level_1(snum, buffer, offered, needed);
4788 return getprinter_level_2(snum, buffer, offered, needed);
4790 return getprinter_level_3(snum, buffer, offered, needed);
4792 return getprinter_level_4(snum, buffer, offered, needed);
4794 return getprinter_level_5(snum, buffer, offered, needed);
4796 return getprinter_level_7(snum, buffer, offered, needed);
4798 return WERR_UNKNOWN_LEVEL;
4801 /********************************************************************
4802 * fill a DRIVER_INFO_1 struct
4803 ********************************************************************/
4805 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4807 init_unistr( &info->name, driver.info_3->name);
4810 /********************************************************************
4811 * construct_printer_driver_info_1
4812 ********************************************************************/
4814 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4816 NT_PRINTER_INFO_LEVEL *printer = NULL;
4817 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4819 ZERO_STRUCT(driver);
4821 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4822 return WERR_INVALID_PRINTER_NAME;
4824 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4825 return WERR_UNKNOWN_PRINTER_DRIVER;
4827 fill_printer_driver_info_1(info, driver, servername, architecture);
4829 free_a_printer(&printer,2);
4834 /********************************************************************
4835 * construct_printer_driver_info_2
4836 * fill a printer_info_2 struct
4837 ********************************************************************/
4839 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4843 info->version=driver.info_3->cversion;
4845 init_unistr( &info->name, driver.info_3->name );
4846 init_unistr( &info->architecture, driver.info_3->environment );
4849 if (strlen(driver.info_3->driverpath)) {
4850 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4851 init_unistr( &info->driverpath, temp );
4853 init_unistr( &info->driverpath, "" );
4855 if (strlen(driver.info_3->datafile)) {
4856 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4857 init_unistr( &info->datafile, temp );
4859 init_unistr( &info->datafile, "" );
4861 if (strlen(driver.info_3->configfile)) {
4862 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4863 init_unistr( &info->configfile, temp );
4865 init_unistr( &info->configfile, "" );
4868 /********************************************************************
4869 * construct_printer_driver_info_2
4870 * fill a printer_info_2 struct
4871 ********************************************************************/
4873 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4875 NT_PRINTER_INFO_LEVEL *printer = NULL;
4876 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4878 ZERO_STRUCT(printer);
4879 ZERO_STRUCT(driver);
4881 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4882 return WERR_INVALID_PRINTER_NAME;
4884 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4885 return WERR_UNKNOWN_PRINTER_DRIVER;
4887 fill_printer_driver_info_2(info, driver, servername);
4889 free_a_printer(&printer,2);
4894 /********************************************************************
4895 * copy a strings array and convert to UNICODE
4897 * convert an array of ascii string to a UNICODE string
4898 ********************************************************************/
4900 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4908 DEBUG(6,("init_unistr_array\n"));
4919 v = ""; /* hack to handle null lists */
4922 /* hack to allow this to be used in places other than when generating
4923 the list of dependent files */
4926 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4930 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4932 /* add one extra unit16 for the second terminating NULL */
4934 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4935 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4943 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4948 /* special case for ""; we need to add both NULL's here */
4950 (*uni_array)[j++]=0x0000;
4951 (*uni_array)[j]=0x0000;
4954 DEBUGADD(6,("last one:done\n"));
4956 /* return size of array in uint16's */
4961 /********************************************************************
4962 * construct_printer_info_3
4963 * fill a printer_info_3 struct
4964 ********************************************************************/
4966 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4972 info->version=driver.info_3->cversion;
4974 init_unistr( &info->name, driver.info_3->name );
4975 init_unistr( &info->architecture, driver.info_3->environment );
4977 if (strlen(driver.info_3->driverpath)) {
4978 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4979 init_unistr( &info->driverpath, temp );
4981 init_unistr( &info->driverpath, "" );
4983 if (strlen(driver.info_3->datafile)) {
4984 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4985 init_unistr( &info->datafile, temp );
4987 init_unistr( &info->datafile, "" );
4989 if (strlen(driver.info_3->configfile)) {
4990 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4991 init_unistr( &info->configfile, temp );
4993 init_unistr( &info->configfile, "" );
4995 if (strlen(driver.info_3->helpfile)) {
4996 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4997 init_unistr( &info->helpfile, temp );
4999 init_unistr( &info->helpfile, "" );
5001 init_unistr( &info->monitorname, driver.info_3->monitorname );
5002 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5004 info->dependentfiles=NULL;
5005 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5008 /********************************************************************
5009 * construct_printer_info_3
5010 * fill a printer_info_3 struct
5011 ********************************************************************/
5013 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5015 NT_PRINTER_INFO_LEVEL *printer = NULL;
5016 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5018 ZERO_STRUCT(driver);
5020 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5021 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5022 if (!W_ERROR_IS_OK(status))
5023 return WERR_INVALID_PRINTER_NAME;
5025 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5026 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5031 * I put this code in during testing. Helpful when commenting out the
5032 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5033 * as win2k always queries the driver using an infor level of 6.
5034 * I've left it in (but ifdef'd out) because I'll probably
5035 * use it in experimentation again in the future. --jerry 22/01/2002
5038 if (!W_ERROR_IS_OK(status)) {
5040 * Is this a W2k client ?
5043 /* Yes - try again with a WinNT driver. */
5045 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5046 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5050 if (!W_ERROR_IS_OK(status)) {
5051 free_a_printer(&printer,2);
5052 return WERR_UNKNOWN_PRINTER_DRIVER;
5060 fill_printer_driver_info_3(info, driver, servername);
5062 free_a_printer(&printer,2);
5067 /********************************************************************
5068 * construct_printer_info_6
5069 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5070 ********************************************************************/
5072 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5078 memset(&nullstr, '\0', sizeof(fstring));
5080 info->version=driver.info_3->cversion;
5082 init_unistr( &info->name, driver.info_3->name );
5083 init_unistr( &info->architecture, driver.info_3->environment );
5085 if (strlen(driver.info_3->driverpath)) {
5086 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5087 init_unistr( &info->driverpath, temp );
5089 init_unistr( &info->driverpath, "" );
5091 if (strlen(driver.info_3->datafile)) {
5092 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5093 init_unistr( &info->datafile, temp );
5095 init_unistr( &info->datafile, "" );
5097 if (strlen(driver.info_3->configfile)) {
5098 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5099 init_unistr( &info->configfile, temp );
5101 init_unistr( &info->configfile, "" );
5103 if (strlen(driver.info_3->helpfile)) {
5104 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5105 init_unistr( &info->helpfile, temp );
5107 init_unistr( &info->helpfile, "" );
5109 init_unistr( &info->monitorname, driver.info_3->monitorname );
5110 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5112 info->dependentfiles = NULL;
5113 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5115 info->previousdrivernames=NULL;
5116 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5118 info->driver_date.low=0;
5119 info->driver_date.high=0;
5122 info->driver_version_low=0;
5123 info->driver_version_high=0;
5125 init_unistr( &info->mfgname, "");
5126 init_unistr( &info->oem_url, "");
5127 init_unistr( &info->hardware_id, "");
5128 init_unistr( &info->provider, "");
5131 /********************************************************************
5132 * construct_printer_info_6
5133 * fill a printer_info_6 struct
5134 ********************************************************************/
5136 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5137 fstring servername, fstring architecture, uint32 version)
5139 NT_PRINTER_INFO_LEVEL *printer = NULL;
5140 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5143 ZERO_STRUCT(driver);
5145 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5147 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5149 if (!W_ERROR_IS_OK(status))
5150 return WERR_INVALID_PRINTER_NAME;
5152 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5154 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5156 if (!W_ERROR_IS_OK(status))
5159 * Is this a W2k client ?
5163 free_a_printer(&printer,2);
5164 return WERR_UNKNOWN_PRINTER_DRIVER;
5167 /* Yes - try again with a WinNT driver. */
5169 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5170 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5171 if (!W_ERROR_IS_OK(status)) {
5172 free_a_printer(&printer,2);
5173 return WERR_UNKNOWN_PRINTER_DRIVER;
5177 fill_printer_driver_info_6(info, driver, servername);
5179 free_a_printer(&printer,2);
5180 free_a_printer_driver(driver, 3);
5185 /****************************************************************************
5186 ****************************************************************************/
5188 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5190 SAFE_FREE(info->dependentfiles);
5193 /****************************************************************************
5194 ****************************************************************************/
5196 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5198 SAFE_FREE(info->dependentfiles);
5202 /****************************************************************************
5203 ****************************************************************************/
5205 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5207 DRIVER_INFO_1 *info=NULL;
5210 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5213 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5214 if (!W_ERROR_IS_OK(status)) {
5219 /* check the required size. */
5220 *needed += spoolss_size_printer_driver_info_1(info);
5222 if (!alloc_buffer_size(buffer, *needed)) {
5224 return WERR_INSUFFICIENT_BUFFER;
5227 /* fill the buffer with the structures */
5228 smb_io_printer_driver_info_1("", buffer, info, 0);
5233 if (*needed > offered)
5234 return WERR_INSUFFICIENT_BUFFER;
5239 /****************************************************************************
5240 ****************************************************************************/
5242 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5244 DRIVER_INFO_2 *info=NULL;
5247 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5250 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5251 if (!W_ERROR_IS_OK(status)) {
5256 /* check the required size. */
5257 *needed += spoolss_size_printer_driver_info_2(info);
5259 if (!alloc_buffer_size(buffer, *needed)) {
5261 return WERR_INSUFFICIENT_BUFFER;
5264 /* fill the buffer with the structures */
5265 smb_io_printer_driver_info_2("", buffer, info, 0);
5270 if (*needed > offered)
5271 return WERR_INSUFFICIENT_BUFFER;
5276 /****************************************************************************
5277 ****************************************************************************/
5279 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5286 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5287 if (!W_ERROR_IS_OK(status)) {
5291 /* check the required size. */
5292 *needed += spoolss_size_printer_driver_info_3(&info);
5294 if (!alloc_buffer_size(buffer, *needed)) {
5295 free_printer_driver_info_3(&info);
5296 return WERR_INSUFFICIENT_BUFFER;
5299 /* fill the buffer with the structures */
5300 smb_io_printer_driver_info_3("", buffer, &info, 0);
5302 free_printer_driver_info_3(&info);
5304 if (*needed > offered)
5305 return WERR_INSUFFICIENT_BUFFER;
5310 /****************************************************************************
5311 ****************************************************************************/
5313 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5320 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5321 if (!W_ERROR_IS_OK(status)) {
5325 /* check the required size. */
5326 *needed += spoolss_size_printer_driver_info_6(&info);
5328 if (!alloc_buffer_size(buffer, *needed)) {
5329 free_printer_driver_info_6(&info);
5330 return WERR_INSUFFICIENT_BUFFER;
5333 /* fill the buffer with the structures */
5334 smb_io_printer_driver_info_6("", buffer, &info, 0);
5336 free_printer_driver_info_6(&info);
5338 if (*needed > offered)
5339 return WERR_INSUFFICIENT_BUFFER;
5344 /****************************************************************************
5345 ****************************************************************************/
5347 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5349 POLICY_HND *handle = &q_u->handle;
5350 UNISTR2 *uni_arch = &q_u->architecture;
5351 uint32 level = q_u->level;
5352 uint32 clientmajorversion = q_u->clientmajorversion;
5353 NEW_BUFFER *buffer = NULL;
5354 uint32 offered = q_u->offered;
5355 uint32 *needed = &r_u->needed;
5356 uint32 *servermajorversion = &r_u->servermajorversion;
5357 uint32 *serverminorversion = &r_u->serverminorversion;
5360 fstring architecture;
5363 /* that's an [in out] buffer */
5364 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5365 buffer = r_u->buffer;
5367 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5370 *servermajorversion = 0;
5371 *serverminorversion = 0;
5373 pstrcpy(servername, get_called_name());
5374 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5376 if (!get_printer_snum(p, handle, &snum))
5381 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5383 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5385 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5387 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5390 return WERR_UNKNOWN_LEVEL;
5393 /****************************************************************************
5394 ****************************************************************************/
5396 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5398 POLICY_HND *handle = &q_u->handle;
5400 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5403 DEBUG(3,("Error in startpageprinter printer handle\n"));
5407 Printer->page_started=True;
5411 /****************************************************************************
5412 ****************************************************************************/
5414 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5416 POLICY_HND *handle = &q_u->handle;
5419 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5422 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5426 if (!get_printer_snum(p, handle, &snum))
5429 Printer->page_started=False;
5430 print_job_endpage(snum, Printer->jobid);
5435 /********************************************************************
5436 * api_spoolss_getprinter
5437 * called from the spoolss dispatcher
5439 ********************************************************************/
5441 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5443 POLICY_HND *handle = &q_u->handle;
5444 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5445 uint32 *jobid = &r_u->jobid;
5447 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5451 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5452 struct current_user user;
5455 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5459 get_current_user(&user, p);
5462 * a nice thing with NT is it doesn't listen to what you tell it.
5463 * when asked to send _only_ RAW datas, it tries to send datas
5466 * So I add checks like in NT Server ...
5469 if (info_1->p_datatype != 0) {
5470 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5471 if (strcmp(datatype, "RAW") != 0) {
5473 return WERR_INVALID_DATATYPE;
5477 /* get the share number of the printer */
5478 if (!get_printer_snum(p, handle, &snum)) {
5482 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5484 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5486 /* An error occured in print_job_start() so return an appropriate
5489 if (Printer->jobid == -1) {
5490 return map_werror_from_unix(errno);
5493 Printer->document_started=True;
5494 (*jobid) = Printer->jobid;
5499 /********************************************************************
5500 * api_spoolss_getprinter
5501 * called from the spoolss dispatcher
5503 ********************************************************************/
5505 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5507 POLICY_HND *handle = &q_u->handle;
5509 return _spoolss_enddocprinter_internal(p, handle);
5512 /****************************************************************************
5513 ****************************************************************************/
5515 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5517 POLICY_HND *handle = &q_u->handle;
5518 uint32 buffer_size = q_u->buffer_size;
5519 uint8 *buffer = q_u->buffer;
5520 uint32 *buffer_written = &q_u->buffer_size2;
5522 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5525 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5526 r_u->buffer_written = q_u->buffer_size2;
5530 if (!get_printer_snum(p, handle, &snum))
5533 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5534 if (*buffer_written == -1) {
5535 r_u->buffer_written = 0;
5536 if (errno == ENOSPC)
5537 return WERR_NO_SPOOL_SPACE;
5539 return WERR_ACCESS_DENIED;
5542 r_u->buffer_written = q_u->buffer_size2;
5547 /********************************************************************
5548 * api_spoolss_getprinter
5549 * called from the spoolss dispatcher
5551 ********************************************************************/
5553 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5556 struct current_user user;
5558 WERROR errcode = WERR_BADFUNC;
5559 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5561 get_current_user(&user, p);
5564 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5568 if (!get_printer_snum(p, handle, &snum))
5572 case PRINTER_CONTROL_PAUSE:
5573 if (print_queue_pause(&user, snum, &errcode)) {
5577 case PRINTER_CONTROL_RESUME:
5578 case PRINTER_CONTROL_UNPAUSE:
5579 if (print_queue_resume(&user, snum, &errcode)) {
5583 case PRINTER_CONTROL_PURGE:
5584 if (print_queue_purge(&user, snum, &errcode)) {
5589 return WERR_UNKNOWN_LEVEL;
5595 /********************************************************************
5596 * api_spoolss_abortprinter
5597 * From MSDN: "Deletes printer's spool file if printer is configured
5599 ********************************************************************/
5601 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5603 POLICY_HND *handle = &q_u->handle;
5604 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5606 struct current_user user;
5607 WERROR errcode = WERR_OK;
5610 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5614 if (!get_printer_snum(p, handle, &snum))
5617 get_current_user( &user, p );
5619 print_job_delete( &user, snum, Printer->jobid, &errcode );
5624 /********************************************************************
5625 * called by spoolss_api_setprinter
5626 * when updating a printer description
5627 ********************************************************************/
5629 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5630 const SPOOL_PRINTER_INFO_LEVEL *info,
5631 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5633 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5634 struct current_user user;
5638 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5640 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5641 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5642 OUR_HANDLE(handle)));
5644 result = WERR_BADFID;
5648 /* NT seems to like setting the security descriptor even though
5649 nothing may have actually changed. This causes annoying
5650 dialog boxes when the user doesn't have permission to change
5651 the security descriptor. */
5653 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5655 if (DEBUGLEVEL >= 10) {
5659 the_acl = old_secdesc_ctr->sec->dacl;
5660 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5661 PRINTERNAME(snum), the_acl->num_aces));
5663 for (i = 0; i < the_acl->num_aces; i++) {
5666 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5668 DEBUG(10, ("%s 0x%08x\n", sid_str,
5669 the_acl->ace[i].info.mask));
5672 the_acl = secdesc_ctr->sec->dacl;
5675 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5676 PRINTERNAME(snum), the_acl->num_aces));
5678 for (i = 0; i < the_acl->num_aces; i++) {
5681 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5683 DEBUG(10, ("%s 0x%08x\n", sid_str,
5684 the_acl->ace[i].info.mask));
5687 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5691 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5693 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5698 /* Work out which user is performing the operation */
5700 get_current_user(&user, p);
5702 /* Check the user has permissions to change the security
5703 descriptor. By experimentation with two NT machines, the user
5704 requires Full Access to the printer to change security
5707 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5708 result = WERR_ACCESS_DENIED;
5712 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5719 /********************************************************************
5720 Do Samba sanity checks on a printer info struct.
5721 this has changed purpose: it now "canonicalises" printer
5722 info from a client rather than just checking it is correct
5723 ********************************************************************/
5725 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5727 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5728 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5730 /* we force some elements to "correct" values */
5731 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5732 fstrcpy(info->sharename, lp_servicename(snum));
5733 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5734 get_called_name(), info->sharename);
5735 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5740 /****************************************************************************
5741 ****************************************************************************/
5743 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5745 extern userdom_struct current_user_info;
5746 char *cmd = lp_addprinter_cmd();
5752 fstring remote_machine = "%m";
5754 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5756 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5757 cmd, printer->info_2->printername, printer->info_2->sharename,
5758 printer->info_2->portname, printer->info_2->drivername,
5759 printer->info_2->location, printer->info_2->comment, remote_machine);
5761 DEBUG(10,("Running [%s]\n", command));
5762 ret = smbrun(command, &fd);
5763 DEBUGADD(10,("returned [%d]\n", ret));
5772 /* Get lines and convert them back to dos-codepage */
5773 qlines = fd_lines_load(fd, &numlines);
5774 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5778 /* Set the portname to what the script says the portname should be. */
5779 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5780 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5782 /* Send SIGHUP to process group... is there a better way? */
5785 /* reload our services immediately */
5786 reload_services( False );
5789 file_lines_free(qlines);
5793 /********************************************************************
5794 * Called by spoolss_api_setprinter
5795 * when updating a printer description.
5796 ********************************************************************/
5798 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5799 const SPOOL_PRINTER_INFO_LEVEL *info,
5800 DEVICEMODE *devmode)
5803 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5804 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5807 DEBUG(8,("update_printer\n"));
5812 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5813 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5814 result = WERR_UNKNOWN_LEVEL;
5819 result = WERR_BADFID;
5823 if (!get_printer_snum(p, handle, &snum)) {
5824 result = WERR_BADFID;
5828 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5829 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5830 result = WERR_BADFID;
5834 DEBUGADD(8,("Converting info_2 struct\n"));
5837 * convert_printer_info converts the incoming
5838 * info from the client and overwrites the info
5839 * just read from the tdb in the pointer 'printer'.
5842 if (!convert_printer_info(info, printer, level)) {
5843 result = WERR_NOMEM;
5848 /* we have a valid devmode
5849 convert it and link it*/
5851 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5852 if (!convert_devicemode(printer->info_2->printername, devmode,
5853 &printer->info_2->devmode)) {
5854 result = WERR_NOMEM;
5859 * make sure we actually reload the services after
5860 * this as smb.conf could have a new section in it
5861 * .... shouldn't .... but could
5863 reload_services(False);
5866 /* Do sanity check on the requested changes for Samba */
5868 if (!check_printer_ok(printer->info_2, snum)) {
5869 result = WERR_INVALID_PARAM;
5873 /* Check calling user has permission to update printer description */
5875 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5876 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5877 result = WERR_ACCESS_DENIED;
5881 /* Call addprinter hook */
5882 /* Check changes to see if this is really needed */
5884 if ( *lp_addprinter_cmd()
5885 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5886 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5887 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5888 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5890 if ( !add_printer_hook(printer) ) {
5891 result = WERR_ACCESS_DENIED;
5897 * When a *new* driver is bound to a printer, the drivername is used to
5898 * lookup previously saved driver initialization info, which is then
5899 * bound to the printer, simulating what happens in the Windows arch.
5901 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5903 if (!set_driver_init(printer, 2))
5905 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5906 printer->info_2->drivername));
5909 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5910 printer->info_2->drivername));
5912 notify_printer_driver(snum, printer->info_2->drivername);
5915 /* Update printer info */
5916 result = mod_a_printer(*printer, 2);
5918 /* flag which changes actually occured. This is a small subset of
5919 all the possible changes */
5921 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5922 notify_printer_comment(snum, printer->info_2->comment);
5924 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5925 notify_printer_sharename(snum, printer->info_2->sharename);
5927 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5928 notify_printer_port(snum, printer->info_2->portname);
5930 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5931 notify_printer_location(snum, printer->info_2->location);
5934 free_a_printer(&printer, 2);
5935 free_a_printer(&old_printer, 2);
5941 /****************************************************************************
5942 ****************************************************************************/
5943 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
5944 const SPOOL_PRINTER_INFO_LEVEL *info)
5947 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
5949 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5952 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5959 if (!get_printer_snum(p, handle, &snum))
5962 nt_printer_publish(snum, info7->action);
5966 return WERR_UNKNOWN_LEVEL;
5969 /****************************************************************************
5970 ****************************************************************************/
5972 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5974 POLICY_HND *handle = &q_u->handle;
5975 uint32 level = q_u->level;
5976 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5977 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5978 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5979 uint32 command = q_u->command;
5981 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5984 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5988 /* check the level */
5991 return control_printer(handle, command, p);
5993 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5995 return update_printer_sec(handle, level, info, p,
5998 return publish_or_unpublish_printer(p, handle, info);
6000 return WERR_UNKNOWN_LEVEL;
6004 /****************************************************************************
6005 ****************************************************************************/
6007 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6009 POLICY_HND *handle = &q_u->handle;
6010 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6013 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6017 if (Printer->notify.client_connected==True) {
6020 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6022 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6023 !get_printer_snum(p, handle, &snum) )
6026 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6029 Printer->notify.flags=0;
6030 Printer->notify.options=0;
6031 Printer->notify.localmachine[0]='\0';
6032 Printer->notify.printerlocal=0;
6033 if (Printer->notify.option)
6034 free_spool_notify_option(&Printer->notify.option);
6035 Printer->notify.client_connected=False;
6040 /****************************************************************************
6041 ****************************************************************************/
6043 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6045 /* that's an [in out] buffer (despite appearences to the contrary) */
6046 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6049 return WERR_INVALID_PARAM; /* this is what a NT server
6050 returns for AddJob. AddJob
6051 must fail on non-local
6055 /****************************************************************************
6056 ****************************************************************************/
6058 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6059 int position, int snum)
6065 t=gmtime(&queue->time);
6066 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6068 job_info->jobid=queue->job;
6069 init_unistr(&job_info->printername, lp_servicename(snum));
6070 init_unistr(&job_info->machinename, temp_name);
6071 init_unistr(&job_info->username, queue->fs_user);
6072 init_unistr(&job_info->document, queue->fs_file);
6073 init_unistr(&job_info->datatype, "RAW");
6074 init_unistr(&job_info->text_status, "");
6075 job_info->status=nt_printj_status(queue->status);
6076 job_info->priority=queue->priority;
6077 job_info->position=position;
6078 job_info->totalpages=queue->page_count;
6079 job_info->pagesprinted=0;
6081 make_systemtime(&job_info->submitted, t);
6084 /****************************************************************************
6085 ****************************************************************************/
6087 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6088 int position, int snum,
6089 NT_PRINTER_INFO_LEVEL *ntprinter,
6090 DEVICEMODE *devmode)
6096 t=gmtime(&queue->time);
6097 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6099 job_info->jobid=queue->job;
6101 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
6103 init_unistr(&job_info->printername, chaine);
6105 init_unistr(&job_info->machinename, temp_name);
6106 init_unistr(&job_info->username, queue->fs_user);
6107 init_unistr(&job_info->document, queue->fs_file);
6108 init_unistr(&job_info->notifyname, queue->fs_user);
6109 init_unistr(&job_info->datatype, "RAW");
6110 init_unistr(&job_info->printprocessor, "winprint");
6111 init_unistr(&job_info->parameters, "");
6112 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6113 init_unistr(&job_info->text_status, "");
6115 /* and here the security descriptor */
6117 job_info->status=nt_printj_status(queue->status);
6118 job_info->priority=queue->priority;
6119 job_info->position=position;
6120 job_info->starttime=0;
6121 job_info->untiltime=0;
6122 job_info->totalpages=queue->page_count;
6123 job_info->size=queue->size;
6124 make_systemtime(&(job_info->submitted), t);
6125 job_info->timeelapsed=0;
6126 job_info->pagesprinted=0;
6128 job_info->devmode = devmode;
6133 /****************************************************************************
6134 Enumjobs at level 1.
6135 ****************************************************************************/
6137 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6138 NEW_BUFFER *buffer, uint32 offered,
6139 uint32 *needed, uint32 *returned)
6144 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6151 for (i=0; i<*returned; i++)
6152 fill_job_info_1(&info[i], &queue[i], i, snum);
6156 /* check the required size. */
6157 for (i=0; i<*returned; i++)
6158 (*needed) += spoolss_size_job_info_1(&info[i]);
6160 if (!alloc_buffer_size(buffer, *needed)) {
6162 return WERR_INSUFFICIENT_BUFFER;
6165 /* fill the buffer with the structures */
6166 for (i=0; i<*returned; i++)
6167 smb_io_job_info_1("", buffer, &info[i], 0);
6172 if (*needed > offered) {
6174 return WERR_INSUFFICIENT_BUFFER;
6180 /****************************************************************************
6181 Enumjobs at level 2.
6182 ****************************************************************************/
6184 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6185 NEW_BUFFER *buffer, uint32 offered,
6186 uint32 *needed, uint32 *returned)
6188 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6189 JOB_INFO_2 *info = NULL;
6192 DEVICEMODE *devmode = NULL;
6194 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6197 result = WERR_NOMEM;
6201 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6202 if (!W_ERROR_IS_OK(result)) {
6207 /* this should not be a failure condition if the devmode is NULL */
6209 devmode = construct_dev_mode(snum);
6211 for (i=0; i<*returned; i++)
6212 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6215 free_a_printer(&ntprinter, 2);
6218 /* check the required size. */
6219 for (i=0; i<*returned; i++)
6220 (*needed) += spoolss_size_job_info_2(&info[i]);
6222 if (*needed > offered) {
6224 result = WERR_INSUFFICIENT_BUFFER;
6228 if (!alloc_buffer_size(buffer, *needed)) {
6230 result = WERR_INSUFFICIENT_BUFFER;
6234 /* fill the buffer with the structures */
6235 for (i=0; i<*returned; i++)
6236 smb_io_job_info_2("", buffer, &info[i], 0);
6241 free_a_printer(&ntprinter, 2);
6242 free_devmode(devmode);
6250 /****************************************************************************
6252 ****************************************************************************/
6254 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6256 POLICY_HND *handle = &q_u->handle;
6257 uint32 level = q_u->level;
6258 NEW_BUFFER *buffer = NULL;
6259 uint32 offered = q_u->offered;
6260 uint32 *needed = &r_u->needed;
6261 uint32 *returned = &r_u->returned;
6264 print_status_struct prt_status;
6265 print_queue_struct *queue=NULL;
6267 /* that's an [in out] buffer */
6268 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6269 buffer = r_u->buffer;
6271 DEBUG(4,("_spoolss_enumjobs\n"));
6276 if (!get_printer_snum(p, handle, &snum))
6279 *returned = print_queue_status(snum, &queue, &prt_status);
6280 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6282 if (*returned == 0) {
6289 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6291 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6295 return WERR_UNKNOWN_LEVEL;
6299 /****************************************************************************
6300 ****************************************************************************/
6302 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6307 /****************************************************************************
6308 ****************************************************************************/
6310 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6312 POLICY_HND *handle = &q_u->handle;
6313 uint32 jobid = q_u->jobid;
6314 uint32 command = q_u->command;
6316 struct current_user user;
6318 WERROR errcode = WERR_BADFUNC;
6320 if (!get_printer_snum(p, handle, &snum)) {
6324 if (!print_job_exists(snum, jobid)) {
6325 return WERR_INVALID_PRINTER_NAME;
6328 get_current_user(&user, p);
6331 case JOB_CONTROL_CANCEL:
6332 case JOB_CONTROL_DELETE:
6333 if (print_job_delete(&user, snum, jobid, &errcode)) {
6337 case JOB_CONTROL_PAUSE:
6338 if (print_job_pause(&user, snum, jobid, &errcode)) {
6342 case JOB_CONTROL_RESTART:
6343 case JOB_CONTROL_RESUME:
6344 if (print_job_resume(&user, snum, jobid, &errcode)) {
6349 return WERR_UNKNOWN_LEVEL;
6355 /****************************************************************************
6356 Enumerates all printer drivers at level 1.
6357 ****************************************************************************/
6359 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6364 fstring *list = NULL;
6366 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6367 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6371 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6373 ndrivers=get_ntdrivers(&list, architecture, version);
6374 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6380 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6381 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6382 SAFE_FREE(driver_info_1);
6386 else driver_info_1 = tdi1;
6389 for (i=0; i<ndrivers; i++) {
6391 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6392 ZERO_STRUCT(driver);
6393 status = get_a_printer_driver(&driver, 3, list[i],
6394 architecture, version);
6395 if (!W_ERROR_IS_OK(status)) {
6399 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6400 free_a_printer_driver(driver, 3);
6403 *returned+=ndrivers;
6407 /* check the required size. */
6408 for (i=0; i<*returned; i++) {
6409 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6410 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6413 if (!alloc_buffer_size(buffer, *needed)) {
6414 SAFE_FREE(driver_info_1);
6415 return WERR_INSUFFICIENT_BUFFER;
6418 /* fill the buffer with the driver structures */
6419 for (i=0; i<*returned; i++) {
6420 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6421 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6424 SAFE_FREE(driver_info_1);
6426 if (*needed > offered) {
6428 return WERR_INSUFFICIENT_BUFFER;
6434 /****************************************************************************
6435 Enumerates all printer drivers at level 2.
6436 ****************************************************************************/
6438 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6443 fstring *list = NULL;
6445 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6446 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6450 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6452 ndrivers=get_ntdrivers(&list, architecture, version);
6453 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6459 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6460 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6461 SAFE_FREE(driver_info_2);
6465 else driver_info_2 = tdi2;
6468 for (i=0; i<ndrivers; i++) {
6471 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6472 ZERO_STRUCT(driver);
6473 status = get_a_printer_driver(&driver, 3, list[i],
6474 architecture, version);
6475 if (!W_ERROR_IS_OK(status)) {
6479 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6480 free_a_printer_driver(driver, 3);
6483 *returned+=ndrivers;
6487 /* check the required size. */
6488 for (i=0; i<*returned; i++) {
6489 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6490 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6493 if (!alloc_buffer_size(buffer, *needed)) {
6494 SAFE_FREE(driver_info_2);
6495 return WERR_INSUFFICIENT_BUFFER;
6498 /* fill the buffer with the form structures */
6499 for (i=0; i<*returned; i++) {
6500 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6501 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6504 SAFE_FREE(driver_info_2);
6506 if (*needed > offered) {
6508 return WERR_INSUFFICIENT_BUFFER;
6514 /****************************************************************************
6515 Enumerates all printer drivers at level 3.
6516 ****************************************************************************/
6518 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6523 fstring *list = NULL;
6525 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6526 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6530 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6532 ndrivers=get_ntdrivers(&list, architecture, version);
6533 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6539 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6540 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6541 SAFE_FREE(driver_info_3);
6545 else driver_info_3 = tdi3;
6548 for (i=0; i<ndrivers; i++) {
6551 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6552 ZERO_STRUCT(driver);
6553 status = get_a_printer_driver(&driver, 3, list[i],
6554 architecture, version);
6555 if (!W_ERROR_IS_OK(status)) {
6559 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6560 free_a_printer_driver(driver, 3);
6563 *returned+=ndrivers;
6567 /* check the required size. */
6568 for (i=0; i<*returned; i++) {
6569 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6570 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6573 if (!alloc_buffer_size(buffer, *needed)) {
6574 SAFE_FREE(driver_info_3);
6575 return WERR_INSUFFICIENT_BUFFER;
6578 /* fill the buffer with the driver structures */
6579 for (i=0; i<*returned; i++) {
6580 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6581 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6584 for (i=0; i<*returned; i++)
6585 SAFE_FREE(driver_info_3[i].dependentfiles);
6587 SAFE_FREE(driver_info_3);
6589 if (*needed > offered) {
6591 return WERR_INSUFFICIENT_BUFFER;
6597 /****************************************************************************
6598 Enumerates all printer drivers.
6599 ****************************************************************************/
6601 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6603 UNISTR2 *environment = &q_u->environment;
6604 uint32 level = q_u->level;
6605 NEW_BUFFER *buffer = NULL;
6606 uint32 offered = q_u->offered;
6607 uint32 *needed = &r_u->needed;
6608 uint32 *returned = &r_u->returned;
6610 fstring *list = NULL;
6612 fstring architecture;
6614 /* that's an [in out] buffer */
6615 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6616 buffer = r_u->buffer;
6618 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6619 fstrcpy(servername, get_called_name());
6623 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6627 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6629 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6631 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6635 return WERR_UNKNOWN_LEVEL;
6639 /****************************************************************************
6640 ****************************************************************************/
6642 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6644 form->flag=list->flag;
6645 init_unistr(&form->name, list->name);
6646 form->width=list->width;
6647 form->length=list->length;
6648 form->left=list->left;
6649 form->top=list->top;
6650 form->right=list->right;
6651 form->bottom=list->bottom;
6654 /****************************************************************************
6655 ****************************************************************************/
6657 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6659 uint32 level = q_u->level;
6660 NEW_BUFFER *buffer = NULL;
6661 uint32 offered = q_u->offered;
6662 uint32 *needed = &r_u->needed;
6663 uint32 *numofforms = &r_u->numofforms;
6664 uint32 numbuiltinforms;
6666 nt_forms_struct *list=NULL;
6667 nt_forms_struct *builtinlist=NULL;
6672 /* that's an [in out] buffer */
6673 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6674 buffer = r_u->buffer;
6676 DEBUG(4,("_spoolss_enumforms\n"));
6677 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6678 DEBUGADD(5,("Info level [%d]\n", level));
6680 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6681 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6682 *numofforms = get_ntforms(&list);
6683 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6684 *numofforms += numbuiltinforms;
6686 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6690 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6695 /* construct the list of form structures */
6696 for (i=0; i<numbuiltinforms; i++) {
6697 DEBUGADD(6,("Filling form number [%d]\n",i));
6698 fill_form_1(&forms_1[i], &builtinlist[i]);
6701 SAFE_FREE(builtinlist);
6703 for (; i<*numofforms; i++) {
6704 DEBUGADD(6,("Filling form number [%d]\n",i));
6705 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6710 /* check the required size. */
6711 for (i=0; i<numbuiltinforms; i++) {
6712 DEBUGADD(6,("adding form [%d]'s size\n",i));
6713 buffer_size += spoolss_size_form_1(&forms_1[i]);
6715 for (; i<*numofforms; i++) {
6716 DEBUGADD(6,("adding form [%d]'s size\n",i));
6717 buffer_size += spoolss_size_form_1(&forms_1[i]);
6720 *needed=buffer_size;
6722 if (!alloc_buffer_size(buffer, buffer_size)){
6724 return WERR_INSUFFICIENT_BUFFER;
6727 /* fill the buffer with the form structures */
6728 for (i=0; i<numbuiltinforms; i++) {
6729 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6730 smb_io_form_1("", buffer, &forms_1[i], 0);
6732 for (; i<*numofforms; i++) {
6733 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6734 smb_io_form_1("", buffer, &forms_1[i], 0);
6739 if (*needed > offered) {
6741 return WERR_INSUFFICIENT_BUFFER;
6748 SAFE_FREE(builtinlist);
6749 return WERR_UNKNOWN_LEVEL;
6754 /****************************************************************************
6755 ****************************************************************************/
6757 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6759 uint32 level = q_u->level;
6760 UNISTR2 *uni_formname = &q_u->formname;
6761 NEW_BUFFER *buffer = NULL;
6762 uint32 offered = q_u->offered;
6763 uint32 *needed = &r_u->needed;
6765 nt_forms_struct *list=NULL;
6766 nt_forms_struct builtin_form;
6771 int numofforms=0, i=0;
6773 /* that's an [in out] buffer */
6774 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6775 buffer = r_u->buffer;
6777 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6779 DEBUG(4,("_spoolss_getform\n"));
6780 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6781 DEBUGADD(5,("Info level [%d]\n", level));
6783 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6784 if (!foundBuiltin) {
6785 numofforms = get_ntforms(&list);
6786 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6788 if (numofforms == 0)
6795 fill_form_1(&form_1, &builtin_form);
6798 /* Check if the requested name is in the list of form structures */
6799 for (i=0; i<numofforms; i++) {
6801 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6803 if (strequal(form_name, list[i].name)) {
6804 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6805 fill_form_1(&form_1, &list[i]);
6811 if (i == numofforms) {
6815 /* check the required size. */
6817 *needed=spoolss_size_form_1(&form_1);
6819 if (!alloc_buffer_size(buffer, buffer_size)){
6820 return WERR_INSUFFICIENT_BUFFER;
6823 if (*needed > offered) {
6824 return WERR_INSUFFICIENT_BUFFER;
6827 /* fill the buffer with the form structures */
6828 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6829 smb_io_form_1("", buffer, &form_1, 0);
6835 return WERR_UNKNOWN_LEVEL;
6839 /****************************************************************************
6840 ****************************************************************************/
6842 static void fill_port_1(PORT_INFO_1 *port, char *name)
6844 init_unistr(&port->port_name, name);
6847 /****************************************************************************
6848 ****************************************************************************/
6850 static void fill_port_2(PORT_INFO_2 *port, char *name)
6852 init_unistr(&port->port_name, name);
6853 init_unistr(&port->monitor_name, "Local Monitor");
6854 init_unistr(&port->description, "Local Port");
6855 #define PORT_TYPE_WRITE 1
6856 port->port_type=PORT_TYPE_WRITE;
6860 /****************************************************************************
6862 ****************************************************************************/
6864 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6866 PORT_INFO_1 *ports=NULL;
6869 if (*lp_enumports_cmd()) {
6870 char *cmd = lp_enumports_cmd();
6877 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6879 DEBUG(10,("Running [%s]\n", command));
6880 ret = smbrun(command, &fd);
6881 DEBUG(10,("Returned [%d]\n", ret));
6885 /* Is this the best error to return here? */
6886 return WERR_ACCESS_DENIED;
6890 qlines = fd_lines_load(fd, &numlines);
6891 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6895 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6896 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6897 dos_errstr(WERR_NOMEM)));
6898 file_lines_free(qlines);
6902 for (i=0; i<numlines; i++) {
6903 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6904 fill_port_1(&ports[i], qlines[i]);
6907 file_lines_free(qlines);
6910 *returned = numlines;
6913 *returned = 1; /* Sole Samba port returned. */
6915 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6918 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6920 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6923 /* check the required size. */
6924 for (i=0; i<*returned; i++) {
6925 DEBUGADD(6,("adding port [%d]'s size\n", i));
6926 *needed += spoolss_size_port_info_1(&ports[i]);
6929 if (!alloc_buffer_size(buffer, *needed)) {
6931 return WERR_INSUFFICIENT_BUFFER;
6934 /* fill the buffer with the ports structures */
6935 for (i=0; i<*returned; i++) {
6936 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6937 smb_io_port_1("", buffer, &ports[i], 0);
6942 if (*needed > offered) {
6944 return WERR_INSUFFICIENT_BUFFER;
6950 /****************************************************************************
6952 ****************************************************************************/
6954 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6956 PORT_INFO_2 *ports=NULL;
6959 if (*lp_enumports_cmd()) {
6960 char *cmd = lp_enumports_cmd();
6969 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6970 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6972 path = lp_lockdir();
6974 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6975 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6978 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6979 ret = smbrun(command, &fd);
6980 DEBUGADD(10,("returned [%d]\n", ret));
6984 /* Is this the best error to return here? */
6985 return WERR_ACCESS_DENIED;
6989 qlines = fd_lines_load(fd, &numlines);
6990 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6994 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6995 file_lines_free(qlines);
6999 for (i=0; i<numlines; i++) {
7000 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7001 fill_port_2(&(ports[i]), qlines[i]);
7004 file_lines_free(qlines);
7007 *returned = numlines;
7013 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7016 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7018 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7021 /* check the required size. */
7022 for (i=0; i<*returned; i++) {
7023 DEBUGADD(6,("adding port [%d]'s size\n", i));
7024 *needed += spoolss_size_port_info_2(&ports[i]);
7027 if (!alloc_buffer_size(buffer, *needed)) {
7029 return WERR_INSUFFICIENT_BUFFER;
7032 /* fill the buffer with the ports structures */
7033 for (i=0; i<*returned; i++) {
7034 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7035 smb_io_port_2("", buffer, &ports[i], 0);
7040 if (*needed > offered) {
7042 return WERR_INSUFFICIENT_BUFFER;
7048 /****************************************************************************
7050 ****************************************************************************/
7052 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7054 uint32 level = q_u->level;
7055 NEW_BUFFER *buffer = NULL;
7056 uint32 offered = q_u->offered;
7057 uint32 *needed = &r_u->needed;
7058 uint32 *returned = &r_u->returned;
7060 /* that's an [in out] buffer */
7061 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7062 buffer = r_u->buffer;
7064 DEBUG(4,("_spoolss_enumports\n"));
7071 return enumports_level_1(buffer, offered, needed, returned);
7073 return enumports_level_2(buffer, offered, needed, returned);
7075 return WERR_UNKNOWN_LEVEL;
7079 /****************************************************************************
7080 ****************************************************************************/
7082 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7083 const SPOOL_PRINTER_INFO_LEVEL *info,
7084 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7085 uint32 user_switch, const SPOOL_USER_CTR *user,
7088 NT_PRINTER_INFO_LEVEL *printer = NULL;
7091 WERROR err = WERR_OK;
7093 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7094 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7098 ZERO_STRUCTP(printer);
7100 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7101 if (!convert_printer_info(info, printer, 2)) {
7102 free_a_printer(&printer, 2);
7106 /* check to see if the printer already exists */
7108 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7109 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7110 printer->info_2->sharename));
7111 free_a_printer(&printer, 2);
7112 return WERR_PRINTER_ALREADY_EXISTS;
7115 if (*lp_addprinter_cmd() ) {
7116 if ( !add_printer_hook(printer) ) {
7117 free_a_printer(&printer,2);
7118 return WERR_ACCESS_DENIED;
7122 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7123 printer->info_2->sharename);
7126 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7127 free_a_printer(&printer,2);
7128 return WERR_ACCESS_DENIED;
7131 /* you must be a printer admin to add a new printer */
7132 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7133 free_a_printer(&printer,2);
7134 return WERR_ACCESS_DENIED;
7138 * Do sanity check on the requested changes for Samba.
7141 if (!check_printer_ok(printer->info_2, snum)) {
7142 free_a_printer(&printer,2);
7143 return WERR_INVALID_PARAM;
7147 * When a printer is created, the drivername bound to the printer is used
7148 * to lookup previously saved driver initialization info, which is then
7149 * bound to the new printer, simulating what happens in the Windows arch.
7154 set_driver_init(printer, 2);
7158 /* A valid devmode was included, convert and link it
7160 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7162 if (!convert_devicemode(printer->info_2->printername, devmode,
7163 &printer->info_2->devmode))
7167 /* write the ASCII on disk */
7168 err = mod_a_printer(*printer, 2);
7169 if (!W_ERROR_IS_OK(err)) {
7170 free_a_printer(&printer,2);
7174 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7175 /* Handle open failed - remove addition. */
7176 del_a_printer(printer->info_2->sharename);
7177 free_a_printer(&printer,2);
7178 return WERR_ACCESS_DENIED;
7181 update_c_setprinter(False);
7182 free_a_printer(&printer,2);
7187 /****************************************************************************
7188 ****************************************************************************/
7190 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7192 UNISTR2 *uni_srv_name = &q_u->server_name;
7193 uint32 level = q_u->level;
7194 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7195 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7196 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7197 uint32 user_switch = q_u->user_switch;
7198 SPOOL_USER_CTR *user = &q_u->user_ctr;
7199 POLICY_HND *handle = &r_u->handle;
7203 /* we don't handle yet */
7204 /* but I know what to do ... */
7205 return WERR_UNKNOWN_LEVEL;
7207 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7209 user_switch, user, handle);
7211 return WERR_UNKNOWN_LEVEL;
7215 /****************************************************************************
7216 ****************************************************************************/
7218 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7220 uint32 level = q_u->level;
7221 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7222 WERROR err = WERR_OK;
7223 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7224 struct current_user user;
7225 fstring driver_name;
7228 ZERO_STRUCT(driver);
7230 get_current_user(&user, p);
7232 if (!convert_printer_driver_info(info, &driver, level)) {
7237 DEBUG(5,("Cleaning driver's information\n"));
7238 err = clean_up_driver_struct(driver, level, &user);
7239 if (!W_ERROR_IS_OK(err))
7242 DEBUG(5,("Moving driver to final destination\n"));
7243 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7244 if (W_ERROR_IS_OK(err))
7245 err = WERR_ACCESS_DENIED;
7249 if (add_a_printer_driver(driver, level)!=0) {
7250 err = WERR_ACCESS_DENIED;
7254 /* BEGIN_ADMIN_LOG */
7257 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7258 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7259 fstrcpy(driver_name, driver.info_3->name);
7262 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7263 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7264 fstrcpy(driver_name, driver.info_6->name);
7270 * I think this is where he DrvUpgradePrinter() hook would be
7271 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7272 * server. Right now, we just need to send ourselves a message
7273 * to update each printer bound to this driver. --jerry
7276 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7277 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7282 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7283 * decide if the driver init data should be deleted. The rules are:
7284 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7285 * 2) delete init data only if there is no 2k/Xp driver
7286 * 3) always delete init data
7287 * The generalized rule is always use init data from the highest order driver.
7288 * It is necessary to follow the driver install by an initialization step to
7289 * finish off this process.
7292 version = driver.info_3->cversion;
7293 else if (level == 6)
7294 version = driver.info_6->version;
7299 * 9x printer driver - never delete init data
7302 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7307 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7308 * there is no 2k/Xp driver init data for this driver name.
7312 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7314 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7316 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7318 if (!del_driver_init(driver_name))
7319 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7322 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7324 free_a_printer_driver(driver1,3);
7325 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7332 * 2k or Xp printer driver - always delete init data
7335 if (!del_driver_init(driver_name))
7336 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7340 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7346 free_a_printer_driver(driver, level);
7350 /********************************************************************
7351 * spoolss_addprinterdriverex
7352 ********************************************************************/
7354 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7356 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7357 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7360 * we only support the semantics of AddPrinterDriver()
7361 * i.e. only copy files that are newer than existing ones
7364 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7365 return WERR_ACCESS_DENIED;
7367 ZERO_STRUCT(q_u_local);
7368 ZERO_STRUCT(r_u_local);
7370 /* just pass the information off to _spoolss_addprinterdriver() */
7371 q_u_local.server_name_ptr = q_u->server_name_ptr;
7372 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7373 q_u_local.level = q_u->level;
7374 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7376 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7379 /****************************************************************************
7380 ****************************************************************************/
7382 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7384 init_unistr(&info->name, name);
7387 /****************************************************************************
7388 ****************************************************************************/
7390 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7394 pstring short_archi;
7395 DRIVER_DIRECTORY_1 *info=NULL;
7397 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7399 if (get_short_archi(short_archi, long_archi)==False)
7400 return WERR_INVALID_ENVIRONMENT;
7402 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7405 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7407 DEBUG(4,("printer driver directory: [%s]\n", path));
7409 fill_driverdir_1(info, path);
7411 *needed += spoolss_size_driverdir_info_1(info);
7413 if (!alloc_buffer_size(buffer, *needed)) {
7415 return WERR_INSUFFICIENT_BUFFER;
7418 smb_io_driverdir_1("", buffer, info, 0);
7422 if (*needed > offered)
7423 return WERR_INSUFFICIENT_BUFFER;
7428 /****************************************************************************
7429 ****************************************************************************/
7431 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7433 UNISTR2 *name = &q_u->name;
7434 UNISTR2 *uni_environment = &q_u->environment;
7435 uint32 level = q_u->level;
7436 NEW_BUFFER *buffer = NULL;
7437 uint32 offered = q_u->offered;
7438 uint32 *needed = &r_u->needed;
7440 /* that's an [in out] buffer */
7441 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7442 buffer = r_u->buffer;
7444 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7450 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7452 return WERR_UNKNOWN_LEVEL;
7456 /****************************************************************************
7457 ****************************************************************************/
7459 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7461 POLICY_HND *handle = &q_u->handle;
7462 uint32 idx = q_u->index;
7463 uint32 in_value_len = q_u->valuesize;
7464 uint32 in_data_len = q_u->datasize;
7465 uint32 *out_max_value_len = &r_u->valuesize;
7466 uint16 **out_value = &r_u->value;
7467 uint32 *out_value_len = &r_u->realvaluesize;
7468 uint32 *out_type = &r_u->type;
7469 uint32 *out_max_data_len = &r_u->datasize;
7470 uint8 **data_out = &r_u->data;
7471 uint32 *out_data_len = &r_u->realdatasize;
7473 NT_PRINTER_INFO_LEVEL *printer = NULL;
7476 uint32 biggest_valuesize;
7477 uint32 biggest_datasize;
7479 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7482 REGISTRY_VALUE *val;
7483 NT_PRINTER_DATA *p_data;
7484 int i, key_index, num_values;
7487 ZERO_STRUCT( printer );
7491 *out_max_data_len = 0;
7495 DEBUG(5,("spoolss_enumprinterdata\n"));
7498 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7502 if (!get_printer_snum(p,handle, &snum))
7505 result = get_a_printer(&printer, 2, lp_servicename(snum));
7506 if (!W_ERROR_IS_OK(result))
7509 p_data = &printer->info_2->data;
7510 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7515 * The NT machine wants to know the biggest size of value and data
7517 * cf: MSDN EnumPrinterData remark section
7520 if ( !in_value_len && !in_data_len )
7522 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7525 biggest_valuesize = 0;
7526 biggest_datasize = 0;
7528 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7530 for ( i=0; i<num_values; i++ )
7532 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7534 name_length = strlen(val->valuename);
7535 if ( strlen(val->valuename) > biggest_valuesize )
7536 biggest_valuesize = name_length;
7538 if ( val->size > biggest_datasize )
7539 biggest_datasize = val->size;
7541 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7545 /* the value is an UNICODE string but real_value_size is the length
7546 in bytes including the trailing 0 */
7548 *out_value_len = 2 * (1+biggest_valuesize);
7549 *out_data_len = biggest_datasize;
7551 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7557 * the value len is wrong in NT sp3
7558 * that's the number of bytes not the number of unicode chars
7561 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7566 /* out_value should default to "" or else NT4 has
7567 problems unmarshalling the response */
7569 *out_max_value_len = (in_value_len/sizeof(uint16));
7571 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7573 result = WERR_NOMEM;
7577 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7579 /* the data is counted in bytes */
7581 *out_max_data_len = in_data_len;
7582 *out_data_len = in_data_len;
7584 /* only allocate when given a non-zero data_len */
7586 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7588 result = WERR_NOMEM;
7592 result = WERR_NO_MORE_ITEMS;
7598 * - counted in bytes in the request
7599 * - counted in UNICODE chars in the max reply
7600 * - counted in bytes in the real size
7602 * take a pause *before* coding not *during* coding
7606 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7607 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7609 result = WERR_NOMEM;
7613 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7617 *out_type = regval_type( val );
7619 /* data - counted in bytes */
7621 *out_max_data_len = in_data_len;
7622 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7624 result = WERR_NOMEM;
7627 data_len = (size_t)regval_size(val);
7628 memcpy( *data_out, regval_data_p(val), data_len );
7629 *out_data_len = data_len;
7633 free_a_printer(&printer, 2);
7637 /****************************************************************************
7638 ****************************************************************************/
7640 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7642 POLICY_HND *handle = &q_u->handle;
7643 UNISTR2 *value = &q_u->value;
7644 uint32 type = q_u->type;
7645 uint8 *data = q_u->data;
7646 uint32 real_len = q_u->real_len;
7648 NT_PRINTER_INFO_LEVEL *printer = NULL;
7650 WERROR status = WERR_OK;
7651 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7654 DEBUG(5,("spoolss_setprinterdata\n"));
7657 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7661 if (!get_printer_snum(p,handle, &snum))
7665 * Access check : NT returns "access denied" if you make a
7666 * SetPrinterData call without the necessary privildge.
7667 * we were originally returning OK if nothing changed
7668 * which made Win2k issue **a lot** of SetPrinterData
7669 * when connecting to a printer --jerry
7672 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7674 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7675 status = WERR_ACCESS_DENIED;
7679 status = get_a_printer(&printer, 2, lp_servicename(snum));
7680 if (!W_ERROR_IS_OK(status))
7683 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7686 * When client side code sets a magic printer data key, detect it and save
7687 * the current printer data and the magic key's data (its the DEVMODE) for
7688 * future printer/driver initializations.
7690 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7692 /* Set devmode and printer initialization info */
7693 status = save_driver_init( printer, 2, data, real_len );
7695 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7699 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7700 type, data, real_len );
7701 if ( W_ERROR_IS_OK(status) )
7702 status = mod_a_printer(*printer, 2);
7706 free_a_printer(&printer, 2);
7711 /****************************************************************************
7712 ****************************************************************************/
7714 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7716 POLICY_HND *handle = &q_u->handle;
7717 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7720 DEBUG(5,("_spoolss_resetprinter\n"));
7723 * All we do is to check to see if the handle and queue is valid.
7724 * This call really doesn't mean anything to us because we only
7725 * support RAW printing. --jerry
7729 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7733 if (!get_printer_snum(p,handle, &snum))
7737 /* blindly return success */
7742 /****************************************************************************
7743 ****************************************************************************/
7745 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7747 POLICY_HND *handle = &q_u->handle;
7748 UNISTR2 *value = &q_u->valuename;
7750 NT_PRINTER_INFO_LEVEL *printer = NULL;
7752 WERROR status = WERR_OK;
7753 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7756 DEBUG(5,("spoolss_deleteprinterdata\n"));
7759 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7763 if (!get_printer_snum(p, handle, &snum))
7766 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7767 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7768 return WERR_ACCESS_DENIED;
7771 status = get_a_printer(&printer, 2, lp_servicename(snum));
7772 if (!W_ERROR_IS_OK(status))
7775 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7777 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7779 free_a_printer(&printer, 2);
7784 /****************************************************************************
7785 ****************************************************************************/
7787 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7789 POLICY_HND *handle = &q_u->handle;
7790 FORM *form = &q_u->form;
7791 nt_forms_struct tmpForm;
7793 WERROR status = WERR_OK;
7794 NT_PRINTER_INFO_LEVEL *printer = NULL;
7797 nt_forms_struct *list=NULL;
7798 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7800 DEBUG(5,("spoolss_addform\n"));
7803 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7808 /* forms can be added on printer of on the print server handle */
7810 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7812 if (!get_printer_snum(p,handle, &snum))
7815 status = get_a_printer(&printer, 2, lp_servicename(snum));
7816 if (!W_ERROR_IS_OK(status))
7820 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7821 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7822 status = WERR_ACCESS_DENIED;
7826 /* can't add if builtin */
7828 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7829 status = WERR_ALREADY_EXISTS;
7833 count = get_ntforms(&list);
7835 if(!add_a_form(&list, form, &count)) {
7836 status = WERR_NOMEM;
7840 write_ntforms(&list, count);
7843 * ChangeID must always be set if this is a printer
7846 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7847 status = mod_a_printer(*printer, 2);
7851 free_a_printer(&printer, 2);
7857 /****************************************************************************
7858 ****************************************************************************/
7860 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7862 POLICY_HND *handle = &q_u->handle;
7863 UNISTR2 *form_name = &q_u->name;
7864 nt_forms_struct tmpForm;
7866 nt_forms_struct *list=NULL;
7867 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7869 WERROR status = WERR_OK;
7870 NT_PRINTER_INFO_LEVEL *printer = NULL;
7872 DEBUG(5,("spoolss_deleteform\n"));
7875 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7879 /* forms can be deleted on printer of on the print server handle */
7881 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7883 if (!get_printer_snum(p,handle, &snum))
7886 status = get_a_printer(&printer, 2, lp_servicename(snum));
7887 if (!W_ERROR_IS_OK(status))
7891 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7892 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7893 status = WERR_ACCESS_DENIED;
7897 /* can't delete if builtin */
7899 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7900 status = WERR_INVALID_PARAM;
7904 count = get_ntforms(&list);
7906 if ( !delete_a_form(&list, form_name, &count, &status ))
7910 * ChangeID must always be set if this is a printer
7913 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7914 status = mod_a_printer(*printer, 2);
7918 free_a_printer(&printer, 2);
7924 /****************************************************************************
7925 ****************************************************************************/
7927 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7929 POLICY_HND *handle = &q_u->handle;
7930 FORM *form = &q_u->form;
7931 nt_forms_struct tmpForm;
7933 WERROR status = WERR_OK;
7934 NT_PRINTER_INFO_LEVEL *printer = NULL;
7937 nt_forms_struct *list=NULL;
7938 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7940 DEBUG(5,("spoolss_setform\n"));
7943 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7947 /* forms can be modified on printer of on the print server handle */
7949 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7951 if (!get_printer_snum(p,handle, &snum))
7954 status = get_a_printer(&printer, 2, lp_servicename(snum));
7955 if (!W_ERROR_IS_OK(status))
7959 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7960 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7961 status = WERR_ACCESS_DENIED;
7965 /* can't set if builtin */
7966 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7967 status = WERR_INVALID_PARAM;
7971 count = get_ntforms(&list);
7972 update_a_form(&list, form, count);
7973 write_ntforms(&list, count);
7976 * ChangeID must always be set if this is a printer
7979 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7980 status = mod_a_printer(*printer, 2);
7985 free_a_printer(&printer, 2);
7991 /****************************************************************************
7992 enumprintprocessors level 1.
7993 ****************************************************************************/
7995 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7997 PRINTPROCESSOR_1 *info_1=NULL;
7999 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8004 init_unistr(&info_1->name, "winprint");
8006 *needed += spoolss_size_printprocessor_info_1(info_1);
8008 if (!alloc_buffer_size(buffer, *needed))
8009 return WERR_INSUFFICIENT_BUFFER;
8011 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8015 if (*needed > offered) {
8017 return WERR_INSUFFICIENT_BUFFER;
8023 /****************************************************************************
8024 ****************************************************************************/
8026 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8028 uint32 level = q_u->level;
8029 NEW_BUFFER *buffer = NULL;
8030 uint32 offered = q_u->offered;
8031 uint32 *needed = &r_u->needed;
8032 uint32 *returned = &r_u->returned;
8034 /* that's an [in out] buffer */
8035 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8036 buffer = r_u->buffer;
8038 DEBUG(5,("spoolss_enumprintprocessors\n"));
8041 * Enumerate the print processors ...
8043 * Just reply with "winprint", to keep NT happy
8044 * and I can use my nice printer checker.
8052 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8054 return WERR_UNKNOWN_LEVEL;
8058 /****************************************************************************
8059 enumprintprocdatatypes level 1.
8060 ****************************************************************************/
8062 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8064 PRINTPROCDATATYPE_1 *info_1=NULL;
8066 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8071 init_unistr(&info_1->name, "RAW");
8073 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8075 if (!alloc_buffer_size(buffer, *needed))
8076 return WERR_INSUFFICIENT_BUFFER;
8078 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8082 if (*needed > offered) {
8084 return WERR_INSUFFICIENT_BUFFER;
8090 /****************************************************************************
8091 ****************************************************************************/
8093 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8095 uint32 level = q_u->level;
8096 NEW_BUFFER *buffer = NULL;
8097 uint32 offered = q_u->offered;
8098 uint32 *needed = &r_u->needed;
8099 uint32 *returned = &r_u->returned;
8101 /* that's an [in out] buffer */
8102 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8103 buffer = r_u->buffer;
8105 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8112 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8114 return WERR_UNKNOWN_LEVEL;
8118 /****************************************************************************
8119 enumprintmonitors level 1.
8120 ****************************************************************************/
8122 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8124 PRINTMONITOR_1 *info_1=NULL;
8126 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8131 init_unistr(&info_1->name, "Local Port");
8133 *needed += spoolss_size_printmonitor_info_1(info_1);
8135 if (!alloc_buffer_size(buffer, *needed))
8136 return WERR_INSUFFICIENT_BUFFER;
8138 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8142 if (*needed > offered) {
8144 return WERR_INSUFFICIENT_BUFFER;
8150 /****************************************************************************
8151 enumprintmonitors level 2.
8152 ****************************************************************************/
8154 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8156 PRINTMONITOR_2 *info_2=NULL;
8158 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8163 init_unistr(&info_2->name, "Local Port");
8164 init_unistr(&info_2->environment, "Windows NT X86");
8165 init_unistr(&info_2->dll_name, "localmon.dll");
8167 *needed += spoolss_size_printmonitor_info_2(info_2);
8169 if (!alloc_buffer_size(buffer, *needed))
8170 return WERR_INSUFFICIENT_BUFFER;
8172 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8176 if (*needed > offered) {
8178 return WERR_INSUFFICIENT_BUFFER;
8184 /****************************************************************************
8185 ****************************************************************************/
8187 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8189 uint32 level = q_u->level;
8190 NEW_BUFFER *buffer = NULL;
8191 uint32 offered = q_u->offered;
8192 uint32 *needed = &r_u->needed;
8193 uint32 *returned = &r_u->returned;
8195 /* that's an [in out] buffer */
8196 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8197 buffer = r_u->buffer;
8199 DEBUG(5,("spoolss_enumprintmonitors\n"));
8202 * Enumerate the print monitors ...
8204 * Just reply with "Local Port", to keep NT happy
8205 * and I can use my nice printer checker.
8213 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8215 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8217 return WERR_UNKNOWN_LEVEL;
8221 /****************************************************************************
8222 ****************************************************************************/
8224 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8228 JOB_INFO_1 *info_1=NULL;
8230 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8232 if (info_1 == NULL) {
8237 for (i=0; i<count && found==False; i++) {
8238 if (queue[i].job==(int)jobid)
8245 /* NT treats not found as bad param... yet another bad choice */
8246 return WERR_INVALID_PARAM;
8249 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8251 *needed += spoolss_size_job_info_1(info_1);
8253 if (!alloc_buffer_size(buffer, *needed)) {
8255 return WERR_INSUFFICIENT_BUFFER;
8258 smb_io_job_info_1("", buffer, info_1, 0);
8262 if (*needed > offered)
8263 return WERR_INSUFFICIENT_BUFFER;
8268 /****************************************************************************
8269 ****************************************************************************/
8271 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8276 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8278 DEVICEMODE *devmode = NULL;
8279 NT_DEVICEMODE *nt_devmode = NULL;
8281 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8283 ZERO_STRUCTP(info_2);
8285 if (info_2 == NULL) {
8290 for ( i=0; i<count && found==False; i++ )
8292 if (queue[i].job == (int)jobid)
8298 /* NT treats not found as bad param... yet another bad
8300 ret = WERR_INVALID_PARAM;
8304 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
8305 if (!W_ERROR_IS_OK(ret))
8309 * if the print job does not have a DEVMODE associated with it,
8310 * just use the one for the printer. A NULL devicemode is not
8311 * a failure condition
8314 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8315 devmode = construct_dev_mode(snum);
8317 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8318 ZERO_STRUCTP( devmode );
8319 convert_nt_devicemode( devmode, nt_devmode );
8323 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8325 *needed += spoolss_size_job_info_2(info_2);
8327 if (!alloc_buffer_size(buffer, *needed)) {
8328 ret = WERR_INSUFFICIENT_BUFFER;
8332 smb_io_job_info_2("", buffer, info_2, 0);
8334 if (*needed > offered) {
8335 ret = WERR_INSUFFICIENT_BUFFER;
8342 /* Cleanup allocated memory */
8344 free_job_info_2(info_2); /* Also frees devmode */
8346 free_a_printer(&ntprinter, 2);
8351 /****************************************************************************
8352 ****************************************************************************/
8354 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8356 POLICY_HND *handle = &q_u->handle;
8357 uint32 jobid = q_u->jobid;
8358 uint32 level = q_u->level;
8359 NEW_BUFFER *buffer = NULL;
8360 uint32 offered = q_u->offered;
8361 uint32 *needed = &r_u->needed;
8362 WERROR wstatus = WERR_OK;
8366 print_queue_struct *queue = NULL;
8367 print_status_struct prt_status;
8369 /* that's an [in out] buffer */
8370 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8371 buffer = r_u->buffer;
8373 DEBUG(5,("spoolss_getjob\n"));
8377 if (!get_printer_snum(p, handle, &snum))
8380 count = print_queue_status(snum, &queue, &prt_status);
8382 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8383 count, prt_status.status, prt_status.message));
8387 wstatus = getjob_level_1(queue, count, snum, jobid,
8388 buffer, offered, needed);
8391 wstatus = getjob_level_2(queue, count, snum, jobid,
8392 buffer, offered, needed);
8395 wstatus = WERR_UNKNOWN_LEVEL;
8403 /********************************************************************
8404 spoolss_getprinterdataex
8406 From MSDN documentation of GetPrinterDataEx: pass request
8407 to GetPrinterData if key is "PrinterDriverData".
8408 ********************************************************************/
8410 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8412 POLICY_HND *handle = &q_u->handle;
8413 uint32 in_size = q_u->size;
8414 uint32 *type = &r_u->type;
8415 uint32 *out_size = &r_u->size;
8416 uint8 **data = &r_u->data;
8417 uint32 *needed = &r_u->needed;
8418 fstring keyname, valuename;
8420 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8422 NT_PRINTER_INFO_LEVEL *printer = NULL;
8424 WERROR status = WERR_OK;
8426 DEBUG(4,("_spoolss_getprinterdataex\n"));
8428 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8429 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8431 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8432 keyname, valuename));
8434 /* in case of problem, return some default values */
8438 *out_size = in_size;
8441 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8442 status = WERR_BADFID;
8446 /* Is the handle to a printer or to the server? */
8448 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8449 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8450 status = WERR_INVALID_PARAM;
8454 if ( !get_printer_snum(p,handle, &snum) )
8457 status = get_a_printer(&printer, 2, lp_servicename(snum));
8458 if ( !W_ERROR_IS_OK(status) )
8461 /* check to see if the keyname is valid */
8462 if ( !strlen(keyname) ) {
8463 status = WERR_INVALID_PARAM;
8467 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8468 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8469 free_a_printer( &printer, 2 );
8470 status = WERR_BADFILE;
8474 /* When given a new keyname, we should just create it */
8476 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8478 if (*needed > *out_size)
8479 status = WERR_MORE_DATA;
8482 if ( !W_ERROR_IS_OK(status) )
8484 DEBUG(5, ("error: allocating %d\n", *out_size));
8486 /* reply this param doesn't exist */
8490 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8491 status = WERR_NOMEM;
8501 free_a_printer( &printer, 2 );
8506 /********************************************************************
8507 * spoolss_setprinterdataex
8508 ********************************************************************/
8510 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8512 POLICY_HND *handle = &q_u->handle;
8513 uint32 type = q_u->type;
8514 uint8 *data = q_u->data;
8515 uint32 real_len = q_u->real_len;
8517 NT_PRINTER_INFO_LEVEL *printer = NULL;
8519 WERROR status = WERR_OK;
8520 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8525 DEBUG(4,("_spoolss_setprinterdataex\n"));
8527 /* From MSDN documentation of SetPrinterDataEx: pass request to
8528 SetPrinterData if key is "PrinterDriverData" */
8531 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8535 if ( !get_printer_snum(p,handle, &snum) )
8539 * Access check : NT returns "access denied" if you make a
8540 * SetPrinterData call without the necessary privildge.
8541 * we were originally returning OK if nothing changed
8542 * which made Win2k issue **a lot** of SetPrinterData
8543 * when connecting to a printer --jerry
8546 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8548 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8549 return WERR_ACCESS_DENIED;
8552 status = get_a_printer(&printer, 2, lp_servicename(snum));
8553 if (!W_ERROR_IS_OK(status))
8556 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8557 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8559 /* check for OID in valuename */
8561 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8567 /* save the registry data */
8569 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8571 /* save the OID if one was specified and the previous set call succeeded */
8573 if ( W_ERROR_IS_OK(status) && oid_string )
8576 fstrcat( keyname, "\\" );
8577 fstrcat( keyname, SPOOL_OID_KEY );
8580 * I'm not checking the status here on purpose. Don't know
8581 * if this is right, but I'm returning the status from the
8582 * previous set_printer_dataex() call. I have no idea if
8583 * this is right. --jerry
8586 set_printer_dataex( printer, keyname, valuename,
8587 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8590 free_a_printer(&printer, 2);
8596 /********************************************************************
8597 * spoolss_deleteprinterdataex
8598 ********************************************************************/
8600 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8602 POLICY_HND *handle = &q_u->handle;
8603 UNISTR2 *value = &q_u->valuename;
8604 UNISTR2 *key = &q_u->keyname;
8606 NT_PRINTER_INFO_LEVEL *printer = NULL;
8608 WERROR status = WERR_OK;
8609 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8610 pstring valuename, keyname;
8612 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8615 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8619 if (!get_printer_snum(p, handle, &snum))
8622 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8623 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8624 return WERR_ACCESS_DENIED;
8627 status = get_a_printer(&printer, 2, lp_servicename(snum));
8628 if (!W_ERROR_IS_OK(status))
8631 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8632 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8634 status = delete_printer_dataex( printer, keyname, valuename );
8636 free_a_printer(&printer, 2);
8641 /********************************************************************
8642 * spoolss_enumprinterkey
8643 ********************************************************************/
8646 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8649 fstring *keynames = NULL;
8650 uint16 *enumkeys = NULL;
8653 POLICY_HND *handle = &q_u->handle;
8654 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8655 NT_PRINTER_DATA *data;
8656 NT_PRINTER_INFO_LEVEL *printer = NULL;
8658 WERROR status = WERR_BADFILE;
8661 DEBUG(4,("_spoolss_enumprinterkey\n"));
8664 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8668 if ( !get_printer_snum(p,handle, &snum) )
8671 status = get_a_printer(&printer, 2, lp_servicename(snum));
8672 if (!W_ERROR_IS_OK(status))
8675 /* get the list of subkey names */
8677 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8678 data = &printer->info_2->data;
8680 num_keys = get_printer_subkeys( data, key, &keynames );
8682 if ( num_keys == -1 ) {
8683 status = WERR_BADFILE;
8687 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8689 r_u->needed = printerkey_len*2;
8691 if ( q_u->size < r_u->needed ) {
8692 status = WERR_MORE_DATA;
8696 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8697 status = WERR_NOMEM;
8703 if ( q_u->size < r_u->needed )
8704 status = WERR_MORE_DATA;
8707 free_a_printer( &printer, 2 );
8708 SAFE_FREE( keynames );
8713 /********************************************************************
8714 * spoolss_deleteprinterkey
8715 ********************************************************************/
8717 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8719 POLICY_HND *handle = &q_u->handle;
8720 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8722 NT_PRINTER_INFO_LEVEL *printer = NULL;
8726 DEBUG(5,("spoolss_deleteprinterkey\n"));
8729 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8733 /* if keyname == NULL, return error */
8735 if ( !q_u->keyname.buffer )
8736 return WERR_INVALID_PARAM;
8738 if (!get_printer_snum(p, handle, &snum))
8741 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8742 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8743 return WERR_ACCESS_DENIED;
8746 status = get_a_printer(&printer, 2, lp_servicename(snum));
8747 if (!W_ERROR_IS_OK(status))
8750 /* delete the key and all subneys */
8752 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8754 status = delete_all_printer_data( printer->info_2, key );
8756 if ( W_ERROR_IS_OK(status) )
8757 status = mod_a_printer(*printer, 2);
8759 free_a_printer( &printer, 2 );
8765 /********************************************************************
8766 * spoolss_enumprinterdataex
8767 ********************************************************************/
8769 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8771 POLICY_HND *handle = &q_u->handle;
8772 uint32 in_size = q_u->size;
8775 NT_PRINTER_INFO_LEVEL *printer = NULL;
8776 PRINTER_ENUM_VALUES *enum_values = NULL;
8777 NT_PRINTER_DATA *p_data;
8779 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8784 REGISTRY_VALUE *val;
8789 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8792 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8796 /* first get the printer off of disk */
8798 if (!get_printer_snum(p,handle, &snum))
8801 ZERO_STRUCT(printer);
8802 result = get_a_printer(&printer, 2, lp_servicename(snum));
8803 if (!W_ERROR_IS_OK(result))
8806 /* now look for a match on the key name */
8808 p_data = &printer->info_2->data;
8810 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8811 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8813 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8814 result = WERR_INVALID_PARAM;
8821 /* allocate the memory for the array of pointers -- if necessary */
8823 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8826 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8828 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8829 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8830 result = WERR_NOMEM;
8834 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8838 * loop through all params and build the array to pass
8839 * back to the client
8842 for ( i=0; i<num_entries; i++ )
8844 /* lookup the registry value */
8846 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8847 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8851 value_name = regval_name( val );
8852 init_unistr( &enum_values[i].valuename, value_name );
8853 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8854 enum_values[i].type = regval_type( val );
8856 data_len = regval_size( val );
8858 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8860 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8862 result = WERR_NOMEM;
8866 enum_values[i].data_len = data_len;
8868 /* keep track of the size of the array in bytes */
8870 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8873 /* housekeeping information in the reply */
8875 r_u->needed = needed;
8876 r_u->returned = num_entries;
8878 if (needed > in_size) {
8879 result = WERR_MORE_DATA;
8883 /* copy data into the reply */
8885 r_u->ctr.size = r_u->needed;
8886 r_u->ctr.size_of_array = r_u->returned;
8887 r_u->ctr.values = enum_values;
8892 free_a_printer(&printer, 2);
8897 /****************************************************************************
8898 ****************************************************************************/
8900 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8902 init_unistr(&info->name, name);
8905 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8906 UNISTR2 *environment,
8913 pstring short_archi;
8914 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8916 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8918 if (get_short_archi(short_archi, long_archi)==False)
8919 return WERR_INVALID_ENVIRONMENT;
8921 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8924 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8926 fill_printprocessordirectory_1(info, path);
8928 *needed += spoolss_size_printprocessordirectory_info_1(info);
8930 if (!alloc_buffer_size(buffer, *needed)) {
8932 return WERR_INSUFFICIENT_BUFFER;
8935 smb_io_printprocessordirectory_1("", buffer, info, 0);
8939 if (*needed > offered)
8940 return WERR_INSUFFICIENT_BUFFER;
8945 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8947 uint32 level = q_u->level;
8948 NEW_BUFFER *buffer = NULL;
8949 uint32 offered = q_u->offered;
8950 uint32 *needed = &r_u->needed;
8953 /* that's an [in out] buffer */
8954 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8955 buffer = r_u->buffer;
8957 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8963 result = getprintprocessordirectory_level_1
8964 (&q_u->name, &q_u->environment, buffer, offered, needed);
8967 result = WERR_UNKNOWN_LEVEL;
8975 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
8976 SPOOL_R_REPLYOPENPRINTER *r_u)
8978 DEBUG(5,("_spoolss_replyopenprinter\n"));
8980 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
8985 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
8986 SPOOL_R_REPLYCLOSEPRINTER *r_u)
8988 DEBUG(5,("_spoolss_replycloseprinter\n"));