2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2002,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
32 #define DBGC_CLASS DBGC_RPC_SRV
33 /* #define EMULATE_WIN2K_HACK 1 */
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41 #define PRINTER_HANDLE_IS_PRINTER 0
42 #define PRINTER_HANDLE_IS_PRINTSERVER 1
44 /* Table to map the driver version */
46 char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
60 /* structure to store the printer handles */
61 /* and a reference to what it's pointing to */
62 /* and the notify info asked about */
63 /* that's the central struct */
64 typedef struct _Printer{
65 struct _Printer *prev, *next;
66 BOOL document_started;
68 uint32 jobid; /* jobid in printing backend */
72 fstring printerservername;
75 uint32 access_granted;
81 SPOOL_NOTIFY_OPTION *option;
82 POLICY_HND client_hnd;
83 uint32 client_connected;
91 /* devmode sent in the OpenPrinter() call */
92 NT_DEVICEMODE *nt_devmode;
96 static Printer_entry *printers_list;
98 typedef struct _counter_printer_0 {
106 static ubi_dlList counter_list;
108 static struct cli_state notify_cli; /* print notify back-channel */
109 static uint32 smb_connections=0;
112 /* in printing/nt_printing.c */
114 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
116 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
117 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
119 /* translate between internal status numbers and NT status numbers */
120 static int nt_printj_status(int v)
126 return JOB_STATUS_PAUSED;
128 return JOB_STATUS_SPOOLING;
130 return JOB_STATUS_PRINTING;
132 return JOB_STATUS_ERROR;
134 return JOB_STATUS_DELETING;
136 return JOB_STATUS_OFFLINE;
138 return JOB_STATUS_PAPEROUT;
140 return JOB_STATUS_PRINTED;
142 return JOB_STATUS_DELETED;
144 return JOB_STATUS_BLOCKED;
145 case LPQ_USER_INTERVENTION:
146 return JOB_STATUS_USER_INTERVENTION;
151 static int nt_printq_status(int v)
155 return PRINTER_STATUS_PAUSED;
164 /****************************************************************************
165 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
166 ****************************************************************************/
168 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
173 SAFE_FREE((*pp)->ctr.type);
177 /***************************************************************************
178 Disconnect from the client
179 ****************************************************************************/
181 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
186 * Tell the specific printing tdb we no longer want messages for this printer
187 * by deregistering our PID.
190 if (!print_notify_deregister_pid(snum))
191 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
193 /* weird if the test succeds !!! */
194 if (smb_connections==0) {
195 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
199 result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle);
201 if (!W_ERROR_IS_OK(result))
202 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
203 dos_errstr(result)));
205 /* if it's the last connection, deconnect the IPC$ share */
206 if (smb_connections==1) {
207 cli_nt_session_close(¬ify_cli);
208 cli_ulogoff(¬ify_cli);
209 cli_shutdown(¬ify_cli);
210 message_deregister(MSG_PRINTER_NOTIFY2);
212 /* Tell the connections db we're no longer interested in
213 * printer notify messages. */
215 register_message_flags( False, FLAG_MSG_PRINTING );
221 /****************************************************************************
222 Functions to free a printer entry datastruct.
223 ****************************************************************************/
225 static void free_printer_entry(void *ptr)
227 Printer_entry *Printer = (Printer_entry *)ptr;
229 if (Printer->notify.client_connected==True)
230 srv_spoolss_replycloseprinter(print_queue_snum(Printer->dev.handlename),
231 &Printer->notify.client_hnd);
233 Printer->notify.flags=0;
234 Printer->notify.options=0;
235 Printer->notify.localmachine[0]='\0';
236 Printer->notify.printerlocal=0;
237 free_spool_notify_option(&Printer->notify.option);
238 Printer->notify.option=NULL;
239 Printer->notify.client_connected=False;
241 free_nt_devicemode( &Printer->nt_devmode );
243 /* Remove from the internal list. */
244 DLIST_REMOVE(printers_list, Printer);
249 /****************************************************************************
250 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
251 ****************************************************************************/
253 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
255 SPOOL_NOTIFY_OPTION *new_sp = NULL;
260 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
267 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
269 if (!new_sp->ctr.type) {
278 /****************************************************************************
279 find printer index by handle
280 ****************************************************************************/
282 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
284 Printer_entry *find_printer = NULL;
286 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
287 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
294 /****************************************************************************
295 Close printer index by handle.
296 ****************************************************************************/
298 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
300 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
303 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
307 close_policy_hnd(p, hnd);
312 /****************************************************************************
313 Delete a printer given a handle.
314 ****************************************************************************/
316 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
318 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
321 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
326 * It turns out that Windows allows delete printer on a handle
327 * opened by an admin user, then used on a pipe handle created
328 * by an anonymous user..... but they're working on security.... riiight !
332 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
333 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
334 return WERR_ACCESS_DENIED;
338 /* Check calling user has permission to delete printer. Note that
339 since we set the snum parameter to -1 only administrators can
340 delete the printer. This stops people with the Full Control
341 permission from deleting the printer. */
343 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
344 DEBUG(3, ("printer delete denied by security descriptor\n"));
345 return WERR_ACCESS_DENIED;
349 if (del_a_printer(Printer->dev.handlename) != 0) {
350 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
354 if (*lp_deleteprinter_cmd()) {
356 char *cmd = lp_deleteprinter_cmd();
361 /* Printer->dev.handlename equals portname equals sharename */
362 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
363 Printer->dev.handlename);
365 DEBUG(10,("Running [%s]\n", command));
366 ret = smbrun(command, NULL);
368 return WERR_BADFID; /* What to return here? */
370 DEBUGADD(10,("returned [%d]\n", ret));
372 /* Send SIGHUP to process group... is there a better way? */
375 /* go ahead and re-read the services immediately */
376 reload_services( False );
378 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
379 return WERR_ACCESS_DENIED;
385 /****************************************************************************
386 Return the snum of a printer corresponding to an handle.
387 ****************************************************************************/
389 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
391 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
394 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
398 switch (Printer->printer_type) {
399 case PRINTER_HANDLE_IS_PRINTER:
400 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
401 *number = print_queue_snum(Printer->dev.handlename);
402 return (*number != -1);
403 case PRINTER_HANDLE_IS_PRINTSERVER:
410 /****************************************************************************
411 Set printer handle type.
412 Check if it's \\server or \\server\printer
413 ****************************************************************************/
415 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
417 DEBUG(3,("Setting printer type=%s\n", handlename));
419 if ( strlen(handlename) < 3 ) {
420 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
424 /* it's a print server */
425 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
426 DEBUGADD(4,("Printer is a print server\n"));
427 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
431 DEBUGADD(4,("Printer is a printer\n"));
432 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
438 /****************************************************************************
439 Set printer handle name.
440 ****************************************************************************/
442 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
445 int n_services=lp_numservices();
450 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
452 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
453 ZERO_STRUCT(Printer->dev.printerservername);
454 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
458 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
461 if (*handlename=='\\') {
462 aprinter=strchr_m(handlename+2, '\\');
469 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
472 * The original code allowed smbd to store a printer name that
473 * was different from the share name. This is not possible
474 * anymore, so I've simplified this loop greatly. Here
475 * we are just verifying that the printer name is a valid
476 * printer service defined in smb.conf
477 * --jerry [Fri Feb 15 11:17:46 CST 2002]
480 for (snum=0; snum<n_services; snum++) {
482 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
485 fstrcpy(sname, lp_servicename(snum));
487 DEBUGADD(5,("share:%s\n",sname));
489 if (! StrCaseCmp(sname, aprinter)) {
498 DEBUGADD(4,("Printer not found\n"));
502 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
504 ZERO_STRUCT(Printer->dev.handlename);
505 fstrcpy(Printer->dev.handlename, sname);
510 /****************************************************************************
511 Find first available printer slot. creates a printer handle for you.
512 ****************************************************************************/
514 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
516 Printer_entry *new_printer;
518 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
520 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
523 ZERO_STRUCTP(new_printer);
525 new_printer->notify.option=NULL;
527 /* Add to the internal list. */
528 DLIST_ADD(printers_list, new_printer);
530 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
531 SAFE_FREE(new_printer);
535 if (!set_printer_hnd_printertype(new_printer, name)) {
536 close_printer_handle(p, hnd);
540 if (!set_printer_hnd_name(new_printer, name)) {
541 close_printer_handle(p, hnd);
545 new_printer->access_granted = access_granted;
547 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
552 /****************************************************************************
553 Allocate more memory for a BUFFER.
554 ****************************************************************************/
556 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
564 /* damn, I'm doing the reverse operation of prs_grow() :) */
565 if (buffer_size < prs_data_size(ps))
568 extra_space = buffer_size - prs_data_size(ps);
571 * save the offset and move to the end of the buffer
572 * prs_grow() checks the extra_space against the offset
574 old_offset=prs_offset(ps);
575 prs_set_offset(ps, prs_data_size(ps));
577 if (!prs_grow(ps, extra_space))
580 prs_set_offset(ps, old_offset);
582 buffer->string_at_end=prs_data_size(ps);
587 /***************************************************************************
588 check to see if the client motify handle is monitoring the notification
589 given by (notify_type, notify_field).
590 **************************************************************************/
592 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
598 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
601 SPOOL_NOTIFY_OPTION *option = p->notify.option;
605 * Flags should always be zero when the change notify
606 * is registered by the cliebnt's spooler. A user Win32 app
607 * might use the flags though instead of the NOTIFY_OPTION_INFO
612 return is_monitoring_event_flags(
613 p->notify.flags, notify_type, notify_field);
615 for (i = 0; i < option->count; i++) {
617 /* Check match for notify_type */
619 if (option->ctr.type[i].type != notify_type)
622 /* Check match for field */
624 for (j = 0; j < option->ctr.type[i].count; j++) {
625 if (option->ctr.type[i].fields[j] == notify_field) {
631 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
632 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
633 p->dev.handlename : p->dev.printerservername,
634 notify_type, notify_field));
639 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
641 static void notify_one_value(struct spoolss_notify_msg *msg,
642 SPOOL_NOTIFY_INFO_DATA *data,
645 data->notify_data.value[0] = msg->notify.value[0];
646 data->notify_data.value[1] = 0;
649 static void notify_string(struct spoolss_notify_msg *msg,
650 SPOOL_NOTIFY_INFO_DATA *data,
655 /* The length of the message includes the trailing \0 */
657 init_unistr2(&unistr, msg->notify.data, msg->len);
659 data->notify_data.data.length = msg->len * 2;
660 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
662 if (!data->notify_data.data.string) {
663 data->notify_data.data.length = 0;
667 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
670 static void notify_system_time(struct spoolss_notify_msg *msg,
671 SPOOL_NOTIFY_INFO_DATA *data,
677 if (msg->len != sizeof(time_t)) {
678 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
683 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
684 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
688 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
689 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
693 if (!spoolss_io_system_time("", &ps, 0, &systime))
696 data->notify_data.data.length = prs_offset(&ps);
697 data->notify_data.data.string =
698 talloc(mem_ctx, prs_offset(&ps));
700 memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
705 struct notify2_message_table {
707 void (*fn)(struct spoolss_notify_msg *msg,
708 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
711 static struct notify2_message_table printer_notify_table[] = {
712 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
713 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
714 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
715 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
716 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
717 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
718 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
719 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
720 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
721 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
722 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
723 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
724 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
725 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
726 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
727 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
728 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
729 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
730 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
733 static struct notify2_message_table job_notify_table[] = {
734 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
735 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
736 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
737 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
738 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
739 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
740 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
741 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
742 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
743 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
744 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
745 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
746 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
747 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
748 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
749 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
750 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
751 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
752 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
753 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
754 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
755 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
756 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
757 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
761 /***********************************************************************
762 Allocate talloc context for container object
763 **********************************************************************/
765 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
770 ctr->ctx = talloc_init();
775 /***********************************************************************
776 release all allocated memory and zero out structure
777 **********************************************************************/
779 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
785 talloc_destroy(ctr->ctx);
792 /***********************************************************************
793 **********************************************************************/
795 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
803 /***********************************************************************
804 **********************************************************************/
806 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
808 if ( !ctr || !ctr->msg_groups )
811 if ( idx >= ctr->num_groups )
814 return &ctr->msg_groups[idx];
818 /***********************************************************************
819 How many groups of change messages do we have ?
820 **********************************************************************/
822 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
827 return ctr->num_groups;
830 /***********************************************************************
831 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
832 **********************************************************************/
834 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
836 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
837 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
838 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
844 /* loop over all groups looking for a matching printer name */
846 for ( i=0; i<ctr->num_groups; i++ ) {
847 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
851 /* add a new group? */
853 if ( i == ctr->num_groups )
857 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
858 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
861 ctr->msg_groups = groups;
863 /* clear the new entry and set the printer name */
865 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
866 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
869 /* add the change messages; 'i' is the correct index now regardless */
871 msg_grp = &ctr->msg_groups[i];
875 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
876 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
879 msg_grp->msgs = msg_list;
881 new_slot = msg_grp->num_msgs-1;
882 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
884 /* need to allocate own copy of data */
887 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
889 return ctr->num_groups;
892 /***********************************************************************
893 Send a change notication message on all handles which have a call
895 **********************************************************************/
897 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
900 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
901 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
902 SPOOLSS_NOTIFY_MSG *messages;
906 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
910 messages = msg_group->msgs;
913 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
917 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
919 /* loop over all printers */
921 for (p = printers_list; p; p = p->next)
923 SPOOL_NOTIFY_INFO_DATA *data;
928 /* Is there notification on this handle? */
930 if ( !p->notify.client_connected )
933 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
935 /* For this printer? Print servers always receive
938 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
939 ( !strequal(msg_group->printername, p->dev.handlename) ) )
942 DEBUG(10,("Our printer\n"));
944 /* allocate the max entries possible */
946 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
949 /* build the array of change notifications */
951 for ( i=0; i<msg_group->num_msgs; i++ )
953 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
955 /* Are we monitoring this event? */
957 if (!is_monitoring_event(p, msg->type, msg->field))
961 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
962 msg->type, msg->field, p->dev.handlename));
965 * if the is a printer notification handle and not a job notification
966 * type, then set the id to 0. Other wise just use what was specified
969 * When registering change notification on a print server handle
970 * we always need to send back the id (snum) matching the printer
971 * for which the change took place. For change notify registered
972 * on a printer handle, this does not matter and the id should be 0.
977 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
983 /* Convert unix jobid to smb jobid */
985 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID)
987 id = sysjob_to_jobid(msg->id);
990 DEBUG(3, ("no such unix jobid %d\n", msg->id));
995 construct_info_data( &data[data_len], msg->type, msg->field, id );
998 case PRINTER_NOTIFY_TYPE:
999 if ( !printer_notify_table[msg->field].fn )
1001 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1005 case JOB_NOTIFY_TYPE:
1006 if ( !job_notify_table[msg->field].fn )
1008 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1013 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1020 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1021 data_len, data, p->notify.change, 0 );
1025 DEBUG(8,("send_notify2_changes: Exit...\n"));
1029 /***********************************************************************
1030 **********************************************************************/
1032 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
1037 /* Unpack message */
1039 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1042 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
1043 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1046 tdb_unpack((char *)buf + offset, len - offset, "dd",
1047 &msg->notify.value[0], &msg->notify.value[1]);
1049 tdb_unpack((char *)buf + offset, len - offset, "B",
1050 &msg->len, &msg->notify.data);
1052 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1053 msg->type, msg->field, msg->flags));
1056 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1057 msg->notify.value[1]));
1059 dump_data(3, msg->notify.data, msg->len);
1064 /********************************************************************
1065 Receive a notify2 message list
1066 ********************************************************************/
1068 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1070 size_t msg_count, i;
1071 char *buf = (char *)msg;
1074 SPOOLSS_NOTIFY_MSG notify;
1075 SPOOLSS_NOTIFY_MSG_CTR messages;
1079 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1083 msg_count = IVAL(buf, 0);
1086 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1088 if (msg_count == 0) {
1089 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1093 /* initialize the container */
1095 ZERO_STRUCT( messages );
1096 notify_msg_ctr_init( &messages );
1099 * build message groups for each printer identified
1100 * in a change_notify msg. Remember that a PCN message
1101 * includes the handle returned for the srv_spoolss_replyopenprinter()
1102 * call. Therefore messages are grouped according to printer handle.
1105 for ( i=0; i<msg_count; i++ )
1107 if (msg_ptr + 4 - buf > len) {
1108 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1112 msg_len = IVAL(msg_ptr,0);
1115 if (msg_ptr + msg_len - buf > len) {
1116 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1120 /* unpack messages */
1122 ZERO_STRUCT( notify );
1123 notify2_unpack_msg( ¬ify, msg_ptr, msg_len );
1126 /* add to correct list in container */
1128 notify_msg_ctr_addmsg( &messages, ¬ify );
1130 /* free memory that might have been allocated by notify2_unpack_msg() */
1132 if ( notify.len != 0 )
1133 SAFE_FREE( notify.notify.data );
1136 /* process each group of messages */
1138 num_groups = notify_msg_ctr_numgroups( &messages );
1139 for ( i=0; i<num_groups; i++ )
1140 send_notify2_changes( &messages, i );
1145 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1147 notify_msg_ctr_destroy( &messages );
1152 /********************************************************************
1153 Send a message to ourself about new driver being installed
1154 so we can upgrade the information for each printer bound to this
1156 ********************************************************************/
1158 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1160 int len = strlen(drivername);
1165 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1168 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1173 /**********************************************************************
1174 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1175 over all printers, upgrading ones as neessary
1176 **********************************************************************/
1178 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1182 int n_services = lp_numservices();
1184 len = MIN(len,sizeof(drivername)-1);
1185 strncpy(drivername, buf, len);
1187 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1189 /* Iterate the printer list */
1191 for (snum=0; snum<n_services; snum++)
1193 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1196 NT_PRINTER_INFO_LEVEL *printer = NULL;
1198 result = get_a_printer(&printer, 2, lp_servicename(snum));
1199 if (!W_ERROR_IS_OK(result))
1202 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1204 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1206 /* all we care about currently is the change_id */
1208 result = mod_a_printer(*printer, 2);
1209 if (!W_ERROR_IS_OK(result)) {
1210 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1211 dos_errstr(result)));
1215 free_a_printer(&printer, 2);
1222 /********************************************************************
1223 Send a message to ourself about new driver being installed
1224 so we can upgrade the information for each printer bound to this
1226 ********************************************************************/
1228 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1230 int len = strlen(drivername);
1235 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1238 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1243 /**********************************************************************
1244 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1245 over all printers, resetting printer data as neessary
1246 **********************************************************************/
1248 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1252 int n_services = lp_numservices();
1254 len = MIN( len, sizeof(drivername)-1 );
1255 strncpy( drivername, buf, len );
1257 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1259 /* Iterate the printer list */
1261 for ( snum=0; snum<n_services; snum++ )
1263 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1266 NT_PRINTER_INFO_LEVEL *printer = NULL;
1268 result = get_a_printer( &printer, 2, lp_servicename(snum) );
1269 if ( !W_ERROR_IS_OK(result) )
1273 * if the printer is bound to the driver,
1274 * then reset to the new driver initdata
1277 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1279 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1281 if ( !set_driver_init(printer, 2) ) {
1282 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1283 printer->info_2->printername, printer->info_2->drivername));
1286 result = mod_a_printer( *printer, 2 );
1287 if ( !W_ERROR_IS_OK(result) ) {
1288 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1289 get_dos_error_msg(result)));
1293 free_a_printer( &printer, 2 );
1302 /********************************************************************
1303 Copy routines used by convert_to_openprinterex()
1304 *******************************************************************/
1306 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1314 DEBUG (8,("dup_devmode\n"));
1316 /* bulk copy first */
1318 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1322 /* dup the pointer members separately */
1324 len = unistrlen(devmode->devicename.buffer);
1326 d->devicename.buffer = talloc(ctx, len*2);
1327 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1332 len = unistrlen(devmode->formname.buffer);
1334 d->devicename.buffer = talloc(ctx, len*2);
1335 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1339 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1344 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1346 if (!new_ctr || !ctr)
1349 DEBUG(8,("copy_devmode_ctr\n"));
1351 new_ctr->size = ctr->size;
1352 new_ctr->devmode_ptr = ctr->devmode_ptr;
1354 if(ctr->devmode_ptr)
1355 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1358 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1360 if (!new_def || !def)
1363 DEBUG(8,("copy_printer_defaults\n"));
1365 new_def->datatype_ptr = def->datatype_ptr;
1367 if (def->datatype_ptr)
1368 copy_unistr2(&new_def->datatype, &def->datatype);
1370 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1372 new_def->access_required = def->access_required;
1375 /********************************************************************
1376 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1377 * SPOOL_Q_OPEN_PRINTER_EX structure
1378 ********************************************************************/
1380 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1382 if (!q_u_ex || !q_u)
1385 DEBUG(8,("convert_to_openprinterex\n"));
1387 q_u_ex->printername_ptr = q_u->printername_ptr;
1389 if (q_u->printername_ptr)
1390 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1392 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1395 /********************************************************************
1396 * spoolss_open_printer
1398 * called from the spoolss dispatcher
1399 ********************************************************************/
1401 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1403 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1404 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1409 ZERO_STRUCT(q_u_ex);
1410 ZERO_STRUCT(r_u_ex);
1412 /* convert the OpenPrinter() call to OpenPrinterEx() */
1414 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1416 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1418 /* convert back to OpenPrinter() */
1420 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1425 /********************************************************************
1426 * spoolss_open_printer
1428 * If the openprinterex rpc call contains a devmode,
1429 * it's a per-user one. This per-user devmode is derivated
1430 * from the global devmode. Openprinterex() contains a per-user
1431 * devmode for when you do EMF printing and spooling.
1432 * In the EMF case, the NT workstation is only doing half the job
1433 * of rendering the page. The other half is done by running the printer
1434 * driver on the server.
1435 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1436 * The EMF file only contains what is to be printed on the page.
1437 * So in order for the server to know how to print, the NT client sends
1438 * a devicemode attached to the openprinterex call.
1439 * But this devicemode is short lived, it's only valid for the current print job.
1441 * If Samba would have supported EMF spooling, this devicemode would
1442 * have been attached to the handle, to sent it to the driver to correctly
1443 * rasterize the EMF file.
1445 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1446 * we just act as a pass-thru between windows and the printer.
1448 * In order to know that Samba supports only RAW spooling, NT has to call
1449 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1450 * and until NT sends a RAW job, we refuse it.
1452 * But to call getprinter() or startdoc(), you first need a valid handle,
1453 * and to get an handle you have to call openprintex(). Hence why you have
1454 * a devicemode in the openprinterex() call.
1457 * Differences between NT4 and NT 2000.
1460 * On NT4, you only have a global devicemode. This global devicemode can be changed
1461 * by the administrator (or by a user with enough privs). Everytime a user
1462 * wants to print, the devicemode is resetted to the default. In Word, everytime
1463 * you print, the printer's characteristics are always reset to the global devicemode.
1467 * In W2K, there is the notion of per-user devicemode. The first time you use
1468 * a printer, a per-user devicemode is build from the global devicemode.
1469 * If you change your per-user devicemode, it is saved in the registry, under the
1470 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1471 * printer preferences available.
1473 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1474 * on the General Tab of the printer properties windows.
1476 * To change the global devicemode: it's the "Printing Defaults..." button
1477 * on the Advanced Tab of the printer properties window.
1480 ********************************************************************/
1482 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1484 UNISTR2 *printername = NULL;
1485 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1486 POLICY_HND *handle = &r_u->handle;
1490 struct current_user user;
1491 Printer_entry *Printer=NULL;
1493 if (q_u->printername_ptr != 0)
1494 printername = &q_u->printername;
1496 if (printername == NULL)
1497 return WERR_INVALID_PRINTER_NAME;
1499 /* some sanity check because you can open a printer or a print server */
1500 /* aka: \\server\printer or \\server */
1501 unistr2_to_ascii(name, printername, sizeof(name)-1);
1503 DEBUGADD(3,("checking name: %s\n",name));
1505 if (!open_printer_hnd(p, handle, name, 0))
1506 return WERR_INVALID_PRINTER_NAME;
1508 Printer=find_printer_index_by_hnd(p, handle);
1510 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1511 Can't find printer handle we created for printer %s\n", name ));
1512 close_printer_handle(p,handle);
1513 return WERR_INVALID_PRINTER_NAME;
1516 get_current_user(&user, p);
1519 * First case: the user is opening the print server:
1521 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1522 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1524 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1525 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1526 * or if the user is listed in the smb.conf printer admin parameter.
1528 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1529 * client view printer folder, but does not show the MSAPW.
1531 * Note: this test needs code to check access rights here too. Jeremy
1532 * could you look at this?
1534 * Second case: the user is opening a printer:
1535 * NT doesn't let us connect to a printer if the connecting user
1536 * doesn't have print permission.
1539 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1541 /* Printserver handles use global struct... */
1545 /* Map standard access rights to object specific access rights */
1547 se_map_standard(&printer_default->access_required,
1548 &printserver_std_mapping);
1550 /* Deny any object specific bits that don't apply to print
1551 servers (i.e printer and job specific bits) */
1553 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1555 if (printer_default->access_required &
1556 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1557 DEBUG(3, ("access DENIED for non-printserver bits"));
1558 close_printer_handle(p, handle);
1559 return WERR_ACCESS_DENIED;
1562 /* Allow admin access */
1564 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1566 if (!lp_ms_add_printer_wizard()) {
1567 close_printer_handle(p, handle);
1568 return WERR_ACCESS_DENIED;
1571 /* if the user is not root and not a printer admin, then fail */
1574 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
1576 close_printer_handle(p, handle);
1577 return WERR_ACCESS_DENIED;
1580 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1584 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1587 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1588 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1590 /* We fall through to return WERR_OK */
1595 /* NT doesn't let us connect to a printer if the connecting user
1596 doesn't have print permission. */
1598 if (!get_printer_snum(p, handle, &snum))
1601 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1603 /* map an empty access mask to the minimum access mask */
1604 if (printer_default->access_required == 0x0)
1605 printer_default->access_required = PRINTER_ACCESS_USE;
1608 * If we are not serving the printer driver for this printer,
1609 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1610 * will keep NT clients happy --jerry
1613 if (lp_use_client_driver(snum)
1614 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1616 printer_default->access_required = PRINTER_ACCESS_USE;
1619 /* check smb.conf parameters and the the sec_desc */
1621 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1622 DEBUG(3, ("access DENIED for printer open\n"));
1623 close_printer_handle(p, handle);
1624 return WERR_ACCESS_DENIED;
1627 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1628 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1629 close_printer_handle(p, handle);
1630 return WERR_ACCESS_DENIED;
1633 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1634 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1636 printer_default->access_required = PRINTER_ACCESS_USE;
1638 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1639 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1643 Printer->access_granted = printer_default->access_required;
1646 * If the client sent a devmode in the OpenPrinter() call, then
1647 * save it here in case we get a job submission on this handle
1650 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1651 && q_u->printer_default.devmode_cont.devmode_ptr )
1653 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1654 &Printer->nt_devmode );
1660 /****************************************************************************
1661 ****************************************************************************/
1663 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1664 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1670 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1679 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1680 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1686 printer->info_3=NULL;
1687 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1691 printer->info_6=NULL;
1692 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1702 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1703 NT_DEVICEMODE **pp_nt_devmode)
1705 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1708 * Ensure nt_devmode is a valid pointer
1709 * as we will be overwriting it.
1712 if (nt_devmode == NULL) {
1713 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1714 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1718 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1719 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1721 nt_devmode->specversion=devmode->specversion;
1722 nt_devmode->driverversion=devmode->driverversion;
1723 nt_devmode->size=devmode->size;
1724 nt_devmode->fields=devmode->fields;
1725 nt_devmode->orientation=devmode->orientation;
1726 nt_devmode->papersize=devmode->papersize;
1727 nt_devmode->paperlength=devmode->paperlength;
1728 nt_devmode->paperwidth=devmode->paperwidth;
1729 nt_devmode->scale=devmode->scale;
1730 nt_devmode->copies=devmode->copies;
1731 nt_devmode->defaultsource=devmode->defaultsource;
1732 nt_devmode->printquality=devmode->printquality;
1733 nt_devmode->color=devmode->color;
1734 nt_devmode->duplex=devmode->duplex;
1735 nt_devmode->yresolution=devmode->yresolution;
1736 nt_devmode->ttoption=devmode->ttoption;
1737 nt_devmode->collate=devmode->collate;
1739 nt_devmode->logpixels=devmode->logpixels;
1740 nt_devmode->bitsperpel=devmode->bitsperpel;
1741 nt_devmode->pelswidth=devmode->pelswidth;
1742 nt_devmode->pelsheight=devmode->pelsheight;
1743 nt_devmode->displayflags=devmode->displayflags;
1744 nt_devmode->displayfrequency=devmode->displayfrequency;
1745 nt_devmode->icmmethod=devmode->icmmethod;
1746 nt_devmode->icmintent=devmode->icmintent;
1747 nt_devmode->mediatype=devmode->mediatype;
1748 nt_devmode->dithertype=devmode->dithertype;
1749 nt_devmode->reserved1=devmode->reserved1;
1750 nt_devmode->reserved2=devmode->reserved2;
1751 nt_devmode->panningwidth=devmode->panningwidth;
1752 nt_devmode->panningheight=devmode->panningheight;
1755 * Only change private and driverextra if the incoming devmode
1756 * has a new one. JRA.
1759 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1760 SAFE_FREE(nt_devmode->private);
1761 nt_devmode->driverextra=devmode->driverextra;
1762 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1764 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1767 *pp_nt_devmode = nt_devmode;
1772 /********************************************************************
1773 * _spoolss_enddocprinter_internal.
1774 ********************************************************************/
1776 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1778 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1782 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1786 if (!get_printer_snum(p, handle, &snum))
1789 Printer->document_started=False;
1790 print_job_end(snum, Printer->jobid,True);
1791 /* error codes unhandled so far ... */
1796 /********************************************************************
1797 * api_spoolss_closeprinter
1798 ********************************************************************/
1800 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1802 POLICY_HND *handle = &q_u->handle;
1804 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1806 if (Printer && Printer->document_started)
1807 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1809 if (!close_printer_handle(p, handle))
1812 /* clear the returned printer handle. Observed behavior
1813 from Win2k server. Don't think this really matters.
1814 Previous code just copied the value of the closed
1817 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1822 /********************************************************************
1823 * api_spoolss_deleteprinter
1825 ********************************************************************/
1827 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1829 POLICY_HND *handle = &q_u->handle;
1830 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1833 if (Printer && Printer->document_started)
1834 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1836 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1838 result = delete_printer_handle(p, handle);
1840 update_c_setprinter(False);
1845 /*******************************************************************
1846 * static function to lookup the version id corresponding to an
1847 * long architecture string
1848 ******************************************************************/
1850 static int get_version_id (char * arch)
1853 struct table_node archi_table[]= {
1855 {"Windows 4.0", "WIN40", 0 },
1856 {"Windows NT x86", "W32X86", 2 },
1857 {"Windows NT R4000", "W32MIPS", 2 },
1858 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1859 {"Windows NT PowerPC", "W32PPC", 2 },
1863 for (i=0; archi_table[i].long_archi != NULL; i++)
1865 if (strcmp(arch, archi_table[i].long_archi) == 0)
1866 return (archi_table[i].version);
1872 /********************************************************************
1873 * _spoolss_deleteprinterdriver
1874 ********************************************************************/
1876 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1880 NT_PRINTER_DRIVER_INFO_LEVEL info;
1881 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1883 struct current_user user;
1885 WERROR status_win2k = WERR_ACCESS_DENIED;
1887 get_current_user(&user, p);
1889 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1890 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1892 /* check that we have a valid driver name first */
1894 if ((version=get_version_id(arch)) == -1)
1895 return WERR_INVALID_ENVIRONMENT;
1898 ZERO_STRUCT(info_win2k);
1900 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1902 /* try for Win2k driver if "Windows NT x86" */
1904 if ( version == 2 ) {
1906 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1907 status = WERR_UNKNOWN_PRINTER_DRIVER;
1913 if (printer_driver_in_use(info.info_3)) {
1914 status = WERR_PRINTER_DRIVER_IN_USE;
1920 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1922 /* if we get to here, we now have 2 driver info structures to remove */
1923 /* remove the Win2k driver first*/
1925 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1926 free_a_printer_driver( info_win2k, 3 );
1928 /* this should not have failed---if it did, report to client */
1929 if ( !W_ERROR_IS_OK(status_win2k) )
1934 status = delete_printer_driver(info.info_3, &user, version, False);
1936 /* if at least one of the deletes succeeded return OK */
1938 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1942 free_a_printer_driver( info, 3 );
1947 /********************************************************************
1948 * spoolss_deleteprinterdriverex
1949 ********************************************************************/
1951 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1955 NT_PRINTER_DRIVER_INFO_LEVEL info;
1956 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1958 uint32 flags = q_u->delete_flags;
1960 struct current_user user;
1962 WERROR status_win2k = WERR_ACCESS_DENIED;
1964 get_current_user(&user, p);
1966 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1967 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1969 /* check that we have a valid driver name first */
1970 if ((version=get_version_id(arch)) == -1) {
1971 /* this is what NT returns */
1972 return WERR_INVALID_ENVIRONMENT;
1975 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
1976 version = q_u->version;
1979 ZERO_STRUCT(info_win2k);
1981 status = get_a_printer_driver(&info, 3, driver, arch, version);
1983 if ( !W_ERROR_IS_OK(status) )
1986 * if the client asked for a specific version,
1987 * or this is something other than Windows NT x86,
1991 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1994 /* try for Win2k driver if "Windows NT x86" */
1997 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1998 status = WERR_UNKNOWN_PRINTER_DRIVER;
2003 if ( printer_driver_in_use(info.info_3) ) {
2004 status = WERR_PRINTER_DRIVER_IN_USE;
2009 * we have a couple of cases to consider.
2010 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2011 * then the delete should fail if **any** files overlap with
2013 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2014 * non-overlapping files
2015 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2016 * is set, the do not delete any files
2017 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2020 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2022 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2024 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2025 /* no idea of the correct error here */
2026 status = WERR_ACCESS_DENIED;
2031 /* also check for W32X86/3 if necessary; maybe we already have? */
2033 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2034 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2037 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2038 /* no idea of the correct error here */
2039 free_a_printer_driver( info_win2k, 3 );
2040 status = WERR_ACCESS_DENIED;
2044 /* if we get to here, we now have 2 driver info structures to remove */
2045 /* remove the Win2k driver first*/
2047 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2048 free_a_printer_driver( info_win2k, 3 );
2050 /* this should not have failed---if it did, report to client */
2052 if ( !W_ERROR_IS_OK(status_win2k) )
2057 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2059 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2062 free_a_printer_driver( info, 3 );
2068 /****************************************************************************
2069 Internal routine for retreiving printerdata
2070 ***************************************************************************/
2072 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2073 char *key, char *value, uint32 *type, uint8 **data,
2074 uint32 *needed, uint32 in_size )
2076 REGISTRY_VALUE *val;
2079 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2080 return WERR_BADFILE;
2082 *type = regval_type( val );
2084 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2086 size = regval_size( val );
2088 /* copy the min(in_size, len) */
2091 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2092 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2100 DEBUG(5,("get_printer_dataex: copy done\n"));
2105 /****************************************************************************
2106 Internal routine for removing printerdata
2107 ***************************************************************************/
2109 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value )
2111 delete_printer_data( printer->info_2, key, value );
2113 return mod_a_printer(*printer, 2);
2116 /****************************************************************************
2117 Internal routine for storing printerdata
2118 ***************************************************************************/
2120 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value,
2121 uint32 type, uint8 *data, int real_len )
2123 delete_printer_data( printer->info_2, key, value );
2125 add_printer_data( printer->info_2, key, value, type, data, real_len );
2127 return mod_a_printer(*printer, 2);
2130 /********************************************************************
2131 GetPrinterData on a printer server Handle.
2132 ********************************************************************/
2134 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2138 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2140 if (!strcmp(value, "W3SvcInstalled")) {
2142 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2148 if (!strcmp(value, "BeepEnabled")) {
2150 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2152 SIVAL(*data, 0, 0x00);
2157 if (!strcmp(value, "EventLog")) {
2159 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2161 /* formally was 0x1b */
2162 SIVAL(*data, 0, 0x0);
2167 if (!strcmp(value, "NetPopup")) {
2169 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2171 SIVAL(*data, 0, 0x00);
2176 if (!strcmp(value, "MajorVersion")) {
2178 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2180 #ifndef EMULATE_WIN2K_HACK /* JERRY */
2189 if (!strcmp(value, "DefaultSpoolDirectory")) {
2192 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2194 *needed = 2*(strlen(string)+1);
2195 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2197 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2199 /* it's done by hand ready to go on the wire */
2200 for (i=0; i<strlen(string); i++) {
2201 (*data)[2*i]=string[i];
2202 (*data)[2*i+1]='\0';
2207 if (!strcmp(value, "Architecture")) {
2208 pstring string="Windows NT x86";
2210 *needed = 2*(strlen(string)+1);
2211 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2213 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2214 for (i=0; i<strlen(string); i++) {
2215 (*data)[2*i]=string[i];
2216 (*data)[2*i+1]='\0';
2221 return WERR_INVALID_PARAM;
2224 /********************************************************************
2225 * spoolss_getprinterdata
2226 ********************************************************************/
2228 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2230 POLICY_HND *handle = &q_u->handle;
2231 UNISTR2 *valuename = &q_u->valuename;
2232 uint32 in_size = q_u->size;
2233 uint32 *type = &r_u->type;
2234 uint32 *out_size = &r_u->size;
2235 uint8 **data = &r_u->data;
2236 uint32 *needed = &r_u->needed;
2239 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2240 NT_PRINTER_INFO_LEVEL *printer = NULL;
2244 * Reminder: when it's a string, the length is in BYTES
2245 * even if UNICODE is negociated.
2250 *out_size = in_size;
2252 /* in case of problem, return some default values */
2257 DEBUG(4,("_spoolss_getprinterdata\n"));
2260 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2261 status = WERR_BADFID;
2265 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2267 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2268 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2271 if ( !get_printer_snum(p,handle, &snum) ) {
2272 status = WERR_BADFID;
2276 status = get_a_printer(&printer, 2, lp_servicename(snum));
2277 if ( !W_ERROR_IS_OK(status) )
2280 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2283 if (*needed > *out_size)
2284 status = WERR_MORE_DATA;
2287 if ( !W_ERROR_IS_OK(status) )
2289 DEBUG(5, ("error: allocating %d\n", *out_size));
2291 /* reply this param doesn't exist */
2294 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2296 free_a_printer( &printer, 2 );
2305 /* cleanup & exit */
2308 free_a_printer( &printer, 2 );
2313 /*********************************************************
2314 Connect to the client machine.
2315 **********************************************************/
2317 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, const char *remote_machine)
2319 extern pstring global_myname;
2321 ZERO_STRUCTP(the_cli);
2322 if(cli_initialise(the_cli) == NULL) {
2323 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2327 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2328 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2329 cli_shutdown(the_cli);
2333 if (ismyip(the_cli->dest_ip)) {
2334 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2335 cli_shutdown(the_cli);
2339 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2340 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2341 cli_shutdown(the_cli);
2345 if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
2346 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2348 cli_shutdown(the_cli);
2352 the_cli->protocol = PROTOCOL_NT1;
2354 if (!cli_negprot(the_cli)) {
2355 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2356 cli_shutdown(the_cli);
2360 if (the_cli->protocol != PROTOCOL_NT1) {
2361 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2362 cli_shutdown(the_cli);
2367 * Do an anonymous session setup.
2370 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2371 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2372 cli_shutdown(the_cli);
2376 if (!(the_cli->sec_mode & 1)) {
2377 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2378 cli_shutdown(the_cli);
2382 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2383 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2384 cli_shutdown(the_cli);
2389 * Ok - we have an anonymous connection to the IPC$ share.
2390 * Now start the NT Domain stuff :-).
2393 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2394 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)));
2395 cli_nt_session_close(the_cli);
2396 cli_ulogoff(the_cli);
2397 cli_shutdown(the_cli);
2404 /***************************************************************************
2405 Connect to the client.
2406 ****************************************************************************/
2408 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2413 * If it's the first connection, contact the client
2414 * and connect to the IPC$ share anonumously
2416 if (smb_connections==0) {
2417 fstring unix_printer;
2419 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2421 if(!spoolss_connect_to_client(¬ify_cli, unix_printer))
2424 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2425 /* Tell the connections db we're now interested in printer
2426 * notify messages. */
2427 register_message_flags( True, FLAG_MSG_PRINTING );
2431 * Tell the specific printing tdb we want messages for this printer
2432 * by registering our PID.
2435 if (!print_notify_register_pid(snum))
2436 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2440 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2443 if (!W_ERROR_IS_OK(result))
2444 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2445 dos_errstr(result)));
2447 return (W_ERROR_IS_OK(result));
2450 /********************************************************************
2452 * ReplyFindFirstPrinterChangeNotifyEx
2454 * before replying OK: status=0 a rpc call is made to the workstation
2455 * asking ReplyOpenPrinter
2457 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2458 * called from api_spoolss_rffpcnex
2459 ********************************************************************/
2461 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2463 POLICY_HND *handle = &q_u->handle;
2464 uint32 flags = q_u->flags;
2465 uint32 options = q_u->options;
2466 UNISTR2 *localmachine = &q_u->localmachine;
2467 uint32 printerlocal = q_u->printerlocal;
2469 SPOOL_NOTIFY_OPTION *option = q_u->option;
2471 /* store the notify value in the printer struct */
2473 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2476 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2480 if (!get_printer_snum(p, handle, &snum))
2483 Printer->notify.flags=flags;
2484 Printer->notify.options=options;
2485 Printer->notify.printerlocal=printerlocal;
2487 if (Printer->notify.option)
2488 free_spool_notify_option(&Printer->notify.option);
2490 Printer->notify.option=dup_spool_notify_option(option);
2492 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2493 sizeof(Printer->notify.localmachine)-1);
2495 /* Connect to the client machine and send a ReplyOpenPrinter */
2497 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2498 Printer->notify.printerlocal, 1,
2499 &Printer->notify.client_hnd))
2500 return WERR_SERVER_UNAVAILABLE;
2502 Printer->notify.client_connected=True;
2507 /*******************************************************************
2508 * fill a notify_info_data with the servername
2509 ********************************************************************/
2511 void spoolss_notify_server_name(int snum,
2512 SPOOL_NOTIFY_INFO_DATA *data,
2513 print_queue_struct *queue,
2514 NT_PRINTER_INFO_LEVEL *printer,
2515 TALLOC_CTX *mem_ctx)
2517 pstring temp_name, temp;
2520 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2522 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2524 data->notify_data.data.length = len;
2525 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2527 if (!data->notify_data.data.string) {
2528 data->notify_data.data.length = 0;
2532 memcpy(data->notify_data.data.string, temp, len);
2535 /*******************************************************************
2536 * fill a notify_info_data with the printername (not including the servername).
2537 ********************************************************************/
2539 void spoolss_notify_printer_name(int snum,
2540 SPOOL_NOTIFY_INFO_DATA *data,
2541 print_queue_struct *queue,
2542 NT_PRINTER_INFO_LEVEL *printer,
2543 TALLOC_CTX *mem_ctx)
2548 /* the notify name should not contain the \\server\ part */
2549 char *p = strrchr(printer->info_2->printername, '\\');
2552 p = printer->info_2->printername;
2557 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2559 data->notify_data.data.length = len;
2560 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2562 if (!data->notify_data.data.string) {
2563 data->notify_data.data.length = 0;
2567 memcpy(data->notify_data.data.string, temp, len);
2570 /*******************************************************************
2571 * fill a notify_info_data with the servicename
2572 ********************************************************************/
2574 void spoolss_notify_share_name(int snum,
2575 SPOOL_NOTIFY_INFO_DATA *data,
2576 print_queue_struct *queue,
2577 NT_PRINTER_INFO_LEVEL *printer,
2578 TALLOC_CTX *mem_ctx)
2583 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2585 data->notify_data.data.length = len;
2586 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2588 if (!data->notify_data.data.string) {
2589 data->notify_data.data.length = 0;
2593 memcpy(data->notify_data.data.string, temp, len);
2596 /*******************************************************************
2597 * fill a notify_info_data with the port name
2598 ********************************************************************/
2600 void spoolss_notify_port_name(int snum,
2601 SPOOL_NOTIFY_INFO_DATA *data,
2602 print_queue_struct *queue,
2603 NT_PRINTER_INFO_LEVEL *printer,
2604 TALLOC_CTX *mem_ctx)
2609 /* even if it's strange, that's consistant in all the code */
2611 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2613 data->notify_data.data.length = len;
2614 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2616 if (!data->notify_data.data.string) {
2617 data->notify_data.data.length = 0;
2621 memcpy(data->notify_data.data.string, temp, len);
2624 /*******************************************************************
2625 * fill a notify_info_data with the printername
2626 * but it doesn't exist, have to see what to do
2627 ********************************************************************/
2629 void spoolss_notify_driver_name(int snum,
2630 SPOOL_NOTIFY_INFO_DATA *data,
2631 print_queue_struct *queue,
2632 NT_PRINTER_INFO_LEVEL *printer,
2633 TALLOC_CTX *mem_ctx)
2638 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2640 data->notify_data.data.length = len;
2641 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2643 if (!data->notify_data.data.string) {
2644 data->notify_data.data.length = 0;
2648 memcpy(data->notify_data.data.string, temp, len);
2651 /*******************************************************************
2652 * fill a notify_info_data with the comment
2653 ********************************************************************/
2655 void spoolss_notify_comment(int snum,
2656 SPOOL_NOTIFY_INFO_DATA *data,
2657 print_queue_struct *queue,
2658 NT_PRINTER_INFO_LEVEL *printer,
2659 TALLOC_CTX *mem_ctx)
2664 if (*printer->info_2->comment == '\0')
2665 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2667 len = rpcstr_push(temp, printer->info_2->comment, 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 comment
2682 * location = "Room 1, floor 2, building 3"
2683 ********************************************************************/
2685 void spoolss_notify_location(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->location,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 device mode
2709 * jfm:xxxx don't to it for know but that's a real problem !!!
2710 ********************************************************************/
2712 static void spoolss_notify_devmode(int snum,
2713 SPOOL_NOTIFY_INFO_DATA *data,
2714 print_queue_struct *queue,
2715 NT_PRINTER_INFO_LEVEL *printer,
2716 TALLOC_CTX *mem_ctx)
2720 /*******************************************************************
2721 * fill a notify_info_data with the separator file name
2722 ********************************************************************/
2724 void spoolss_notify_sepfile(int snum,
2725 SPOOL_NOTIFY_INFO_DATA *data,
2726 print_queue_struct *queue,
2727 NT_PRINTER_INFO_LEVEL *printer,
2728 TALLOC_CTX *mem_ctx)
2733 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2735 data->notify_data.data.length = len;
2736 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2738 if (!data->notify_data.data.string) {
2739 data->notify_data.data.length = 0;
2743 memcpy(data->notify_data.data.string, temp, len);
2746 /*******************************************************************
2747 * fill a notify_info_data with the print processor
2748 * jfm:xxxx return always winprint to indicate we don't do anything to it
2749 ********************************************************************/
2751 void spoolss_notify_print_processor(int snum,
2752 SPOOL_NOTIFY_INFO_DATA *data,
2753 print_queue_struct *queue,
2754 NT_PRINTER_INFO_LEVEL *printer,
2755 TALLOC_CTX *mem_ctx)
2760 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2762 data->notify_data.data.length = len;
2763 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2765 if (!data->notify_data.data.string) {
2766 data->notify_data.data.length = 0;
2770 memcpy(data->notify_data.data.string, temp, len);
2773 /*******************************************************************
2774 * fill a notify_info_data with the print processor options
2775 * jfm:xxxx send an empty string
2776 ********************************************************************/
2778 void spoolss_notify_parameters(int snum,
2779 SPOOL_NOTIFY_INFO_DATA *data,
2780 print_queue_struct *queue,
2781 NT_PRINTER_INFO_LEVEL *printer,
2782 TALLOC_CTX *mem_ctx)
2787 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2789 data->notify_data.data.length = len;
2790 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2792 if (!data->notify_data.data.string) {
2793 data->notify_data.data.length = 0;
2797 memcpy(data->notify_data.data.string, temp, len);
2800 /*******************************************************************
2801 * fill a notify_info_data with the data type
2802 * jfm:xxxx always send RAW as data type
2803 ********************************************************************/
2805 void spoolss_notify_datatype(int snum,
2806 SPOOL_NOTIFY_INFO_DATA *data,
2807 print_queue_struct *queue,
2808 NT_PRINTER_INFO_LEVEL *printer,
2809 TALLOC_CTX *mem_ctx)
2814 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2816 data->notify_data.data.length = len;
2817 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2819 if (!data->notify_data.data.string) {
2820 data->notify_data.data.length = 0;
2824 memcpy(data->notify_data.data.string, temp, len);
2827 /*******************************************************************
2828 * fill a notify_info_data with the security descriptor
2829 * jfm:xxxx send an null pointer to say no security desc
2830 * have to implement security before !
2831 ********************************************************************/
2833 static void spoolss_notify_security_desc(int snum,
2834 SPOOL_NOTIFY_INFO_DATA *data,
2835 print_queue_struct *queue,
2836 NT_PRINTER_INFO_LEVEL *printer,
2837 TALLOC_CTX *mem_ctx)
2839 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2840 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2843 /*******************************************************************
2844 * fill a notify_info_data with the attributes
2845 * jfm:xxxx a samba printer is always shared
2846 ********************************************************************/
2848 void spoolss_notify_attributes(int snum,
2849 SPOOL_NOTIFY_INFO_DATA *data,
2850 print_queue_struct *queue,
2851 NT_PRINTER_INFO_LEVEL *printer,
2852 TALLOC_CTX *mem_ctx)
2854 data->notify_data.value[0] = printer->info_2->attributes;
2855 data->notify_data.value[1] = 0;
2858 /*******************************************************************
2859 * fill a notify_info_data with the priority
2860 ********************************************************************/
2862 static void spoolss_notify_priority(int snum,
2863 SPOOL_NOTIFY_INFO_DATA *data,
2864 print_queue_struct *queue,
2865 NT_PRINTER_INFO_LEVEL *printer,
2866 TALLOC_CTX *mem_ctx)
2868 data->notify_data.value[0] = printer->info_2->priority;
2869 data->notify_data.value[1] = 0;
2872 /*******************************************************************
2873 * fill a notify_info_data with the default priority
2874 ********************************************************************/
2876 static void spoolss_notify_default_priority(int snum,
2877 SPOOL_NOTIFY_INFO_DATA *data,
2878 print_queue_struct *queue,
2879 NT_PRINTER_INFO_LEVEL *printer,
2880 TALLOC_CTX *mem_ctx)
2882 data->notify_data.value[0] = printer->info_2->default_priority;
2883 data->notify_data.value[1] = 0;
2886 /*******************************************************************
2887 * fill a notify_info_data with the start time
2888 ********************************************************************/
2890 static void spoolss_notify_start_time(int snum,
2891 SPOOL_NOTIFY_INFO_DATA *data,
2892 print_queue_struct *queue,
2893 NT_PRINTER_INFO_LEVEL *printer,
2894 TALLOC_CTX *mem_ctx)
2896 data->notify_data.value[0] = printer->info_2->starttime;
2897 data->notify_data.value[1] = 0;
2900 /*******************************************************************
2901 * fill a notify_info_data with the until time
2902 ********************************************************************/
2904 static void spoolss_notify_until_time(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->untiltime;
2911 data->notify_data.value[1] = 0;
2914 /*******************************************************************
2915 * fill a notify_info_data with the status
2916 ********************************************************************/
2918 static void spoolss_notify_status(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 print_status_struct status;
2926 print_queue_length(snum, &status);
2927 data->notify_data.value[0]=(uint32) status.status;
2928 data->notify_data.value[1] = 0;
2931 /*******************************************************************
2932 * fill a notify_info_data with the number of jobs queued
2933 ********************************************************************/
2935 void spoolss_notify_cjobs(int snum,
2936 SPOOL_NOTIFY_INFO_DATA *data,
2937 print_queue_struct *queue,
2938 NT_PRINTER_INFO_LEVEL *printer,
2939 TALLOC_CTX *mem_ctx)
2941 data->notify_data.value[0] = print_queue_length(snum, NULL);
2942 data->notify_data.value[1] = 0;
2945 /*******************************************************************
2946 * fill a notify_info_data with the average ppm
2947 ********************************************************************/
2949 static void spoolss_notify_average_ppm(int snum,
2950 SPOOL_NOTIFY_INFO_DATA *data,
2951 print_queue_struct *queue,
2952 NT_PRINTER_INFO_LEVEL *printer,
2953 TALLOC_CTX *mem_ctx)
2955 /* always respond 8 pages per minutes */
2956 /* a little hard ! */
2957 data->notify_data.value[0] = printer->info_2->averageppm;
2958 data->notify_data.value[1] = 0;
2961 /*******************************************************************
2962 * fill a notify_info_data with username
2963 ********************************************************************/
2965 static void spoolss_notify_username(int snum,
2966 SPOOL_NOTIFY_INFO_DATA *data,
2967 print_queue_struct *queue,
2968 NT_PRINTER_INFO_LEVEL *printer,
2969 TALLOC_CTX *mem_ctx)
2974 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2976 data->notify_data.data.length = len;
2977 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2979 if (!data->notify_data.data.string) {
2980 data->notify_data.data.length = 0;
2984 memcpy(data->notify_data.data.string, temp, len);
2987 /*******************************************************************
2988 * fill a notify_info_data with job status
2989 ********************************************************************/
2991 static void spoolss_notify_job_status(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]=nt_printj_status(queue->status);
2998 data->notify_data.value[1] = 0;
3001 /*******************************************************************
3002 * fill a notify_info_data with job name
3003 ********************************************************************/
3005 static void spoolss_notify_job_name(int snum,
3006 SPOOL_NOTIFY_INFO_DATA *data,
3007 print_queue_struct *queue,
3008 NT_PRINTER_INFO_LEVEL *printer,
3009 TALLOC_CTX *mem_ctx)
3014 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3016 data->notify_data.data.length = len;
3017 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3019 if (!data->notify_data.data.string) {
3020 data->notify_data.data.length = 0;
3024 memcpy(data->notify_data.data.string, temp, len);
3027 /*******************************************************************
3028 * fill a notify_info_data with job status
3029 ********************************************************************/
3031 static void spoolss_notify_job_status_string(int snum,
3032 SPOOL_NOTIFY_INFO_DATA *data,
3033 print_queue_struct *queue,
3034 NT_PRINTER_INFO_LEVEL *printer,
3035 TALLOC_CTX *mem_ctx)
3038 * Now we're returning job status codes we just return a "" here. JRA.
3045 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3048 switch (queue->status) {
3053 p = ""; /* NT provides the paused string */
3062 #endif /* NO LONGER NEEDED. */
3064 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3066 data->notify_data.data.length = len;
3067 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3069 if (!data->notify_data.data.string) {
3070 data->notify_data.data.length = 0;
3074 memcpy(data->notify_data.data.string, temp, len);
3077 /*******************************************************************
3078 * fill a notify_info_data with job time
3079 ********************************************************************/
3081 static void spoolss_notify_job_time(int snum,
3082 SPOOL_NOTIFY_INFO_DATA *data,
3083 print_queue_struct *queue,
3084 NT_PRINTER_INFO_LEVEL *printer,
3085 TALLOC_CTX *mem_ctx)
3087 data->notify_data.value[0]=0x0;
3088 data->notify_data.value[1]=0;
3091 /*******************************************************************
3092 * fill a notify_info_data with job size
3093 ********************************************************************/
3095 static void spoolss_notify_job_size(int snum,
3096 SPOOL_NOTIFY_INFO_DATA *data,
3097 print_queue_struct *queue,
3098 NT_PRINTER_INFO_LEVEL *printer,
3099 TALLOC_CTX *mem_ctx)
3101 data->notify_data.value[0]=queue->size;
3102 data->notify_data.value[1]=0;
3105 /*******************************************************************
3106 * fill a notify_info_data with page info
3107 ********************************************************************/
3108 static void spoolss_notify_total_pages(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 data->notify_data.value[0]=queue->page_count;
3115 data->notify_data.value[1]=0;
3118 /*******************************************************************
3119 * fill a notify_info_data with pages printed info.
3120 ********************************************************************/
3121 static void spoolss_notify_pages_printed(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3127 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3128 data->notify_data.value[1]=0;
3131 /*******************************************************************
3132 Fill a notify_info_data with job position.
3133 ********************************************************************/
3135 static void spoolss_notify_job_position(int snum,
3136 SPOOL_NOTIFY_INFO_DATA *data,
3137 print_queue_struct *queue,
3138 NT_PRINTER_INFO_LEVEL *printer,
3139 TALLOC_CTX *mem_ctx)
3141 data->notify_data.value[0]=queue->job;
3142 data->notify_data.value[1]=0;
3145 /*******************************************************************
3146 Fill a notify_info_data with submitted time.
3147 ********************************************************************/
3149 static void spoolss_notify_submitted_time(int snum,
3150 SPOOL_NOTIFY_INFO_DATA *data,
3151 print_queue_struct *queue,
3152 NT_PRINTER_INFO_LEVEL *printer,
3153 TALLOC_CTX *mem_ctx)
3160 t=gmtime(&queue->time);
3162 len = sizeof(SYSTEMTIME);
3164 data->notify_data.data.length = len;
3165 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3167 if (!data->notify_data.data.string) {
3168 data->notify_data.data.length = 0;
3172 make_systemtime(&st, t);
3175 * Systemtime must be linearized as a set of UINT16's.
3176 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3179 p = (char *)data->notify_data.data.string;
3180 SSVAL(p, 0, st.year);
3181 SSVAL(p, 2, st.month);
3182 SSVAL(p, 4, st.dayofweek);
3183 SSVAL(p, 6, st.day);
3184 SSVAL(p, 8, st.hour);
3185 SSVAL(p, 10, st.minute);
3186 SSVAL(p, 12, st.second);
3187 SSVAL(p, 14, st.milliseconds);
3190 struct s_notify_info_data_table
3196 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3197 print_queue_struct *queue,
3198 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3201 /* A table describing the various print notification constants and
3202 whether the notification data is a pointer to a variable sized
3203 buffer, a one value uint32 or a two value uint32. */
3205 struct s_notify_info_data_table notify_info_data_table[] =
3207 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3208 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3209 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3210 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3211 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3212 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3213 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3214 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3215 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3216 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3217 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3218 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3219 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3220 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3221 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3222 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3223 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3224 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3225 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3226 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3227 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3228 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3229 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3230 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3231 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3232 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3233 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3234 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3235 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3236 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3237 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3238 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3239 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3240 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3241 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3242 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3243 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3244 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3245 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3246 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3247 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3248 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3249 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3250 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3251 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3252 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3253 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3254 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3255 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3258 /*******************************************************************
3259 Return the size of info_data structure.
3260 ********************************************************************/
3262 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3266 for (i = 0; i < sizeof(notify_info_data_table); i++)
3268 if ( (notify_info_data_table[i].type == type)
3269 && (notify_info_data_table[i].field == field) )
3271 switch(notify_info_data_table[i].size)
3273 case NOTIFY_ONE_VALUE:
3274 case NOTIFY_TWO_VALUE:
3279 /* The only pointer notify data I have seen on
3280 the wire is the submitted time and this has
3281 the notify size set to 4. -tpot */
3283 case NOTIFY_POINTER:
3286 case NOTIFY_SECDESC:
3292 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3297 /*******************************************************************
3298 Return the type of notify_info_data.
3299 ********************************************************************/
3301 static int type_of_notify_info_data(uint16 type, uint16 field)
3305 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3306 if (notify_info_data_table[i].type == type &&
3307 notify_info_data_table[i].field == field)
3308 return notify_info_data_table[i].size;
3314 /****************************************************************************
3315 ****************************************************************************/
3317 static int search_notify(uint16 type, uint16 field, int *value)
3321 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3322 if (notify_info_data_table[i].type == type &&
3323 notify_info_data_table[i].field == field &&
3324 notify_info_data_table[i].fn != NULL) {
3333 /****************************************************************************
3334 ****************************************************************************/
3336 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3338 info_data->type = type;
3339 info_data->field = field;
3340 info_data->reserved = 0;
3342 info_data->size = size_of_notify_info_data(type, field);
3343 info_data->enc_type = type_of_notify_info_data(type, field);
3350 /*******************************************************************
3352 * fill a notify_info struct with info asked
3354 ********************************************************************/
3356 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
3357 snum, SPOOL_NOTIFY_OPTION_TYPE
3358 *option_type, uint32 id,
3359 TALLOC_CTX *mem_ctx)
3365 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3366 NT_PRINTER_INFO_LEVEL *printer = NULL;
3367 print_queue_struct *queue=NULL;
3369 type=option_type->type;
3371 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3372 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3373 option_type->count, lp_servicename(snum)));
3375 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3378 for(field_num=0; field_num<option_type->count; field_num++)
3380 field = option_type->fields[field_num];
3382 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3384 if (!search_notify(type, field, &j) )
3387 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
3389 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3395 current_data = &info->data[info->count];
3397 construct_info_data(current_data, type, field, id);
3399 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3400 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3402 notify_info_data_table[j].fn(snum, current_data, queue,
3408 free_a_printer(&printer, 2);
3412 /*******************************************************************
3414 * fill a notify_info struct with info asked
3416 ********************************************************************/
3418 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3419 SPOOL_NOTIFY_INFO *info,
3420 NT_PRINTER_INFO_LEVEL *printer,
3421 int snum, SPOOL_NOTIFY_OPTION_TYPE
3422 *option_type, uint32 id,
3423 TALLOC_CTX *mem_ctx)
3429 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3431 DEBUG(4,("construct_notify_jobs_info\n"));
3433 type = option_type->type;
3435 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3436 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3437 option_type->count));
3439 for(field_num=0; field_num<option_type->count; field_num++) {
3440 field = option_type->fields[field_num];
3442 if (!search_notify(type, field, &j) )
3445 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3446 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3449 else info->data = tid;
3451 current_data=&(info->data[info->count]);
3453 construct_info_data(current_data, type, field, id);
3454 notify_info_data_table[j].fn(snum, current_data, queue,
3463 * JFM: The enumeration is not that simple, it's even non obvious.
3465 * let's take an example: I want to monitor the PRINTER SERVER for
3466 * the printer's name and the number of jobs currently queued.
3467 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3468 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3470 * I have 3 printers on the back of my server.
3472 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3475 * 1 printer 1 name 1
3476 * 2 printer 1 cjob 1
3477 * 3 printer 2 name 2
3478 * 4 printer 2 cjob 2
3479 * 5 printer 3 name 3
3480 * 6 printer 3 name 3
3482 * that's the print server case, the printer case is even worse.
3485 /*******************************************************************
3487 * enumerate all printers on the printserver
3488 * fill a notify_info struct with info asked
3490 ********************************************************************/
3492 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3493 SPOOL_NOTIFY_INFO *info,
3494 TALLOC_CTX *mem_ctx)
3497 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3498 int n_services=lp_numservices();
3501 SPOOL_NOTIFY_OPTION *option;
3502 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3504 DEBUG(4,("printserver_notify_info\n"));
3509 option=Printer->notify.option;
3515 for (i=0; i<option->count; i++) {
3516 option_type=&(option->ctr.type[i]);
3518 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3521 for (snum=0; snum<n_services; snum++)
3523 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3524 construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
3530 * Debugging information, don't delete.
3533 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3534 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3535 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3537 for (i=0; i<info->count; i++) {
3538 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3539 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3540 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3547 /*******************************************************************
3549 * fill a notify_info struct with info asked
3551 ********************************************************************/
3553 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3554 TALLOC_CTX *mem_ctx)
3557 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3560 SPOOL_NOTIFY_OPTION *option;
3561 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3563 print_queue_struct *queue=NULL;
3564 print_status_struct status;
3566 DEBUG(4,("printer_notify_info\n"));
3571 option=Printer->notify.option;
3577 get_printer_snum(p, hnd, &snum);
3579 for (i=0; i<option->count; i++) {
3580 option_type=&option->ctr.type[i];
3582 switch ( option_type->type ) {
3583 case PRINTER_NOTIFY_TYPE:
3584 if(construct_notify_printer_info(info, snum,
3590 case JOB_NOTIFY_TYPE: {
3591 NT_PRINTER_INFO_LEVEL *printer = NULL;
3593 count = print_queue_status(snum, &queue, &status);
3595 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3596 lp_servicename(snum))))
3599 for (j=0; j<count; j++) {
3600 construct_notify_jobs_info(&queue[j], info,
3607 free_a_printer(&printer, 2);
3617 * Debugging information, don't delete.
3620 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3621 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3622 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3624 for (i=0; i<info->count; i++) {
3625 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3626 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3627 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3633 /********************************************************************
3635 ********************************************************************/
3637 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3639 POLICY_HND *handle = &q_u->handle;
3640 SPOOL_NOTIFY_INFO *info = &r_u->info;
3642 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3643 WERROR result = WERR_BADFID;
3645 /* we always have a NOTIFY_INFO struct */
3649 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3650 OUR_HANDLE(handle)));
3654 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3657 * We are now using the change value, and
3658 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3659 * I don't have a global notification system, I'm sending back all the
3660 * informations even when _NOTHING_ has changed.
3663 /* We need to keep track of the change value to send back in
3664 RRPCN replies otherwise our updates are ignored. */
3666 if (Printer->notify.client_connected) {
3667 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3668 Printer->notify.change = q_u->change;
3671 /* just ignore the SPOOL_NOTIFY_OPTION */
3673 switch (Printer->printer_type) {
3674 case PRINTER_HANDLE_IS_PRINTSERVER:
3675 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3678 case PRINTER_HANDLE_IS_PRINTER:
3679 result = printer_notify_info(p, handle, info, p->mem_ctx);
3687 /********************************************************************
3688 * construct_printer_info_0
3689 * fill a printer_info_0 struct
3690 ********************************************************************/
3692 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3696 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3697 counter_printer_0 *session_counter;
3698 uint32 global_counter;
3701 print_status_struct status;
3703 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3706 count = print_queue_length(snum, &status);
3708 /* check if we already have a counter for this printer */
3709 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3711 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3712 if (session_counter->snum == snum)
3716 /* it's the first time, add it to the list */
3717 if (session_counter==NULL) {
3718 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3719 free_a_printer(&ntprinter, 2);
3722 ZERO_STRUCTP(session_counter);
3723 session_counter->snum=snum;
3724 session_counter->counter=0;
3725 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3729 session_counter->counter++;
3732 * the global_counter should be stored in a TDB as it's common to all the clients
3733 * and should be zeroed on samba startup
3735 global_counter=session_counter->counter;
3737 pstrcpy(chaine,ntprinter->info_2->printername);
3739 init_unistr(&printer->printername, chaine);
3741 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3742 init_unistr(&printer->servername, chaine);
3744 printer->cjobs = count;
3745 printer->total_jobs = 0;
3746 printer->total_bytes = 0;
3748 setuptime = (time_t)ntprinter->info_2->setuptime;
3749 t=gmtime(&setuptime);
3751 printer->year = t->tm_year+1900;
3752 printer->month = t->tm_mon+1;
3753 printer->dayofweek = t->tm_wday;
3754 printer->day = t->tm_mday;
3755 printer->hour = t->tm_hour;
3756 printer->minute = t->tm_min;
3757 printer->second = t->tm_sec;
3758 printer->milliseconds = 0;
3760 printer->global_counter = global_counter;
3761 printer->total_pages = 0;
3762 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3763 printer->major_version = 0x0004; /* NT 4 */
3764 printer->build_version = 0x0565; /* build 1381 */
3766 printer->major_version = 0x0005; /* NT 5 */
3767 printer->build_version = 0x0893; /* build 2195 */
3769 printer->unknown7 = 0x1;
3770 printer->unknown8 = 0x0;
3771 printer->unknown9 = 0x0;
3772 printer->session_counter = session_counter->counter;
3773 printer->unknown11 = 0x0;
3774 printer->printer_errors = 0x0; /* number of print failure */
3775 printer->unknown13 = 0x0;
3776 printer->unknown14 = 0x1;
3777 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3778 printer->unknown16 = 0x0;
3779 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3780 printer->unknown18 = 0x0;
3781 printer->status = nt_printq_status(status.status);
3782 printer->unknown20 = 0x0;
3783 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3784 printer->unknown22 = 0x0;
3785 printer->unknown23 = 0x6; /* 6 ???*/
3786 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3787 printer->unknown25 = 0;
3788 printer->unknown26 = 0;
3789 printer->unknown27 = 0;
3790 printer->unknown28 = 0;
3791 printer->unknown29 = 0;
3793 free_a_printer(&ntprinter,2);
3797 /********************************************************************
3798 * construct_printer_info_1
3799 * fill a printer_info_1 struct
3800 ********************************************************************/
3801 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3805 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3807 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3810 printer->flags=flags;
3812 if (*ntprinter->info_2->comment == '\0') {
3813 init_unistr(&printer->comment, lp_comment(snum));
3814 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3815 ntprinter->info_2->drivername, lp_comment(snum));
3818 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3819 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3820 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3823 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3825 init_unistr(&printer->description, chaine);
3826 init_unistr(&printer->name, chaine2);
3828 free_a_printer(&ntprinter,2);
3833 /****************************************************************************
3834 Free a DEVMODE struct.
3835 ****************************************************************************/
3837 static void free_dev_mode(DEVICEMODE *dev)
3842 SAFE_FREE(dev->private);
3847 /****************************************************************************
3848 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3849 should be valid upon entry
3850 ****************************************************************************/
3852 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
3854 if ( !devmode || !ntdevmode )
3857 init_unistr(&devmode->devicename, ntdevmode->devicename);
3859 init_unistr(&devmode->formname, ntdevmode->formname);
3861 devmode->specversion = ntdevmode->specversion;
3862 devmode->driverversion = ntdevmode->driverversion;
3863 devmode->size = ntdevmode->size;
3864 devmode->driverextra = ntdevmode->driverextra;
3865 devmode->fields = ntdevmode->fields;
3867 devmode->orientation = ntdevmode->orientation;
3868 devmode->papersize = ntdevmode->papersize;
3869 devmode->paperlength = ntdevmode->paperlength;
3870 devmode->paperwidth = ntdevmode->paperwidth;
3871 devmode->scale = ntdevmode->scale;
3872 devmode->copies = ntdevmode->copies;
3873 devmode->defaultsource = ntdevmode->defaultsource;
3874 devmode->printquality = ntdevmode->printquality;
3875 devmode->color = ntdevmode->color;
3876 devmode->duplex = ntdevmode->duplex;
3877 devmode->yresolution = ntdevmode->yresolution;
3878 devmode->ttoption = ntdevmode->ttoption;
3879 devmode->collate = ntdevmode->collate;
3880 devmode->icmmethod = ntdevmode->icmmethod;
3881 devmode->icmintent = ntdevmode->icmintent;
3882 devmode->mediatype = ntdevmode->mediatype;
3883 devmode->dithertype = ntdevmode->dithertype;
3885 if (ntdevmode->private != NULL) {
3886 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3893 /****************************************************************************
3894 Create a DEVMODE struct. Returns malloced memory.
3895 ****************************************************************************/
3897 DEVICEMODE *construct_dev_mode(int snum)
3899 NT_PRINTER_INFO_LEVEL *printer = NULL;
3900 DEVICEMODE *devmode = NULL;
3902 DEBUG(7,("construct_dev_mode\n"));
3904 DEBUGADD(8,("getting printer characteristics\n"));
3906 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3909 if ( !printer->info_2->devmode ) {
3910 DEBUG(5, ("BONG! There was no device mode!\n"));
3914 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3915 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3919 ZERO_STRUCTP(devmode);
3921 DEBUGADD(8,("loading DEVICEMODE\n"));
3923 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
3924 free_dev_mode( devmode );
3929 free_a_printer(&printer,2);
3934 /********************************************************************
3935 * construct_printer_info_2
3936 * fill a printer_info_2 struct
3937 ********************************************************************/
3939 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3942 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3944 print_status_struct status;
3946 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3949 count = print_queue_length(snum, &status);
3951 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3952 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3953 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3954 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3955 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3957 if (*ntprinter->info_2->comment == '\0')
3958 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3960 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3962 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3963 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3964 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3965 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3966 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3968 printer->attributes = ntprinter->info_2->attributes;
3970 printer->priority = ntprinter->info_2->priority; /* priority */
3971 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3972 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3973 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3974 printer->status = nt_printq_status(status.status); /* status */
3975 printer->cjobs = count; /* jobs */
3976 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3978 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3979 DEBUG(8, ("Returning NULL Devicemode!\n"));
3982 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3983 /* steal the printer info sec_desc structure. [badly done]. */
3984 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3985 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3986 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3987 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3990 printer->secdesc = NULL;
3993 free_a_printer(&ntprinter, 2);
3997 /********************************************************************
3998 * construct_printer_info_3
3999 * fill a printer_info_3 struct
4000 ********************************************************************/
4002 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
4004 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4005 PRINTER_INFO_3 *printer = NULL;
4007 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4011 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4012 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4016 ZERO_STRUCTP(printer);
4018 printer->flags = 4; /* These are the components of the SD we are returning. */
4019 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4020 /* steal the printer info sec_desc structure. [badly done]. */
4021 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4025 * Set the flags for the components we are returning.
4028 if (printer->secdesc->owner_sid)
4029 printer->flags |= OWNER_SECURITY_INFORMATION;
4031 if (printer->secdesc->grp_sid)
4032 printer->flags |= GROUP_SECURITY_INFORMATION;
4034 if (printer->secdesc->dacl)
4035 printer->flags |= DACL_SECURITY_INFORMATION;
4037 if (printer->secdesc->sacl)
4038 printer->flags |= SACL_SECURITY_INFORMATION;
4041 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4042 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4043 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4046 free_a_printer(&ntprinter, 2);
4048 *pp_printer = printer;
4052 /********************************************************************
4053 * construct_printer_info_4
4054 * fill a printer_info_4 struct
4055 ********************************************************************/
4057 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
4059 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4061 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4064 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4065 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4066 printer->attributes = ntprinter->info_2->attributes;
4068 free_a_printer(&ntprinter, 2);
4072 /********************************************************************
4073 * construct_printer_info_5
4074 * fill a printer_info_5 struct
4075 ********************************************************************/
4077 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
4079 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4081 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4084 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4085 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
4086 printer->attributes = ntprinter->info_2->attributes;
4087 printer->device_not_selected_timeout = 0x3a98;
4088 printer->transmission_retry_timeout = 0xafc8;
4090 free_a_printer(&ntprinter, 2);
4094 /********************************************************************
4095 Spoolss_enumprinters.
4096 ********************************************************************/
4098 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4102 int n_services=lp_numservices();
4103 PRINTER_INFO_1 *tp, *printers=NULL;
4104 PRINTER_INFO_1 current_prt;
4106 DEBUG(4,("enum_all_printers_info_1\n"));
4108 for (snum=0; snum<n_services; snum++) {
4109 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4110 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4112 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
4113 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4114 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4115 SAFE_FREE(printers);
4120 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4122 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4128 /* check the required size. */
4129 for (i=0; i<*returned; i++)
4130 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4132 if (!alloc_buffer_size(buffer, *needed))
4133 return WERR_INSUFFICIENT_BUFFER;
4135 /* fill the buffer with the structures */
4136 for (i=0; i<*returned; i++)
4137 smb_io_printer_info_1("", buffer, &printers[i], 0);
4140 SAFE_FREE(printers);
4142 if (*needed > offered) {
4144 return WERR_INSUFFICIENT_BUFFER;
4150 /********************************************************************
4151 enum_all_printers_info_1_local.
4152 *********************************************************************/
4154 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4156 DEBUG(4,("enum_all_printers_info_1_local\n"));
4158 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4161 /********************************************************************
4162 enum_all_printers_info_1_name.
4163 *********************************************************************/
4165 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4169 DEBUG(4,("enum_all_printers_info_1_name\n"));
4171 if ((name[0] == '\\') && (name[1] == '\\'))
4174 if (is_myname_or_ipaddr(s)) {
4175 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4178 return WERR_INVALID_NAME;
4181 /********************************************************************
4182 enum_all_printers_info_1_remote.
4183 *********************************************************************/
4185 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4187 PRINTER_INFO_1 *printer;
4188 fstring printername;
4191 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4193 /* JFM: currently it's more a place holder than anything else.
4194 * In the spooler world there is a notion of server registration.
4195 * the print servers are registring (sp ?) on the PDC (in the same domain)
4197 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4200 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4205 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4206 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4207 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4209 init_unistr(&printer->description, desc);
4210 init_unistr(&printer->name, printername);
4211 init_unistr(&printer->comment, comment);
4212 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4214 /* check the required size. */
4215 *needed += spoolss_size_printer_info_1(printer);
4217 if (!alloc_buffer_size(buffer, *needed)) {
4219 return WERR_INSUFFICIENT_BUFFER;
4222 /* fill the buffer with the structures */
4223 smb_io_printer_info_1("", buffer, printer, 0);
4228 if (*needed > offered) {
4230 return WERR_INSUFFICIENT_BUFFER;
4236 /********************************************************************
4237 enum_all_printers_info_1_network.
4238 *********************************************************************/
4240 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4244 DEBUG(4,("enum_all_printers_info_1_network\n"));
4246 /* If we respond to a enum_printers level 1 on our name with flags
4247 set to PRINTER_ENUM_REMOTE with a list of printers then these
4248 printers incorrectly appear in the APW browse list.
4249 Specifically the printers for the server appear at the workgroup
4250 level where all the other servers in the domain are
4251 listed. Windows responds to this call with a
4252 WERR_CAN_NOT_COMPLETE so we should do the same. */
4254 if (name[0] == '\\' && name[1] == '\\')
4257 if (is_myname_or_ipaddr(s))
4258 return WERR_CAN_NOT_COMPLETE;
4260 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4263 /********************************************************************
4264 * api_spoolss_enumprinters
4266 * called from api_spoolss_enumprinters (see this to understand)
4267 ********************************************************************/
4269 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4273 int n_services=lp_numservices();
4274 PRINTER_INFO_2 *tp, *printers=NULL;
4275 PRINTER_INFO_2 current_prt;
4277 for (snum=0; snum<n_services; snum++) {
4278 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4279 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4281 if (construct_printer_info_2(¤t_prt, snum)) {
4282 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4283 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4284 SAFE_FREE(printers);
4289 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4290 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4296 /* check the required size. */
4297 for (i=0; i<*returned; i++)
4298 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4300 if (!alloc_buffer_size(buffer, *needed)) {
4301 for (i=0; i<*returned; i++) {
4302 free_devmode(printers[i].devmode);
4304 SAFE_FREE(printers);
4305 return WERR_INSUFFICIENT_BUFFER;
4308 /* fill the buffer with the structures */
4309 for (i=0; i<*returned; i++)
4310 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4313 for (i=0; i<*returned; i++) {
4314 free_devmode(printers[i].devmode);
4316 SAFE_FREE(printers);
4318 if (*needed > offered) {
4320 return WERR_INSUFFICIENT_BUFFER;
4326 /********************************************************************
4327 * handle enumeration of printers at level 1
4328 ********************************************************************/
4330 static WERROR enumprinters_level1( uint32 flags, fstring name,
4331 NEW_BUFFER *buffer, uint32 offered,
4332 uint32 *needed, uint32 *returned)
4334 /* Not all the flags are equals */
4336 if (flags & PRINTER_ENUM_LOCAL)
4337 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4339 if (flags & PRINTER_ENUM_NAME)
4340 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4342 if (flags & PRINTER_ENUM_REMOTE)
4343 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4345 if (flags & PRINTER_ENUM_NETWORK)
4346 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4348 return WERR_OK; /* NT4sp5 does that */
4351 /********************************************************************
4352 * handle enumeration of printers at level 2
4353 ********************************************************************/
4355 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4356 NEW_BUFFER *buffer, uint32 offered,
4357 uint32 *needed, uint32 *returned)
4359 char *s = servername;
4361 if (flags & PRINTER_ENUM_LOCAL) {
4362 return enum_all_printers_info_2(buffer, offered, needed, returned);
4365 if (flags & PRINTER_ENUM_NAME) {
4366 if ((servername[0] == '\\') && (servername[1] == '\\'))
4368 if (is_myname_or_ipaddr(s))
4369 return enum_all_printers_info_2(buffer, offered, needed, returned);
4371 return WERR_INVALID_NAME;
4374 if (flags & PRINTER_ENUM_REMOTE)
4375 return WERR_UNKNOWN_LEVEL;
4380 /********************************************************************
4381 * handle enumeration of printers at level 5
4382 ********************************************************************/
4384 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4385 NEW_BUFFER *buffer, uint32 offered,
4386 uint32 *needed, uint32 *returned)
4388 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4392 /********************************************************************
4393 * api_spoolss_enumprinters
4395 * called from api_spoolss_enumprinters (see this to understand)
4396 ********************************************************************/
4398 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4400 uint32 flags = q_u->flags;
4401 UNISTR2 *servername = &q_u->servername;
4402 uint32 level = q_u->level;
4403 NEW_BUFFER *buffer = NULL;
4404 uint32 offered = q_u->offered;
4405 uint32 *needed = &r_u->needed;
4406 uint32 *returned = &r_u->returned;
4410 /* that's an [in out] buffer */
4411 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4412 buffer = r_u->buffer;
4414 DEBUG(4,("_spoolss_enumprinters\n"));
4421 * flags==PRINTER_ENUM_NAME
4422 * if name=="" then enumerates all printers
4423 * if name!="" then enumerate the printer
4424 * flags==PRINTER_ENUM_REMOTE
4425 * name is NULL, enumerate printers
4426 * Level 2: name!="" enumerates printers, name can't be NULL
4427 * Level 3: doesn't exist
4428 * Level 4: does a local registry lookup
4429 * Level 5: same as Level 2
4432 unistr2_to_ascii(name, servername, sizeof(name)-1);
4437 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4439 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4441 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4446 return WERR_UNKNOWN_LEVEL;
4449 /****************************************************************************
4450 ****************************************************************************/
4452 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4454 PRINTER_INFO_0 *printer=NULL;
4456 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4459 construct_printer_info_0(printer, snum);
4461 /* check the required size. */
4462 *needed += spoolss_size_printer_info_0(printer);
4464 if (!alloc_buffer_size(buffer, *needed)) {
4466 return WERR_INSUFFICIENT_BUFFER;
4469 /* fill the buffer with the structures */
4470 smb_io_printer_info_0("", buffer, printer, 0);
4475 if (*needed > offered) {
4476 return WERR_INSUFFICIENT_BUFFER;
4482 /****************************************************************************
4483 ****************************************************************************/
4485 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4487 PRINTER_INFO_1 *printer=NULL;
4489 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4492 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4494 /* check the required size. */
4495 *needed += spoolss_size_printer_info_1(printer);
4497 if (!alloc_buffer_size(buffer, *needed)) {
4499 return WERR_INSUFFICIENT_BUFFER;
4502 /* fill the buffer with the structures */
4503 smb_io_printer_info_1("", buffer, printer, 0);
4508 if (*needed > offered) {
4509 return WERR_INSUFFICIENT_BUFFER;
4515 /****************************************************************************
4516 ****************************************************************************/
4518 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4520 PRINTER_INFO_2 *printer=NULL;
4522 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4525 construct_printer_info_2(printer, snum);
4527 /* check the required size. */
4528 *needed += spoolss_size_printer_info_2(printer);
4530 if (!alloc_buffer_size(buffer, *needed)) {
4531 free_printer_info_2(printer);
4532 return WERR_INSUFFICIENT_BUFFER;
4535 /* fill the buffer with the structures */
4536 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4537 free_printer_info_2(printer);
4542 free_printer_info_2(printer);
4544 if (*needed > offered) {
4545 return WERR_INSUFFICIENT_BUFFER;
4551 /****************************************************************************
4552 ****************************************************************************/
4554 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4556 PRINTER_INFO_3 *printer=NULL;
4558 if (!construct_printer_info_3(&printer, snum))
4561 /* check the required size. */
4562 *needed += spoolss_size_printer_info_3(printer);
4564 if (!alloc_buffer_size(buffer, *needed)) {
4565 free_printer_info_3(printer);
4566 return WERR_INSUFFICIENT_BUFFER;
4569 /* fill the buffer with the structures */
4570 smb_io_printer_info_3("", buffer, printer, 0);
4573 free_printer_info_3(printer);
4575 if (*needed > offered) {
4576 return WERR_INSUFFICIENT_BUFFER;
4582 /****************************************************************************
4583 ****************************************************************************/
4585 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4587 PRINTER_INFO_4 *printer=NULL;
4589 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4592 if (!construct_printer_info_4(printer, snum))
4595 /* check the required size. */
4596 *needed += spoolss_size_printer_info_4(printer);
4598 if (!alloc_buffer_size(buffer, *needed)) {
4599 free_printer_info_4(printer);
4600 return WERR_INSUFFICIENT_BUFFER;
4603 /* fill the buffer with the structures */
4604 smb_io_printer_info_4("", buffer, printer, 0);
4607 free_printer_info_4(printer);
4609 if (*needed > offered) {
4610 return WERR_INSUFFICIENT_BUFFER;
4616 /****************************************************************************
4617 ****************************************************************************/
4619 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4621 PRINTER_INFO_5 *printer=NULL;
4623 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4626 if (!construct_printer_info_5(printer, snum))
4629 /* check the required size. */
4630 *needed += spoolss_size_printer_info_5(printer);
4632 if (!alloc_buffer_size(buffer, *needed)) {
4633 free_printer_info_5(printer);
4634 return WERR_INSUFFICIENT_BUFFER;
4637 /* fill the buffer with the structures */
4638 smb_io_printer_info_5("", buffer, printer, 0);
4641 free_printer_info_5(printer);
4643 if (*needed > offered) {
4644 return WERR_INSUFFICIENT_BUFFER;
4650 /****************************************************************************
4651 ****************************************************************************/
4653 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4655 POLICY_HND *handle = &q_u->handle;
4656 uint32 level = q_u->level;
4657 NEW_BUFFER *buffer = NULL;
4658 uint32 offered = q_u->offered;
4659 uint32 *needed = &r_u->needed;
4663 /* that's an [in out] buffer */
4664 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4665 buffer = r_u->buffer;
4669 if (!get_printer_snum(p, handle, &snum))
4674 return getprinter_level_0(snum, buffer, offered, needed);
4676 return getprinter_level_1(snum, buffer, offered, needed);
4678 return getprinter_level_2(snum, buffer, offered, needed);
4680 return getprinter_level_3(snum, buffer, offered, needed);
4682 return getprinter_level_4(snum, buffer, offered, needed);
4684 return getprinter_level_5(snum, buffer, offered, needed);
4686 return WERR_UNKNOWN_LEVEL;
4689 /********************************************************************
4690 * fill a DRIVER_INFO_1 struct
4691 ********************************************************************/
4693 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4695 init_unistr( &info->name, driver.info_3->name);
4698 /********************************************************************
4699 * construct_printer_driver_info_1
4700 ********************************************************************/
4702 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4704 NT_PRINTER_INFO_LEVEL *printer = NULL;
4705 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4707 ZERO_STRUCT(driver);
4709 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4710 return WERR_INVALID_PRINTER_NAME;
4712 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4713 return WERR_UNKNOWN_PRINTER_DRIVER;
4715 fill_printer_driver_info_1(info, driver, servername, architecture);
4717 free_a_printer(&printer,2);
4722 /********************************************************************
4723 * construct_printer_driver_info_2
4724 * fill a printer_info_2 struct
4725 ********************************************************************/
4727 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4731 info->version=driver.info_3->cversion;
4733 init_unistr( &info->name, driver.info_3->name );
4734 init_unistr( &info->architecture, driver.info_3->environment );
4737 if (strlen(driver.info_3->driverpath)) {
4738 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4739 init_unistr( &info->driverpath, temp );
4741 init_unistr( &info->driverpath, "" );
4743 if (strlen(driver.info_3->datafile)) {
4744 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4745 init_unistr( &info->datafile, temp );
4747 init_unistr( &info->datafile, "" );
4749 if (strlen(driver.info_3->configfile)) {
4750 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4751 init_unistr( &info->configfile, temp );
4753 init_unistr( &info->configfile, "" );
4756 /********************************************************************
4757 * construct_printer_driver_info_2
4758 * fill a printer_info_2 struct
4759 ********************************************************************/
4761 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4763 NT_PRINTER_INFO_LEVEL *printer = NULL;
4764 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4766 ZERO_STRUCT(printer);
4767 ZERO_STRUCT(driver);
4769 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4770 return WERR_INVALID_PRINTER_NAME;
4772 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4773 return WERR_UNKNOWN_PRINTER_DRIVER;
4775 fill_printer_driver_info_2(info, driver, servername);
4777 free_a_printer(&printer,2);
4782 /********************************************************************
4783 * copy a strings array and convert to UNICODE
4785 * convert an array of ascii string to a UNICODE string
4786 ********************************************************************/
4788 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4796 DEBUG(6,("init_unistr_array\n"));
4807 v = ""; /* hack to handle null lists */
4810 /* hack to allow this to be used in places other than when generating
4811 the list of dependent files */
4814 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4818 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4820 if ( (tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4821 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4829 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4834 (*uni_array)[j]=0x0000;
4837 DEBUGADD(6,("last one:done\n"));
4839 /* return size of array in uint16's */
4844 /********************************************************************
4845 * construct_printer_info_3
4846 * fill a printer_info_3 struct
4847 ********************************************************************/
4849 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4855 info->version=driver.info_3->cversion;
4857 init_unistr( &info->name, driver.info_3->name );
4858 init_unistr( &info->architecture, driver.info_3->environment );
4860 if (strlen(driver.info_3->driverpath)) {
4861 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4862 init_unistr( &info->driverpath, temp );
4864 init_unistr( &info->driverpath, "" );
4866 if (strlen(driver.info_3->datafile)) {
4867 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4868 init_unistr( &info->datafile, temp );
4870 init_unistr( &info->datafile, "" );
4872 if (strlen(driver.info_3->configfile)) {
4873 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4874 init_unistr( &info->configfile, temp );
4876 init_unistr( &info->configfile, "" );
4878 if (strlen(driver.info_3->helpfile)) {
4879 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4880 init_unistr( &info->helpfile, temp );
4882 init_unistr( &info->helpfile, "" );
4884 init_unistr( &info->monitorname, driver.info_3->monitorname );
4885 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4887 info->dependentfiles=NULL;
4888 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4891 /********************************************************************
4892 * construct_printer_info_3
4893 * fill a printer_info_3 struct
4894 ********************************************************************/
4896 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4898 NT_PRINTER_INFO_LEVEL *printer = NULL;
4899 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4901 ZERO_STRUCT(driver);
4903 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4904 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4905 if (!W_ERROR_IS_OK(status))
4906 return WERR_INVALID_PRINTER_NAME;
4908 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4909 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4914 * I put this code in during testing. Helpful when commenting out the
4915 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4916 * as win2k always queries the driver using an infor level of 6.
4917 * I've left it in (but ifdef'd out) because I'll probably
4918 * use it in experimentation again in the future. --jerry 22/01/2002
4921 if (!W_ERROR_IS_OK(status)) {
4923 * Is this a W2k client ?
4926 /* Yes - try again with a WinNT driver. */
4928 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4929 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4933 if (!W_ERROR_IS_OK(status)) {
4934 free_a_printer(&printer,2);
4935 return WERR_UNKNOWN_PRINTER_DRIVER;
4943 fill_printer_driver_info_3(info, driver, servername);
4945 free_a_printer(&printer,2);
4950 /********************************************************************
4951 * construct_printer_info_6
4952 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4953 ********************************************************************/
4955 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4961 memset(&nullstr, '\0', sizeof(fstring));
4963 info->version=driver.info_3->cversion;
4965 init_unistr( &info->name, driver.info_3->name );
4966 init_unistr( &info->architecture, driver.info_3->environment );
4968 if (strlen(driver.info_3->driverpath)) {
4969 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4970 init_unistr( &info->driverpath, temp );
4972 init_unistr( &info->driverpath, "" );
4974 if (strlen(driver.info_3->datafile)) {
4975 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4976 init_unistr( &info->datafile, temp );
4978 init_unistr( &info->datafile, "" );
4980 if (strlen(driver.info_3->configfile)) {
4981 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4982 init_unistr( &info->configfile, temp );
4984 init_unistr( &info->configfile, "" );
4986 if (strlen(driver.info_3->helpfile)) {
4987 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4988 init_unistr( &info->helpfile, temp );
4990 init_unistr( &info->helpfile, "" );
4992 init_unistr( &info->monitorname, driver.info_3->monitorname );
4993 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4995 info->dependentfiles = NULL;
4996 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
4998 info->previousdrivernames=NULL;
4999 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5001 info->driver_date.low=0;
5002 info->driver_date.high=0;
5005 info->driver_version_low=0;
5006 info->driver_version_high=0;
5008 init_unistr( &info->mfgname, "");
5009 init_unistr( &info->oem_url, "");
5010 init_unistr( &info->hardware_id, "");
5011 init_unistr( &info->provider, "");
5014 /********************************************************************
5015 * construct_printer_info_6
5016 * fill a printer_info_6 struct
5017 ********************************************************************/
5019 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5020 fstring servername, fstring architecture, uint32 version)
5022 NT_PRINTER_INFO_LEVEL *printer = NULL;
5023 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5026 ZERO_STRUCT(driver);
5028 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5030 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5032 if (!W_ERROR_IS_OK(status))
5033 return WERR_INVALID_PRINTER_NAME;
5035 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5037 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5039 if (!W_ERROR_IS_OK(status))
5042 * Is this a W2k client ?
5046 free_a_printer(&printer,2);
5047 return WERR_UNKNOWN_PRINTER_DRIVER;
5050 /* Yes - try again with a WinNT driver. */
5052 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5053 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5054 if (!W_ERROR_IS_OK(status)) {
5055 free_a_printer(&printer,2);
5056 return WERR_UNKNOWN_PRINTER_DRIVER;
5060 fill_printer_driver_info_6(info, driver, servername);
5062 free_a_printer(&printer,2);
5067 /****************************************************************************
5068 ****************************************************************************/
5070 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5072 SAFE_FREE(info->dependentfiles);
5075 /****************************************************************************
5076 ****************************************************************************/
5078 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5080 SAFE_FREE(info->dependentfiles);
5084 /****************************************************************************
5085 ****************************************************************************/
5087 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5089 DRIVER_INFO_1 *info=NULL;
5092 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5095 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5096 if (!W_ERROR_IS_OK(status)) {
5101 /* check the required size. */
5102 *needed += spoolss_size_printer_driver_info_1(info);
5104 if (!alloc_buffer_size(buffer, *needed)) {
5106 return WERR_INSUFFICIENT_BUFFER;
5109 /* fill the buffer with the structures */
5110 smb_io_printer_driver_info_1("", buffer, info, 0);
5115 if (*needed > offered)
5116 return WERR_INSUFFICIENT_BUFFER;
5121 /****************************************************************************
5122 ****************************************************************************/
5124 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5126 DRIVER_INFO_2 *info=NULL;
5129 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5132 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5133 if (!W_ERROR_IS_OK(status)) {
5138 /* check the required size. */
5139 *needed += spoolss_size_printer_driver_info_2(info);
5141 if (!alloc_buffer_size(buffer, *needed)) {
5143 return WERR_INSUFFICIENT_BUFFER;
5146 /* fill the buffer with the structures */
5147 smb_io_printer_driver_info_2("", buffer, info, 0);
5152 if (*needed > offered)
5153 return WERR_INSUFFICIENT_BUFFER;
5158 /****************************************************************************
5159 ****************************************************************************/
5161 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5168 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5169 if (!W_ERROR_IS_OK(status)) {
5173 /* check the required size. */
5174 *needed += spoolss_size_printer_driver_info_3(&info);
5176 if (!alloc_buffer_size(buffer, *needed)) {
5177 free_printer_driver_info_3(&info);
5178 return WERR_INSUFFICIENT_BUFFER;
5181 /* fill the buffer with the structures */
5182 smb_io_printer_driver_info_3("", buffer, &info, 0);
5184 free_printer_driver_info_3(&info);
5186 if (*needed > offered)
5187 return WERR_INSUFFICIENT_BUFFER;
5192 /****************************************************************************
5193 ****************************************************************************/
5195 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5202 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5203 if (!W_ERROR_IS_OK(status)) {
5207 /* check the required size. */
5208 *needed += spoolss_size_printer_driver_info_6(&info);
5210 if (!alloc_buffer_size(buffer, *needed)) {
5211 free_printer_driver_info_6(&info);
5212 return WERR_INSUFFICIENT_BUFFER;
5215 /* fill the buffer with the structures */
5216 smb_io_printer_driver_info_6("", buffer, &info, 0);
5218 free_printer_driver_info_6(&info);
5220 if (*needed > offered)
5221 return WERR_INSUFFICIENT_BUFFER;
5226 /****************************************************************************
5227 ****************************************************************************/
5229 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5231 POLICY_HND *handle = &q_u->handle;
5232 UNISTR2 *uni_arch = &q_u->architecture;
5233 uint32 level = q_u->level;
5234 uint32 clientmajorversion = q_u->clientmajorversion;
5235 NEW_BUFFER *buffer = NULL;
5236 uint32 offered = q_u->offered;
5237 uint32 *needed = &r_u->needed;
5238 uint32 *servermajorversion = &r_u->servermajorversion;
5239 uint32 *serverminorversion = &r_u->serverminorversion;
5242 fstring architecture;
5245 /* that's an [in out] buffer */
5246 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5247 buffer = r_u->buffer;
5249 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5252 *servermajorversion = 0;
5253 *serverminorversion = 0;
5255 pstrcpy(servername, get_called_name());
5256 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5258 if (!get_printer_snum(p, handle, &snum))
5263 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5265 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5267 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5269 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5272 return WERR_UNKNOWN_LEVEL;
5275 /****************************************************************************
5276 ****************************************************************************/
5278 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5280 POLICY_HND *handle = &q_u->handle;
5282 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5285 DEBUG(3,("Error in startpageprinter printer handle\n"));
5289 Printer->page_started=True;
5293 /****************************************************************************
5294 ****************************************************************************/
5296 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5298 POLICY_HND *handle = &q_u->handle;
5301 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5304 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5308 if (!get_printer_snum(p, handle, &snum))
5311 Printer->page_started=False;
5312 print_job_endpage(snum, Printer->jobid);
5317 /********************************************************************
5318 * api_spoolss_getprinter
5319 * called from the spoolss dispatcher
5321 ********************************************************************/
5323 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5325 POLICY_HND *handle = &q_u->handle;
5326 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5327 uint32 *jobid = &r_u->jobid;
5329 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5333 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5334 struct current_user user;
5337 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5341 get_current_user(&user, p);
5344 * a nice thing with NT is it doesn't listen to what you tell it.
5345 * when asked to send _only_ RAW datas, it tries to send datas
5348 * So I add checks like in NT Server ...
5351 if (info_1->p_datatype != 0) {
5352 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5353 if (strcmp(datatype, "RAW") != 0) {
5355 return WERR_INVALID_DATATYPE;
5359 /* get the share number of the printer */
5360 if (!get_printer_snum(p, handle, &snum)) {
5364 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5366 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5368 /* An error occured in print_job_start() so return an appropriate
5371 if (Printer->jobid == -1) {
5372 return map_werror_from_unix(errno);
5375 Printer->document_started=True;
5376 (*jobid) = Printer->jobid;
5381 /********************************************************************
5382 * api_spoolss_getprinter
5383 * called from the spoolss dispatcher
5385 ********************************************************************/
5387 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5389 POLICY_HND *handle = &q_u->handle;
5391 return _spoolss_enddocprinter_internal(p, handle);
5394 /****************************************************************************
5395 ****************************************************************************/
5397 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5399 POLICY_HND *handle = &q_u->handle;
5400 uint32 buffer_size = q_u->buffer_size;
5401 uint8 *buffer = q_u->buffer;
5402 uint32 *buffer_written = &q_u->buffer_size2;
5404 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5407 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5408 r_u->buffer_written = q_u->buffer_size2;
5412 if (!get_printer_snum(p, handle, &snum))
5415 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5416 if (*buffer_written == -1) {
5417 r_u->buffer_written = 0;
5418 if (errno == ENOSPC)
5419 return WERR_NO_SPOOL_SPACE;
5421 return WERR_ACCESS_DENIED;
5424 r_u->buffer_written = q_u->buffer_size2;
5429 /********************************************************************
5430 * api_spoolss_getprinter
5431 * called from the spoolss dispatcher
5433 ********************************************************************/
5435 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5438 struct current_user user;
5440 WERROR errcode = WERR_BADFUNC;
5441 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5443 get_current_user(&user, p);
5446 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5450 if (!get_printer_snum(p, handle, &snum))
5454 case PRINTER_CONTROL_PAUSE:
5455 if (print_queue_pause(&user, snum, &errcode)) {
5459 case PRINTER_CONTROL_RESUME:
5460 case PRINTER_CONTROL_UNPAUSE:
5461 if (print_queue_resume(&user, snum, &errcode)) {
5465 case PRINTER_CONTROL_PURGE:
5466 if (print_queue_purge(&user, snum, &errcode)) {
5471 return WERR_UNKNOWN_LEVEL;
5477 /********************************************************************
5478 * api_spoolss_abortprinter
5479 * From MSDN: "Deletes printer's spool file if printer is configured
5481 ********************************************************************/
5483 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5485 POLICY_HND *handle = &q_u->handle;
5486 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5488 struct current_user user;
5489 WERROR errcode = WERR_OK;
5492 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5496 if (!get_printer_snum(p, handle, &snum))
5499 get_current_user( &user, p );
5501 print_job_delete( &user, snum, Printer->jobid, &errcode );
5506 /********************************************************************
5507 * called by spoolss_api_setprinter
5508 * when updating a printer description
5509 ********************************************************************/
5511 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5512 const SPOOL_PRINTER_INFO_LEVEL *info,
5513 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5515 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5516 struct current_user user;
5520 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5522 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5523 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5524 OUR_HANDLE(handle)));
5526 result = WERR_BADFID;
5530 /* NT seems to like setting the security descriptor even though
5531 nothing may have actually changed. This causes annoying
5532 dialog boxes when the user doesn't have permission to change
5533 the security descriptor. */
5535 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5537 if (DEBUGLEVEL >= 10) {
5541 the_acl = old_secdesc_ctr->sec->dacl;
5542 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5543 PRINTERNAME(snum), the_acl->num_aces));
5545 for (i = 0; i < the_acl->num_aces; i++) {
5548 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5550 DEBUG(10, ("%s 0x%08x\n", sid_str,
5551 the_acl->ace[i].info.mask));
5554 the_acl = secdesc_ctr->sec->dacl;
5557 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5558 PRINTERNAME(snum), the_acl->num_aces));
5560 for (i = 0; i < the_acl->num_aces; i++) {
5563 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5565 DEBUG(10, ("%s 0x%08x\n", sid_str,
5566 the_acl->ace[i].info.mask));
5569 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5573 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5575 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5580 /* Work out which user is performing the operation */
5582 get_current_user(&user, p);
5584 /* Check the user has permissions to change the security
5585 descriptor. By experimentation with two NT machines, the user
5586 requires Full Access to the printer to change security
5589 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5590 result = WERR_ACCESS_DENIED;
5594 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5601 /********************************************************************
5602 Do Samba sanity checks on a printer info struct.
5603 this has changed purpose: it now "canonicalises" printer
5604 info from a client rather than just checking it is correct
5605 ********************************************************************/
5607 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5609 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5610 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5612 /* we force some elements to "correct" values */
5613 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5614 fstrcpy(info->sharename, lp_servicename(snum));
5615 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5616 get_called_name(), info->sharename);
5617 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5622 /****************************************************************************
5623 ****************************************************************************/
5625 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5627 extern userdom_struct current_user_info;
5628 char *cmd = lp_addprinter_cmd();
5634 fstring remote_machine = "%m";
5636 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5638 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5639 cmd, printer->info_2->printername, printer->info_2->sharename,
5640 printer->info_2->portname, printer->info_2->drivername,
5641 printer->info_2->location, printer->info_2->comment, remote_machine);
5643 DEBUG(10,("Running [%s]\n", command));
5644 ret = smbrun(command, &fd);
5645 DEBUGADD(10,("returned [%d]\n", ret));
5654 /* Get lines and convert them back to dos-codepage */
5655 qlines = fd_lines_load(fd, &numlines);
5656 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5660 /* Set the portname to what the script says the portname should be. */
5661 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5662 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5664 /* Send SIGHUP to process group... is there a better way? */
5667 /* reload our services immediately */
5668 reload_services( False );
5671 file_lines_free(qlines);
5675 /********************************************************************
5676 * Called by spoolss_api_setprinter
5677 * when updating a printer description.
5678 ********************************************************************/
5680 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5681 const SPOOL_PRINTER_INFO_LEVEL *info,
5682 DEVICEMODE *devmode)
5685 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5686 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5689 DEBUG(8,("update_printer\n"));
5694 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5695 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5696 result = WERR_UNKNOWN_LEVEL;
5701 result = WERR_BADFID;
5705 if (!get_printer_snum(p, handle, &snum)) {
5706 result = WERR_BADFID;
5710 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5711 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5712 result = WERR_BADFID;
5716 DEBUGADD(8,("Converting info_2 struct\n"));
5719 * convert_printer_info converts the incoming
5720 * info from the client and overwrites the info
5721 * just read from the tdb in the pointer 'printer'.
5724 if (!convert_printer_info(info, printer, level)) {
5725 result = WERR_NOMEM;
5730 /* we have a valid devmode
5731 convert it and link it*/
5733 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5734 if (!convert_devicemode(printer->info_2->printername, devmode,
5735 &printer->info_2->devmode)) {
5736 result = WERR_NOMEM;
5741 * make sure we actually reload the services after
5742 * this as smb.conf could have a new section in it
5743 * .... shouldn't .... but could
5745 reload_services(False);
5748 /* Do sanity check on the requested changes for Samba */
5750 if (!check_printer_ok(printer->info_2, snum)) {
5751 result = WERR_INVALID_PARAM;
5755 /* Check calling user has permission to update printer description */
5757 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5758 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5759 result = WERR_ACCESS_DENIED;
5763 /* Call addprinter hook */
5765 if (*lp_addprinter_cmd()) {
5766 if ( !add_printer_hook(printer) ) {
5767 result = WERR_ACCESS_DENIED;
5773 * When a *new* driver is bound to a printer, the drivername is used to
5774 * lookup previously saved driver initialization info, which is then
5775 * bound to the printer, simulating what happens in the Windows arch.
5777 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5779 if (!set_driver_init(printer, 2))
5781 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5782 printer->info_2->drivername));
5785 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5786 printer->info_2->drivername));
5788 notify_printer_driver(snum, printer->info_2->drivername);
5791 /* Update printer info */
5792 result = mod_a_printer(*printer, 2);
5794 /* flag which changes actually occured. This is a small subset of
5795 all the possible changes */
5797 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5798 notify_printer_comment(snum, printer->info_2->comment);
5800 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5801 notify_printer_sharename(snum, printer->info_2->sharename);
5803 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5804 notify_printer_port(snum, printer->info_2->portname);
5806 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5807 notify_printer_location(snum, printer->info_2->location);
5810 free_a_printer(&printer, 2);
5811 free_a_printer(&old_printer, 2);
5817 /****************************************************************************
5818 ****************************************************************************/
5820 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5822 POLICY_HND *handle = &q_u->handle;
5823 uint32 level = q_u->level;
5824 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5825 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5826 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5827 uint32 command = q_u->command;
5829 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5832 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5836 /* check the level */
5839 return control_printer(handle, command, p);
5841 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5843 return update_printer_sec(handle, level, info, p,
5846 return WERR_UNKNOWN_LEVEL;
5850 /****************************************************************************
5851 ****************************************************************************/
5853 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5855 POLICY_HND *handle = &q_u->handle;
5857 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5860 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5864 if (!get_printer_snum(p, handle, &snum))
5867 if (Printer->notify.client_connected==True)
5868 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5870 Printer->notify.flags=0;
5871 Printer->notify.options=0;
5872 Printer->notify.localmachine[0]='\0';
5873 Printer->notify.printerlocal=0;
5874 if (Printer->notify.option)
5875 free_spool_notify_option(&Printer->notify.option);
5876 Printer->notify.client_connected=False;
5881 /****************************************************************************
5882 ****************************************************************************/
5884 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5886 /* that's an [in out] buffer (despite appearences to the contrary) */
5887 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5890 return WERR_INVALID_PARAM; /* this is what a NT server
5891 returns for AddJob. AddJob
5892 must fail on non-local
5896 /****************************************************************************
5897 ****************************************************************************/
5899 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5900 int position, int snum)
5906 t=gmtime(&queue->time);
5907 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5909 job_info->jobid=queue->job;
5910 init_unistr(&job_info->printername, lp_servicename(snum));
5911 init_unistr(&job_info->machinename, temp_name);
5912 init_unistr(&job_info->username, queue->fs_user);
5913 init_unistr(&job_info->document, queue->fs_file);
5914 init_unistr(&job_info->datatype, "RAW");
5915 init_unistr(&job_info->text_status, "");
5916 job_info->status=nt_printj_status(queue->status);
5917 job_info->priority=queue->priority;
5918 job_info->position=position;
5919 job_info->totalpages=queue->page_count;
5920 job_info->pagesprinted=0;
5922 make_systemtime(&job_info->submitted, t);
5925 /****************************************************************************
5926 ****************************************************************************/
5928 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5929 int position, int snum,
5930 NT_PRINTER_INFO_LEVEL *ntprinter,
5931 DEVICEMODE *devmode)
5937 t=gmtime(&queue->time);
5938 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5940 job_info->jobid=queue->job;
5942 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5944 init_unistr(&job_info->printername, chaine);
5946 init_unistr(&job_info->machinename, temp_name);
5947 init_unistr(&job_info->username, queue->fs_user);
5948 init_unistr(&job_info->document, queue->fs_file);
5949 init_unistr(&job_info->notifyname, queue->fs_user);
5950 init_unistr(&job_info->datatype, "RAW");
5951 init_unistr(&job_info->printprocessor, "winprint");
5952 init_unistr(&job_info->parameters, "");
5953 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5954 init_unistr(&job_info->text_status, "");
5956 /* and here the security descriptor */
5958 job_info->status=nt_printj_status(queue->status);
5959 job_info->priority=queue->priority;
5960 job_info->position=position;
5961 job_info->starttime=0;
5962 job_info->untiltime=0;
5963 job_info->totalpages=queue->page_count;
5964 job_info->size=queue->size;
5965 make_systemtime(&(job_info->submitted), t);
5966 job_info->timeelapsed=0;
5967 job_info->pagesprinted=0;
5969 job_info->devmode = devmode;
5974 /****************************************************************************
5975 Enumjobs at level 1.
5976 ****************************************************************************/
5978 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5979 NEW_BUFFER *buffer, uint32 offered,
5980 uint32 *needed, uint32 *returned)
5985 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5992 for (i=0; i<*returned; i++)
5993 fill_job_info_1(&info[i], &queue[i], i, snum);
5997 /* check the required size. */
5998 for (i=0; i<*returned; i++)
5999 (*needed) += spoolss_size_job_info_1(&info[i]);
6001 if (!alloc_buffer_size(buffer, *needed)) {
6003 return WERR_INSUFFICIENT_BUFFER;
6006 /* fill the buffer with the structures */
6007 for (i=0; i<*returned; i++)
6008 smb_io_job_info_1("", buffer, &info[i], 0);
6013 if (*needed > offered) {
6015 return WERR_INSUFFICIENT_BUFFER;
6021 /****************************************************************************
6022 Enumjobs at level 2.
6023 ****************************************************************************/
6025 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6026 NEW_BUFFER *buffer, uint32 offered,
6027 uint32 *needed, uint32 *returned)
6029 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6030 JOB_INFO_2 *info = NULL;
6033 DEVICEMODE *devmode = NULL;
6035 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6038 result = WERR_NOMEM;
6042 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6043 if (!W_ERROR_IS_OK(result)) {
6048 /* this should not be a failure condition if the devmode is NULL */
6050 devmode = construct_dev_mode(snum);
6052 for (i=0; i<*returned; i++)
6053 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6056 free_a_printer(&ntprinter, 2);
6059 /* check the required size. */
6060 for (i=0; i<*returned; i++)
6061 (*needed) += spoolss_size_job_info_2(&info[i]);
6063 if (*needed > offered) {
6065 result = WERR_INSUFFICIENT_BUFFER;
6069 if (!alloc_buffer_size(buffer, *needed)) {
6071 result = WERR_INSUFFICIENT_BUFFER;
6075 /* fill the buffer with the structures */
6076 for (i=0; i<*returned; i++)
6077 smb_io_job_info_2("", buffer, &info[i], 0);
6082 free_a_printer(&ntprinter, 2);
6083 free_devmode(devmode);
6091 /****************************************************************************
6093 ****************************************************************************/
6095 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6097 POLICY_HND *handle = &q_u->handle;
6098 uint32 level = q_u->level;
6099 NEW_BUFFER *buffer = NULL;
6100 uint32 offered = q_u->offered;
6101 uint32 *needed = &r_u->needed;
6102 uint32 *returned = &r_u->returned;
6105 print_status_struct prt_status;
6106 print_queue_struct *queue=NULL;
6108 /* that's an [in out] buffer */
6109 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6110 buffer = r_u->buffer;
6112 DEBUG(4,("_spoolss_enumjobs\n"));
6117 if (!get_printer_snum(p, handle, &snum))
6120 *returned = print_queue_status(snum, &queue, &prt_status);
6121 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6123 if (*returned == 0) {
6130 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6132 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6136 return WERR_UNKNOWN_LEVEL;
6140 /****************************************************************************
6141 ****************************************************************************/
6143 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6148 /****************************************************************************
6149 ****************************************************************************/
6151 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6153 POLICY_HND *handle = &q_u->handle;
6154 uint32 jobid = q_u->jobid;
6155 uint32 command = q_u->command;
6157 struct current_user user;
6159 WERROR errcode = WERR_BADFUNC;
6161 if (!get_printer_snum(p, handle, &snum)) {
6165 if (!print_job_exists(snum, jobid)) {
6166 return WERR_INVALID_PRINTER_NAME;
6169 get_current_user(&user, p);
6172 case JOB_CONTROL_CANCEL:
6173 case JOB_CONTROL_DELETE:
6174 if (print_job_delete(&user, snum, jobid, &errcode)) {
6178 case JOB_CONTROL_PAUSE:
6179 if (print_job_pause(&user, snum, jobid, &errcode)) {
6183 case JOB_CONTROL_RESTART:
6184 case JOB_CONTROL_RESUME:
6185 if (print_job_resume(&user, snum, jobid, &errcode)) {
6190 return WERR_UNKNOWN_LEVEL;
6196 /****************************************************************************
6197 Enumerates all printer drivers at level 1.
6198 ****************************************************************************/
6200 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6205 fstring *list = NULL;
6207 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6208 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6212 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6214 ndrivers=get_ntdrivers(&list, architecture, version);
6215 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6221 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6222 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6223 SAFE_FREE(driver_info_1);
6227 else driver_info_1 = tdi1;
6230 for (i=0; i<ndrivers; i++) {
6232 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6233 ZERO_STRUCT(driver);
6234 status = get_a_printer_driver(&driver, 3, list[i],
6235 architecture, version);
6236 if (!W_ERROR_IS_OK(status)) {
6240 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6241 free_a_printer_driver(driver, 3);
6244 *returned+=ndrivers;
6248 /* check the required size. */
6249 for (i=0; i<*returned; i++) {
6250 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6251 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6254 if (!alloc_buffer_size(buffer, *needed)) {
6255 SAFE_FREE(driver_info_1);
6256 return WERR_INSUFFICIENT_BUFFER;
6259 /* fill the buffer with the driver structures */
6260 for (i=0; i<*returned; i++) {
6261 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6262 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6265 SAFE_FREE(driver_info_1);
6267 if (*needed > offered) {
6269 return WERR_INSUFFICIENT_BUFFER;
6275 /****************************************************************************
6276 Enumerates all printer drivers at level 2.
6277 ****************************************************************************/
6279 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6284 fstring *list = NULL;
6286 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6287 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6291 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6293 ndrivers=get_ntdrivers(&list, architecture, version);
6294 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6300 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6301 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6302 SAFE_FREE(driver_info_2);
6306 else driver_info_2 = tdi2;
6309 for (i=0; i<ndrivers; i++) {
6312 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6313 ZERO_STRUCT(driver);
6314 status = get_a_printer_driver(&driver, 3, list[i],
6315 architecture, version);
6316 if (!W_ERROR_IS_OK(status)) {
6320 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6321 free_a_printer_driver(driver, 3);
6324 *returned+=ndrivers;
6328 /* check the required size. */
6329 for (i=0; i<*returned; i++) {
6330 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6331 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6334 if (!alloc_buffer_size(buffer, *needed)) {
6335 SAFE_FREE(driver_info_2);
6336 return WERR_INSUFFICIENT_BUFFER;
6339 /* fill the buffer with the form structures */
6340 for (i=0; i<*returned; i++) {
6341 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6342 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6345 SAFE_FREE(driver_info_2);
6347 if (*needed > offered) {
6349 return WERR_INSUFFICIENT_BUFFER;
6355 /****************************************************************************
6356 Enumerates all printer drivers at level 3.
6357 ****************************************************************************/
6359 static WERROR enumprinterdrivers_level3(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_3 *tdi3, *driver_info_3=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((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6381 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6382 SAFE_FREE(driver_info_3);
6386 else driver_info_3 = tdi3;
6389 for (i=0; i<ndrivers; i++) {
6392 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6393 ZERO_STRUCT(driver);
6394 status = get_a_printer_driver(&driver, 3, list[i],
6395 architecture, version);
6396 if (!W_ERROR_IS_OK(status)) {
6400 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6401 free_a_printer_driver(driver, 3);
6404 *returned+=ndrivers;
6408 /* check the required size. */
6409 for (i=0; i<*returned; i++) {
6410 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6411 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6414 if (!alloc_buffer_size(buffer, *needed)) {
6415 SAFE_FREE(driver_info_3);
6416 return WERR_INSUFFICIENT_BUFFER;
6419 /* fill the buffer with the driver structures */
6420 for (i=0; i<*returned; i++) {
6421 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6422 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6425 for (i=0; i<*returned; i++)
6426 SAFE_FREE(driver_info_3[i].dependentfiles);
6428 SAFE_FREE(driver_info_3);
6430 if (*needed > offered) {
6432 return WERR_INSUFFICIENT_BUFFER;
6438 /****************************************************************************
6439 Enumerates all printer drivers.
6440 ****************************************************************************/
6442 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6444 UNISTR2 *environment = &q_u->environment;
6445 uint32 level = q_u->level;
6446 NEW_BUFFER *buffer = NULL;
6447 uint32 offered = q_u->offered;
6448 uint32 *needed = &r_u->needed;
6449 uint32 *returned = &r_u->returned;
6451 fstring *list = NULL;
6453 fstring architecture;
6455 /* that's an [in out] buffer */
6456 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6457 buffer = r_u->buffer;
6459 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6460 fstrcpy(servername, get_called_name());
6464 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6468 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6470 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6472 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6476 return WERR_UNKNOWN_LEVEL;
6480 /****************************************************************************
6481 ****************************************************************************/
6483 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6485 form->flag=list->flag;
6486 init_unistr(&form->name, list->name);
6487 form->width=list->width;
6488 form->length=list->length;
6489 form->left=list->left;
6490 form->top=list->top;
6491 form->right=list->right;
6492 form->bottom=list->bottom;
6495 /****************************************************************************
6496 ****************************************************************************/
6498 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6500 uint32 level = q_u->level;
6501 NEW_BUFFER *buffer = NULL;
6502 uint32 offered = q_u->offered;
6503 uint32 *needed = &r_u->needed;
6504 uint32 *numofforms = &r_u->numofforms;
6505 uint32 numbuiltinforms;
6507 nt_forms_struct *list=NULL;
6508 nt_forms_struct *builtinlist=NULL;
6513 /* that's an [in out] buffer */
6514 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6515 buffer = r_u->buffer;
6517 DEBUG(4,("_spoolss_enumforms\n"));
6518 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6519 DEBUGADD(5,("Info level [%d]\n", level));
6521 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6522 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6523 *numofforms = get_ntforms(&list);
6524 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6525 *numofforms += numbuiltinforms;
6527 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6531 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6536 /* construct the list of form structures */
6537 for (i=0; i<numbuiltinforms; i++) {
6538 DEBUGADD(6,("Filling form number [%d]\n",i));
6539 fill_form_1(&forms_1[i], &builtinlist[i]);
6542 SAFE_FREE(builtinlist);
6544 for (; i<*numofforms; i++) {
6545 DEBUGADD(6,("Filling form number [%d]\n",i));
6546 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6551 /* check the required size. */
6552 for (i=0; i<numbuiltinforms; i++) {
6553 DEBUGADD(6,("adding form [%d]'s size\n",i));
6554 buffer_size += spoolss_size_form_1(&forms_1[i]);
6556 for (; i<*numofforms; i++) {
6557 DEBUGADD(6,("adding form [%d]'s size\n",i));
6558 buffer_size += spoolss_size_form_1(&forms_1[i]);
6561 *needed=buffer_size;
6563 if (!alloc_buffer_size(buffer, buffer_size)){
6565 return WERR_INSUFFICIENT_BUFFER;
6568 /* fill the buffer with the form structures */
6569 for (i=0; i<numbuiltinforms; i++) {
6570 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6571 smb_io_form_1("", buffer, &forms_1[i], 0);
6573 for (; i<*numofforms; i++) {
6574 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6575 smb_io_form_1("", buffer, &forms_1[i], 0);
6580 if (*needed > offered) {
6582 return WERR_INSUFFICIENT_BUFFER;
6589 SAFE_FREE(builtinlist);
6590 return WERR_UNKNOWN_LEVEL;
6595 /****************************************************************************
6596 ****************************************************************************/
6598 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6600 uint32 level = q_u->level;
6601 UNISTR2 *uni_formname = &q_u->formname;
6602 NEW_BUFFER *buffer = NULL;
6603 uint32 offered = q_u->offered;
6604 uint32 *needed = &r_u->needed;
6606 nt_forms_struct *list=NULL;
6607 nt_forms_struct builtin_form;
6612 int numofforms=0, i=0;
6614 /* that's an [in out] buffer */
6615 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6616 buffer = r_u->buffer;
6618 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6620 DEBUG(4,("_spoolss_getform\n"));
6621 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6622 DEBUGADD(5,("Info level [%d]\n", level));
6624 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6625 if (!foundBuiltin) {
6626 numofforms = get_ntforms(&list);
6627 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6629 if (numofforms == 0)
6636 fill_form_1(&form_1, &builtin_form);
6639 /* Check if the requested name is in the list of form structures */
6640 for (i=0; i<numofforms; i++) {
6642 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6644 if (strequal(form_name, list[i].name)) {
6645 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6646 fill_form_1(&form_1, &list[i]);
6652 if (i == numofforms) {
6656 /* check the required size. */
6658 *needed=spoolss_size_form_1(&form_1);
6660 if (!alloc_buffer_size(buffer, buffer_size)){
6661 return WERR_INSUFFICIENT_BUFFER;
6664 if (*needed > offered) {
6665 return WERR_INSUFFICIENT_BUFFER;
6668 /* fill the buffer with the form structures */
6669 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6670 smb_io_form_1("", buffer, &form_1, 0);
6676 return WERR_UNKNOWN_LEVEL;
6680 /****************************************************************************
6681 ****************************************************************************/
6683 static void fill_port_1(PORT_INFO_1 *port, char *name)
6685 init_unistr(&port->port_name, name);
6688 /****************************************************************************
6689 ****************************************************************************/
6691 static void fill_port_2(PORT_INFO_2 *port, char *name)
6693 init_unistr(&port->port_name, name);
6694 init_unistr(&port->monitor_name, "Local Monitor");
6695 init_unistr(&port->description, "Local Port");
6696 #define PORT_TYPE_WRITE 1
6697 port->port_type=PORT_TYPE_WRITE;
6701 /****************************************************************************
6703 ****************************************************************************/
6705 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6707 PORT_INFO_1 *ports=NULL;
6710 if (*lp_enumports_cmd()) {
6711 char *cmd = lp_enumports_cmd();
6718 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6720 DEBUG(10,("Running [%s]\n", command));
6721 ret = smbrun(command, &fd);
6722 DEBUG(10,("Returned [%d]\n", ret));
6726 /* Is this the best error to return here? */
6727 return WERR_ACCESS_DENIED;
6731 qlines = fd_lines_load(fd, &numlines);
6732 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6736 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6737 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6738 dos_errstr(WERR_NOMEM)));
6739 file_lines_free(qlines);
6743 for (i=0; i<numlines; i++) {
6744 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6745 fill_port_1(&ports[i], qlines[i]);
6748 file_lines_free(qlines);
6751 *returned = numlines;
6754 *returned = 1; /* Sole Samba port returned. */
6756 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6759 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6761 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6764 /* check the required size. */
6765 for (i=0; i<*returned; i++) {
6766 DEBUGADD(6,("adding port [%d]'s size\n", i));
6767 *needed += spoolss_size_port_info_1(&ports[i]);
6770 if (!alloc_buffer_size(buffer, *needed)) {
6772 return WERR_INSUFFICIENT_BUFFER;
6775 /* fill the buffer with the ports structures */
6776 for (i=0; i<*returned; i++) {
6777 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6778 smb_io_port_1("", buffer, &ports[i], 0);
6783 if (*needed > offered) {
6785 return WERR_INSUFFICIENT_BUFFER;
6791 /****************************************************************************
6793 ****************************************************************************/
6795 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6797 PORT_INFO_2 *ports=NULL;
6800 if (*lp_enumports_cmd()) {
6801 char *cmd = lp_enumports_cmd();
6810 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6811 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6813 path = lp_lockdir();
6815 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6816 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6819 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6820 ret = smbrun(command, &fd);
6821 DEBUGADD(10,("returned [%d]\n", ret));
6825 /* Is this the best error to return here? */
6826 return WERR_ACCESS_DENIED;
6830 qlines = fd_lines_load(fd, &numlines);
6831 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6835 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6836 file_lines_free(qlines);
6840 for (i=0; i<numlines; i++) {
6841 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6842 fill_port_2(&(ports[i]), qlines[i]);
6845 file_lines_free(qlines);
6848 *returned = numlines;
6854 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6857 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6859 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6862 /* check the required size. */
6863 for (i=0; i<*returned; i++) {
6864 DEBUGADD(6,("adding port [%d]'s size\n", i));
6865 *needed += spoolss_size_port_info_2(&ports[i]);
6868 if (!alloc_buffer_size(buffer, *needed)) {
6870 return WERR_INSUFFICIENT_BUFFER;
6873 /* fill the buffer with the ports structures */
6874 for (i=0; i<*returned; i++) {
6875 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6876 smb_io_port_2("", buffer, &ports[i], 0);
6881 if (*needed > offered) {
6883 return WERR_INSUFFICIENT_BUFFER;
6889 /****************************************************************************
6891 ****************************************************************************/
6893 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6895 uint32 level = q_u->level;
6896 NEW_BUFFER *buffer = NULL;
6897 uint32 offered = q_u->offered;
6898 uint32 *needed = &r_u->needed;
6899 uint32 *returned = &r_u->returned;
6901 /* that's an [in out] buffer */
6902 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6903 buffer = r_u->buffer;
6905 DEBUG(4,("_spoolss_enumports\n"));
6912 return enumports_level_1(buffer, offered, needed, returned);
6914 return enumports_level_2(buffer, offered, needed, returned);
6916 return WERR_UNKNOWN_LEVEL;
6920 /****************************************************************************
6921 ****************************************************************************/
6923 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6924 const SPOOL_PRINTER_INFO_LEVEL *info,
6925 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6926 uint32 user_switch, const SPOOL_USER_CTR *user,
6929 NT_PRINTER_INFO_LEVEL *printer = NULL;
6932 WERROR err = WERR_OK;
6934 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6935 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6939 ZERO_STRUCTP(printer);
6941 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6942 if (!convert_printer_info(info, printer, 2)) {
6943 free_a_printer(&printer, 2);
6947 /* check to see if the printer already exists */
6949 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6950 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6951 printer->info_2->sharename));
6952 free_a_printer(&printer, 2);
6953 return WERR_PRINTER_ALREADY_EXISTS;
6956 if (*lp_addprinter_cmd() ) {
6957 if ( !add_printer_hook(printer) ) {
6958 free_a_printer(&printer,2);
6959 return WERR_ACCESS_DENIED;
6963 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6964 printer->info_2->sharename);
6967 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6968 free_a_printer(&printer,2);
6969 return WERR_ACCESS_DENIED;
6972 /* you must be a printer admin to add a new printer */
6973 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6974 free_a_printer(&printer,2);
6975 return WERR_ACCESS_DENIED;
6979 * Do sanity check on the requested changes for Samba.
6982 if (!check_printer_ok(printer->info_2, snum)) {
6983 free_a_printer(&printer,2);
6984 return WERR_INVALID_PARAM;
6988 * When a printer is created, the drivername bound to the printer is used
6989 * to lookup previously saved driver initialization info, which is then
6990 * bound to the new printer, simulating what happens in the Windows arch.
6995 set_driver_init(printer, 2);
6999 /* A valid devmode was included, convert and link it
7001 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7003 if (!convert_devicemode(printer->info_2->printername, devmode,
7004 &printer->info_2->devmode))
7008 /* write the ASCII on disk */
7009 err = mod_a_printer(*printer, 2);
7010 if (!W_ERROR_IS_OK(err)) {
7011 free_a_printer(&printer,2);
7015 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7016 /* Handle open failed - remove addition. */
7017 del_a_printer(printer->info_2->sharename);
7018 free_a_printer(&printer,2);
7019 return WERR_ACCESS_DENIED;
7022 update_c_setprinter(False);
7023 free_a_printer(&printer,2);
7028 /****************************************************************************
7029 ****************************************************************************/
7031 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7033 UNISTR2 *uni_srv_name = &q_u->server_name;
7034 uint32 level = q_u->level;
7035 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7036 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7037 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7038 uint32 user_switch = q_u->user_switch;
7039 SPOOL_USER_CTR *user = &q_u->user_ctr;
7040 POLICY_HND *handle = &r_u->handle;
7044 /* we don't handle yet */
7045 /* but I know what to do ... */
7046 return WERR_UNKNOWN_LEVEL;
7048 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7050 user_switch, user, handle);
7052 return WERR_UNKNOWN_LEVEL;
7056 /****************************************************************************
7057 ****************************************************************************/
7059 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7061 uint32 level = q_u->level;
7062 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7063 WERROR err = WERR_OK;
7064 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7065 struct current_user user;
7066 fstring driver_name;
7069 ZERO_STRUCT(driver);
7071 get_current_user(&user, p);
7073 if (!convert_printer_driver_info(info, &driver, level)) {
7078 DEBUG(5,("Cleaning driver's information\n"));
7079 err = clean_up_driver_struct(driver, level, &user);
7080 if (!W_ERROR_IS_OK(err))
7083 DEBUG(5,("Moving driver to final destination\n"));
7084 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7085 if (W_ERROR_IS_OK(err))
7086 err = WERR_ACCESS_DENIED;
7090 if (add_a_printer_driver(driver, level)!=0) {
7091 err = WERR_ACCESS_DENIED;
7095 /* BEGIN_ADMIN_LOG */
7098 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7099 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7100 fstrcpy(driver_name, driver.info_3->name);
7103 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7104 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7105 fstrcpy(driver_name, driver.info_6->name);
7111 * I think this is where he DrvUpgradePrinter() hook would be
7112 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7113 * server. Right now, we just need to send ourselves a message
7114 * to update each printer bound to this driver. --jerry
7117 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7118 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7123 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7124 * decide if the driver init data should be deleted. The rules are:
7125 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7126 * 2) delete init data only if there is no 2k/Xp driver
7127 * 3) always delete init data
7128 * The generalized rule is always use init data from the highest order driver.
7129 * It is necessary to follow the driver install by an initialization step to
7130 * finish off this process.
7133 version = driver.info_3->cversion;
7134 else if (level == 6)
7135 version = driver.info_6->version;
7140 * 9x printer driver - never delete init data
7143 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7148 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7149 * there is no 2k/Xp driver init data for this driver name.
7153 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7155 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7157 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7159 if (!del_driver_init(driver_name))
7160 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7163 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7165 free_a_printer_driver(driver1,3);
7166 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7173 * 2k or Xp printer driver - always delete init data
7176 if (!del_driver_init(driver_name))
7177 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7181 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7187 free_a_printer_driver(driver, level);
7191 /********************************************************************
7192 * spoolss_addprinterdriverex
7193 ********************************************************************/
7195 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7197 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7198 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7201 * we only support the semantics of AddPrinterDriver()
7202 * i.e. only copy files that are newer than existing ones
7205 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7206 return WERR_ACCESS_DENIED;
7208 ZERO_STRUCT(q_u_local);
7209 ZERO_STRUCT(r_u_local);
7211 /* just pass the information off to _spoolss_addprinterdriver() */
7212 q_u_local.server_name_ptr = q_u->server_name_ptr;
7213 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7214 q_u_local.level = q_u->level;
7215 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7217 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7220 /****************************************************************************
7221 ****************************************************************************/
7223 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7225 init_unistr(&info->name, name);
7228 /****************************************************************************
7229 ****************************************************************************/
7231 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7235 pstring short_archi;
7236 DRIVER_DIRECTORY_1 *info=NULL;
7238 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7240 if (get_short_archi(short_archi, long_archi)==False)
7241 return WERR_INVALID_ENVIRONMENT;
7243 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7246 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7248 DEBUG(4,("printer driver directory: [%s]\n", path));
7250 fill_driverdir_1(info, path);
7252 *needed += spoolss_size_driverdir_info_1(info);
7254 if (!alloc_buffer_size(buffer, *needed)) {
7256 return WERR_INSUFFICIENT_BUFFER;
7259 smb_io_driverdir_1("", buffer, info, 0);
7263 if (*needed > offered)
7264 return WERR_INSUFFICIENT_BUFFER;
7269 /****************************************************************************
7270 ****************************************************************************/
7272 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7274 UNISTR2 *name = &q_u->name;
7275 UNISTR2 *uni_environment = &q_u->environment;
7276 uint32 level = q_u->level;
7277 NEW_BUFFER *buffer = NULL;
7278 uint32 offered = q_u->offered;
7279 uint32 *needed = &r_u->needed;
7281 /* that's an [in out] buffer */
7282 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7283 buffer = r_u->buffer;
7285 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7291 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7293 return WERR_UNKNOWN_LEVEL;
7297 /****************************************************************************
7298 ****************************************************************************/
7300 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7302 POLICY_HND *handle = &q_u->handle;
7303 uint32 idx = q_u->index;
7304 uint32 in_value_len = q_u->valuesize;
7305 uint32 in_data_len = q_u->datasize;
7306 uint32 *out_max_value_len = &r_u->valuesize;
7307 uint16 **out_value = &r_u->value;
7308 uint32 *out_value_len = &r_u->realvaluesize;
7309 uint32 *out_type = &r_u->type;
7310 uint32 *out_max_data_len = &r_u->datasize;
7311 uint8 **data_out = &r_u->data;
7312 uint32 *out_data_len = &r_u->realdatasize;
7314 NT_PRINTER_INFO_LEVEL *printer = NULL;
7317 uint32 biggest_valuesize;
7318 uint32 biggest_datasize;
7320 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7323 REGISTRY_VALUE *val;
7324 NT_PRINTER_DATA *p_data;
7325 int i, key_index, num_values;
7328 ZERO_STRUCT( printer );
7332 *out_max_data_len = 0;
7336 DEBUG(5,("spoolss_enumprinterdata\n"));
7339 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7343 if (!get_printer_snum(p,handle, &snum))
7346 result = get_a_printer(&printer, 2, lp_servicename(snum));
7347 if (!W_ERROR_IS_OK(result))
7350 p_data = &printer->info_2->data;
7351 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7356 * The NT machine wants to know the biggest size of value and data
7358 * cf: MSDN EnumPrinterData remark section
7361 if ( !in_value_len && !in_data_len )
7363 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7366 biggest_valuesize = 0;
7367 biggest_datasize = 0;
7369 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7371 for ( i=0; i<num_values; i++ )
7373 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7375 name_length = strlen(val->valuename);
7376 if ( strlen(val->valuename) > biggest_valuesize )
7377 biggest_valuesize = name_length;
7379 if ( val->size > biggest_datasize )
7380 biggest_datasize = val->size;
7382 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7386 /* the value is an UNICODE string but real_value_size is the length
7387 in bytes including the trailing 0 */
7389 *out_value_len = 2 * (1+biggest_valuesize);
7390 *out_data_len = biggest_datasize;
7392 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7398 * the value len is wrong in NT sp3
7399 * that's the number of bytes not the number of unicode chars
7402 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7407 /* out_value should default to "" or else NT4 has
7408 problems unmarshalling the response */
7410 *out_max_value_len = (in_value_len/sizeof(uint16));
7412 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7414 result = WERR_NOMEM;
7418 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7420 /* the data is counted in bytes */
7422 *out_max_data_len = in_data_len;
7423 *out_data_len = in_data_len;
7425 /* only allocate when given a non-zero data_len */
7427 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7429 result = WERR_NOMEM;
7433 result = WERR_NO_MORE_ITEMS;
7439 * - counted in bytes in the request
7440 * - counted in UNICODE chars in the max reply
7441 * - counted in bytes in the real size
7443 * take a pause *before* coding not *during* coding
7447 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7448 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7450 result = WERR_NOMEM;
7454 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7458 *out_type = regval_type( val );
7460 /* data - counted in bytes */
7462 *out_max_data_len = in_data_len;
7463 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7465 result = WERR_NOMEM;
7468 data_len = (size_t)regval_size(val);
7469 memcpy( *data_out, regval_data_p(val), data_len );
7470 *out_data_len = data_len;
7474 free_a_printer(&printer, 2);
7478 /****************************************************************************
7479 ****************************************************************************/
7481 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7483 POLICY_HND *handle = &q_u->handle;
7484 UNISTR2 *value = &q_u->value;
7485 uint32 type = q_u->type;
7486 uint8 *data = q_u->data;
7487 uint32 real_len = q_u->real_len;
7489 NT_PRINTER_INFO_LEVEL *printer = NULL;
7491 WERROR status = WERR_OK;
7492 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7495 DEBUG(5,("spoolss_setprinterdata\n"));
7498 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7502 if (!get_printer_snum(p,handle, &snum))
7506 * Access check : NT returns "access denied" if you make a
7507 * SetPrinterData call without the necessary privildge.
7508 * we were originally returning OK if nothing changed
7509 * which made Win2k issue **a lot** of SetPrinterData
7510 * when connecting to a printer --jerry
7513 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7515 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7516 status = WERR_ACCESS_DENIED;
7520 status = get_a_printer(&printer, 2, lp_servicename(snum));
7521 if (!W_ERROR_IS_OK(status))
7524 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7527 * When client side code sets a magic printer data key, detect it and save
7528 * the current printer data and the magic key's data (its the DEVMODE) for
7529 * future printer/driver initializations.
7531 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7533 /* Set devmode and printer initialization info */
7534 status = save_driver_init( printer, 2, data, real_len );
7536 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7540 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7541 type, data, real_len );
7542 if ( W_ERROR_IS_OK(status) )
7543 status = mod_a_printer(*printer, 2);
7547 free_a_printer(&printer, 2);
7552 /****************************************************************************
7553 ****************************************************************************/
7555 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7557 POLICY_HND *handle = &q_u->handle;
7558 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7561 DEBUG(5,("_spoolss_resetprinter\n"));
7564 * All we do is to check to see if the handle and queue is valid.
7565 * This call really doesn't mean anything to us because we only
7566 * support RAW printing. --jerry
7570 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7574 if (!get_printer_snum(p,handle, &snum))
7578 /* blindly return success */
7583 /****************************************************************************
7584 ****************************************************************************/
7586 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7588 POLICY_HND *handle = &q_u->handle;
7589 UNISTR2 *value = &q_u->valuename;
7591 NT_PRINTER_INFO_LEVEL *printer = NULL;
7593 WERROR status = WERR_OK;
7594 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7597 DEBUG(5,("spoolss_deleteprinterdata\n"));
7600 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7604 if (!get_printer_snum(p, handle, &snum))
7607 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7608 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7609 return WERR_ACCESS_DENIED;
7612 status = get_a_printer(&printer, 2, lp_servicename(snum));
7613 if (!W_ERROR_IS_OK(status))
7616 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7618 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7620 free_a_printer(&printer, 2);
7625 /****************************************************************************
7626 ****************************************************************************/
7628 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7630 POLICY_HND *handle = &q_u->handle;
7631 FORM *form = &q_u->form;
7632 nt_forms_struct tmpForm;
7634 WERROR status = WERR_OK;
7635 NT_PRINTER_INFO_LEVEL *printer = NULL;
7638 nt_forms_struct *list=NULL;
7639 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7641 DEBUG(5,("spoolss_addform\n"));
7644 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7649 /* forms can be added on printer of on the print server handle */
7651 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7653 if (!get_printer_snum(p,handle, &snum))
7656 status = get_a_printer(&printer, 2, lp_servicename(snum));
7657 if (!W_ERROR_IS_OK(status))
7661 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7662 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7663 status = WERR_ACCESS_DENIED;
7667 /* can't add if builtin */
7669 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7670 status = WERR_ALREADY_EXISTS;
7674 count = get_ntforms(&list);
7676 if(!add_a_form(&list, form, &count)) {
7677 status = WERR_NOMEM;
7681 write_ntforms(&list, count);
7684 * ChangeID must always be set if this is a printer
7687 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7688 status = mod_a_printer(*printer, 2);
7692 free_a_printer(&printer, 2);
7698 /****************************************************************************
7699 ****************************************************************************/
7701 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7703 POLICY_HND *handle = &q_u->handle;
7704 UNISTR2 *form_name = &q_u->name;
7705 nt_forms_struct tmpForm;
7707 nt_forms_struct *list=NULL;
7708 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7710 WERROR status = WERR_OK;
7711 NT_PRINTER_INFO_LEVEL *printer = NULL;
7713 DEBUG(5,("spoolss_deleteform\n"));
7716 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7720 /* forms can be deleted on printer of on the print server handle */
7722 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7724 if (!get_printer_snum(p,handle, &snum))
7727 status = get_a_printer(&printer, 2, lp_servicename(snum));
7728 if (!W_ERROR_IS_OK(status))
7732 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7733 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7734 status = WERR_ACCESS_DENIED;
7738 /* can't delete if builtin */
7740 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7741 status = WERR_INVALID_PARAM;
7745 count = get_ntforms(&list);
7747 if ( !delete_a_form(&list, form_name, &count, &status ))
7751 * ChangeID must always be set if this is a printer
7754 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7755 status = mod_a_printer(*printer, 2);
7759 free_a_printer(&printer, 2);
7765 /****************************************************************************
7766 ****************************************************************************/
7768 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7770 POLICY_HND *handle = &q_u->handle;
7771 FORM *form = &q_u->form;
7772 nt_forms_struct tmpForm;
7774 WERROR status = WERR_OK;
7775 NT_PRINTER_INFO_LEVEL *printer = NULL;
7778 nt_forms_struct *list=NULL;
7779 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7781 DEBUG(5,("spoolss_setform\n"));
7784 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7788 /* forms can be modified on printer of on the print server handle */
7790 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7792 if (!get_printer_snum(p,handle, &snum))
7795 status = get_a_printer(&printer, 2, lp_servicename(snum));
7796 if (!W_ERROR_IS_OK(status))
7800 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7801 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7802 status = WERR_ACCESS_DENIED;
7806 /* can't set if builtin */
7807 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7808 status = WERR_INVALID_PARAM;
7812 count = get_ntforms(&list);
7813 update_a_form(&list, form, count);
7814 write_ntforms(&list, count);
7817 * ChangeID must always be set if this is a printer
7820 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7821 status = mod_a_printer(*printer, 2);
7826 free_a_printer(&printer, 2);
7832 /****************************************************************************
7833 enumprintprocessors level 1.
7834 ****************************************************************************/
7836 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7838 PRINTPROCESSOR_1 *info_1=NULL;
7840 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7845 init_unistr(&info_1->name, "winprint");
7847 *needed += spoolss_size_printprocessor_info_1(info_1);
7849 if (!alloc_buffer_size(buffer, *needed))
7850 return WERR_INSUFFICIENT_BUFFER;
7852 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7856 if (*needed > offered) {
7858 return WERR_INSUFFICIENT_BUFFER;
7864 /****************************************************************************
7865 ****************************************************************************/
7867 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7869 uint32 level = q_u->level;
7870 NEW_BUFFER *buffer = NULL;
7871 uint32 offered = q_u->offered;
7872 uint32 *needed = &r_u->needed;
7873 uint32 *returned = &r_u->returned;
7875 /* that's an [in out] buffer */
7876 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7877 buffer = r_u->buffer;
7879 DEBUG(5,("spoolss_enumprintprocessors\n"));
7882 * Enumerate the print processors ...
7884 * Just reply with "winprint", to keep NT happy
7885 * and I can use my nice printer checker.
7893 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7895 return WERR_UNKNOWN_LEVEL;
7899 /****************************************************************************
7900 enumprintprocdatatypes level 1.
7901 ****************************************************************************/
7903 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7905 PRINTPROCDATATYPE_1 *info_1=NULL;
7907 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7912 init_unistr(&info_1->name, "RAW");
7914 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7916 if (!alloc_buffer_size(buffer, *needed))
7917 return WERR_INSUFFICIENT_BUFFER;
7919 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7923 if (*needed > offered) {
7925 return WERR_INSUFFICIENT_BUFFER;
7931 /****************************************************************************
7932 ****************************************************************************/
7934 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7936 uint32 level = q_u->level;
7937 NEW_BUFFER *buffer = NULL;
7938 uint32 offered = q_u->offered;
7939 uint32 *needed = &r_u->needed;
7940 uint32 *returned = &r_u->returned;
7942 /* that's an [in out] buffer */
7943 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7944 buffer = r_u->buffer;
7946 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7953 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7955 return WERR_UNKNOWN_LEVEL;
7959 /****************************************************************************
7960 enumprintmonitors level 1.
7961 ****************************************************************************/
7963 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7965 PRINTMONITOR_1 *info_1=NULL;
7967 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7972 init_unistr(&info_1->name, "Local Port");
7974 *needed += spoolss_size_printmonitor_info_1(info_1);
7976 if (!alloc_buffer_size(buffer, *needed))
7977 return WERR_INSUFFICIENT_BUFFER;
7979 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7983 if (*needed > offered) {
7985 return WERR_INSUFFICIENT_BUFFER;
7991 /****************************************************************************
7992 enumprintmonitors level 2.
7993 ****************************************************************************/
7995 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7997 PRINTMONITOR_2 *info_2=NULL;
7999 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8004 init_unistr(&info_2->name, "Local Port");
8005 init_unistr(&info_2->environment, "Windows NT X86");
8006 init_unistr(&info_2->dll_name, "localmon.dll");
8008 *needed += spoolss_size_printmonitor_info_2(info_2);
8010 if (!alloc_buffer_size(buffer, *needed))
8011 return WERR_INSUFFICIENT_BUFFER;
8013 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8017 if (*needed > offered) {
8019 return WERR_INSUFFICIENT_BUFFER;
8025 /****************************************************************************
8026 ****************************************************************************/
8028 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8030 uint32 level = q_u->level;
8031 NEW_BUFFER *buffer = NULL;
8032 uint32 offered = q_u->offered;
8033 uint32 *needed = &r_u->needed;
8034 uint32 *returned = &r_u->returned;
8036 /* that's an [in out] buffer */
8037 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8038 buffer = r_u->buffer;
8040 DEBUG(5,("spoolss_enumprintmonitors\n"));
8043 * Enumerate the print monitors ...
8045 * Just reply with "Local Port", to keep NT happy
8046 * and I can use my nice printer checker.
8054 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8056 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8058 return WERR_UNKNOWN_LEVEL;
8062 /****************************************************************************
8063 ****************************************************************************/
8065 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8069 JOB_INFO_1 *info_1=NULL;
8071 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8073 if (info_1 == NULL) {
8078 for (i=0; i<count && found==False; i++) {
8079 if (queue[i].job==(int)jobid)
8086 /* NT treats not found as bad param... yet another bad choice */
8087 return WERR_INVALID_PARAM;
8090 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8092 *needed += spoolss_size_job_info_1(info_1);
8094 if (!alloc_buffer_size(buffer, *needed)) {
8096 return WERR_INSUFFICIENT_BUFFER;
8099 smb_io_job_info_1("", buffer, info_1, 0);
8103 if (*needed > offered)
8104 return WERR_INSUFFICIENT_BUFFER;
8109 /****************************************************************************
8110 ****************************************************************************/
8112 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8117 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8119 DEVICEMODE *devmode = NULL;
8120 NT_DEVICEMODE *nt_devmode = NULL;
8122 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8124 ZERO_STRUCTP(info_2);
8126 if (info_2 == NULL) {
8131 for ( i=0; i<count && found==False; i++ )
8133 if (queue[i].job == (int)jobid)
8139 /* NT treats not found as bad param... yet another bad
8141 ret = WERR_INVALID_PARAM;
8145 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
8146 if (!W_ERROR_IS_OK(ret))
8150 * if the print job does not have a DEVMODE associated with it,
8151 * just use the one for the printer. A NULL devicemode is not
8152 * a failure condition
8155 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8156 devmode = construct_dev_mode(snum);
8158 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8159 ZERO_STRUCTP( devmode );
8160 convert_nt_devicemode( devmode, nt_devmode );
8164 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8166 *needed += spoolss_size_job_info_2(info_2);
8168 if (!alloc_buffer_size(buffer, *needed)) {
8169 ret = WERR_INSUFFICIENT_BUFFER;
8173 smb_io_job_info_2("", buffer, info_2, 0);
8175 if (*needed > offered) {
8176 ret = WERR_INSUFFICIENT_BUFFER;
8183 /* Cleanup allocated memory */
8185 free_job_info_2(info_2); /* Also frees devmode */
8187 free_a_printer(&ntprinter, 2);
8192 /****************************************************************************
8193 ****************************************************************************/
8195 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8197 POLICY_HND *handle = &q_u->handle;
8198 uint32 jobid = q_u->jobid;
8199 uint32 level = q_u->level;
8200 NEW_BUFFER *buffer = NULL;
8201 uint32 offered = q_u->offered;
8202 uint32 *needed = &r_u->needed;
8203 WERROR wstatus = WERR_OK;
8207 print_queue_struct *queue = NULL;
8208 print_status_struct prt_status;
8210 /* that's an [in out] buffer */
8211 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8212 buffer = r_u->buffer;
8214 DEBUG(5,("spoolss_getjob\n"));
8218 if (!get_printer_snum(p, handle, &snum))
8221 count = print_queue_status(snum, &queue, &prt_status);
8223 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8224 count, prt_status.status, prt_status.message));
8228 wstatus = getjob_level_1(queue, count, snum, jobid,
8229 buffer, offered, needed);
8232 wstatus = getjob_level_2(queue, count, snum, jobid,
8233 buffer, offered, needed);
8236 wstatus = WERR_UNKNOWN_LEVEL;
8244 /********************************************************************
8245 spoolss_getprinterdataex
8247 From MSDN documentation of GetPrinterDataEx: pass request
8248 to GetPrinterData if key is "PrinterDriverData".
8249 ********************************************************************/
8251 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8253 POLICY_HND *handle = &q_u->handle;
8254 uint32 in_size = q_u->size;
8255 uint32 *type = &r_u->type;
8256 uint32 *out_size = &r_u->size;
8257 uint8 **data = &r_u->data;
8258 uint32 *needed = &r_u->needed;
8259 fstring keyname, valuename;
8261 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8263 NT_PRINTER_INFO_LEVEL *printer = NULL;
8265 WERROR status = WERR_OK;
8267 DEBUG(4,("_spoolss_getprinterdataex\n"));
8269 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8270 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8272 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8273 keyname, valuename));
8275 /* in case of problem, return some default values */
8279 *out_size = in_size;
8282 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8283 status = WERR_BADFID;
8287 /* Is the handle to a printer or to the server? */
8289 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8290 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8291 status = WERR_INVALID_PARAM;
8295 if ( !get_printer_snum(p,handle, &snum) )
8298 status = get_a_printer(&printer, 2, lp_servicename(snum));
8299 if ( !W_ERROR_IS_OK(status) )
8302 /* check to see if the keyname is valid */
8303 if ( !strlen(keyname) ) {
8304 status = WERR_INVALID_PARAM;
8308 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8309 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8310 free_a_printer( &printer, 2 );
8311 status = WERR_BADFILE;
8315 /* When given a new keyname, we should just create it */
8317 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8319 if (*needed > *out_size)
8320 status = WERR_MORE_DATA;
8323 if ( !W_ERROR_IS_OK(status) )
8325 DEBUG(5, ("error: allocating %d\n", *out_size));
8327 /* reply this param doesn't exist */
8331 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8332 status = WERR_NOMEM;
8342 free_a_printer( &printer, 2 );
8347 /********************************************************************
8348 * spoolss_setprinterdataex
8349 ********************************************************************/
8351 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8353 POLICY_HND *handle = &q_u->handle;
8354 uint32 type = q_u->type;
8355 uint8 *data = q_u->data;
8356 uint32 real_len = q_u->real_len;
8358 NT_PRINTER_INFO_LEVEL *printer = NULL;
8360 WERROR status = WERR_OK;
8361 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8366 DEBUG(4,("_spoolss_setprinterdataex\n"));
8368 /* From MSDN documentation of SetPrinterDataEx: pass request to
8369 SetPrinterData if key is "PrinterDriverData" */
8372 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8376 if ( !get_printer_snum(p,handle, &snum) )
8380 * Access check : NT returns "access denied" if you make a
8381 * SetPrinterData call without the necessary privildge.
8382 * we were originally returning OK if nothing changed
8383 * which made Win2k issue **a lot** of SetPrinterData
8384 * when connecting to a printer --jerry
8387 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8389 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8390 return WERR_ACCESS_DENIED;
8393 status = get_a_printer(&printer, 2, lp_servicename(snum));
8394 if (!W_ERROR_IS_OK(status))
8397 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8398 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8400 /* check for OID in valuename */
8402 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8408 /* save the registry data */
8410 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8412 /* save the OID if one was specified and the previous set call succeeded */
8414 if ( W_ERROR_IS_OK(status) && oid_string )
8417 fstrcat( keyname, "\\" );
8418 fstrcat( keyname, SPOOL_OID_KEY );
8421 * I'm not checking the status here on purpose. Don't know
8422 * if this is right, but I'm returning the status from the
8423 * previous set_printer_dataex() call. I have no idea if
8424 * this is right. --jerry
8427 set_printer_dataex( printer, keyname, valuename,
8428 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8431 free_a_printer(&printer, 2);
8437 /********************************************************************
8438 * spoolss_deleteprinterdataex
8439 ********************************************************************/
8441 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8443 POLICY_HND *handle = &q_u->handle;
8444 UNISTR2 *value = &q_u->valuename;
8445 UNISTR2 *key = &q_u->keyname;
8447 NT_PRINTER_INFO_LEVEL *printer = NULL;
8449 WERROR status = WERR_OK;
8450 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8451 pstring valuename, keyname;
8453 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8456 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8460 if (!get_printer_snum(p, handle, &snum))
8463 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8464 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8465 return WERR_ACCESS_DENIED;
8468 status = get_a_printer(&printer, 2, lp_servicename(snum));
8469 if (!W_ERROR_IS_OK(status))
8472 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8473 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8475 status = delete_printer_dataex( printer, keyname, valuename );
8477 free_a_printer(&printer, 2);
8482 /********************************************************************
8483 * spoolss_enumprinterkey
8484 ********************************************************************/
8487 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8490 fstring *keynames = NULL;
8491 uint16 *enumkeys = NULL;
8494 POLICY_HND *handle = &q_u->handle;
8495 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8496 NT_PRINTER_DATA *data;
8497 NT_PRINTER_INFO_LEVEL *printer = NULL;
8499 WERROR status = WERR_BADFILE;
8502 DEBUG(4,("_spoolss_enumprinterkey\n"));
8505 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8509 if ( !get_printer_snum(p,handle, &snum) )
8512 status = get_a_printer(&printer, 2, lp_servicename(snum));
8513 if (!W_ERROR_IS_OK(status))
8516 /* get the list of subkey names */
8518 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8519 data = &printer->info_2->data;
8521 num_keys = get_printer_subkeys( data, key, &keynames );
8523 if ( num_keys == -1 ) {
8524 status = WERR_BADFILE;
8528 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8530 r_u->needed = printerkey_len*2;
8532 if ( q_u->size < r_u->needed ) {
8533 status = WERR_MORE_DATA;
8537 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8538 status = WERR_NOMEM;
8544 if ( q_u->size < r_u->needed )
8545 status = WERR_MORE_DATA;
8548 free_a_printer( &printer, 2 );
8549 SAFE_FREE( keynames );
8554 /********************************************************************
8555 * spoolss_deleteprinterkey
8556 ********************************************************************/
8558 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8560 POLICY_HND *handle = &q_u->handle;
8561 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8563 NT_PRINTER_INFO_LEVEL *printer = NULL;
8567 DEBUG(5,("spoolss_deleteprinterkey\n"));
8570 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8574 /* if keyname == NULL, return error */
8576 if ( !q_u->keyname.buffer )
8577 return WERR_INVALID_PARAM;
8579 if (!get_printer_snum(p, handle, &snum))
8582 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8583 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8584 return WERR_ACCESS_DENIED;
8587 status = get_a_printer(&printer, 2, lp_servicename(snum));
8588 if (!W_ERROR_IS_OK(status))
8591 /* delete the key and all subneys */
8593 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8595 status = delete_all_printer_data( printer->info_2, key );
8597 if ( W_ERROR_IS_OK(status) )
8598 status = mod_a_printer(*printer, 2);
8600 free_a_printer( &printer, 2 );
8606 /********************************************************************
8607 * spoolss_enumprinterdataex
8608 ********************************************************************/
8610 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8612 POLICY_HND *handle = &q_u->handle;
8613 uint32 in_size = q_u->size;
8616 NT_PRINTER_INFO_LEVEL *printer = NULL;
8617 PRINTER_ENUM_VALUES *enum_values = NULL;
8618 NT_PRINTER_DATA *p_data;
8620 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8625 REGISTRY_VALUE *val;
8630 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8633 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8637 /* first get the printer off of disk */
8639 if (!get_printer_snum(p,handle, &snum))
8642 ZERO_STRUCT(printer);
8643 result = get_a_printer(&printer, 2, lp_servicename(snum));
8644 if (!W_ERROR_IS_OK(result))
8647 /* now look for a match on the key name */
8649 p_data = &printer->info_2->data;
8651 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8652 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8654 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8655 result = WERR_INVALID_PARAM;
8662 /* allocate the memory for the array of pointers -- if necessary */
8664 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8667 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8669 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8670 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8671 result = WERR_NOMEM;
8675 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8679 * loop through all params and build the array to pass
8680 * back to the client
8683 for ( i=0; i<num_entries; i++ )
8685 /* lookup the registry value */
8687 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8688 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8692 value_name = regval_name( val );
8693 init_unistr( &enum_values[i].valuename, value_name );
8694 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8695 enum_values[i].type = regval_type( val );
8697 data_len = regval_size( val );
8699 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8701 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8703 result = WERR_NOMEM;
8707 enum_values[i].data_len = data_len;
8709 /* keep track of the size of the array in bytes */
8711 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8714 /* housekeeping information in the reply */
8716 r_u->needed = needed;
8717 r_u->returned = num_entries;
8719 if (needed > in_size) {
8720 result = WERR_MORE_DATA;
8724 /* copy data into the reply */
8726 r_u->ctr.size = r_u->needed;
8727 r_u->ctr.size_of_array = r_u->returned;
8728 r_u->ctr.values = enum_values;
8733 free_a_printer(&printer, 2);
8738 /****************************************************************************
8739 ****************************************************************************/
8741 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8743 init_unistr(&info->name, name);
8746 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8747 UNISTR2 *environment,
8754 pstring short_archi;
8755 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8757 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8759 if (get_short_archi(short_archi, long_archi)==False)
8760 return WERR_INVALID_ENVIRONMENT;
8762 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8765 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8767 fill_printprocessordirectory_1(info, path);
8769 *needed += spoolss_size_printprocessordirectory_info_1(info);
8771 if (!alloc_buffer_size(buffer, *needed)) {
8773 return WERR_INSUFFICIENT_BUFFER;
8776 smb_io_printprocessordirectory_1("", buffer, info, 0);
8780 if (*needed > offered)
8781 return WERR_INSUFFICIENT_BUFFER;
8786 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8788 uint32 level = q_u->level;
8789 NEW_BUFFER *buffer = NULL;
8790 uint32 offered = q_u->offered;
8791 uint32 *needed = &r_u->needed;
8794 /* that's an [in out] buffer */
8795 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8796 buffer = r_u->buffer;
8798 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8804 result = getprintprocessordirectory_level_1
8805 (&q_u->name, &q_u->environment, buffer, offered, needed);
8808 result = WERR_UNKNOWN_LEVEL;
8816 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
8817 SPOOL_R_REPLYOPENPRINTER *r_u)
8819 DEBUG(5,("_spoolss_replyopenprinter\n"));
8821 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
8826 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
8827 SPOOL_R_REPLYCLOSEPRINTER *r_u)
8829 DEBUG(5,("_spoolss_replycloseprinter\n"));