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,
8 * Copyright (C) Gerald Carter 2000-2001,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 #ifndef MAX_OPEN_PRINTER_EXS
32 #define MAX_OPEN_PRINTER_EXS 50
35 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
36 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
37 #define PRINTER_HANDLE_IS_PRINTER 0
38 #define PRINTER_HANDLE_IS_PRINTSERVER 1
40 /* Table to map the driver version */
42 char * drv_ver_to_os[] = {
43 "WIN9X", /* driver version/cversion 0 */
45 "WINNT", /* driver version/cversion 2 */
46 "WIN2K", /* driver version/cversion 3 */
56 /* structure to store the printer handles */
57 /* and a reference to what it's pointing to */
58 /* and the notify info asked about */
59 /* that's the central struct */
60 typedef struct _Printer{
61 struct _Printer *prev, *next;
62 BOOL document_started;
64 int jobid; /* jobid in printing backend */
68 fstring printerservername;
71 uint32 access_granted;
77 SPOOL_NOTIFY_OPTION *option;
78 POLICY_HND client_hnd;
79 uint32 client_connected;
87 static Printer_entry *printers_list;
89 typedef struct _counter_printer_0 {
97 static ubi_dlList counter_list;
99 static struct cli_state cli;
100 static uint32 smb_connections=0;
103 /* in printing/nt_printing.c */
105 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
107 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
108 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
110 /* translate between internal status numbers and NT status numbers */
111 static int nt_printj_status(int v)
117 return JOB_STATUS_PAUSED;
119 return JOB_STATUS_SPOOLING;
121 return JOB_STATUS_PRINTING;
123 return JOB_STATUS_ERROR;
125 return JOB_STATUS_DELETING;
127 return JOB_STATUS_OFFLINE;
129 return JOB_STATUS_PAPEROUT;
131 return JOB_STATUS_PRINTED;
133 return JOB_STATUS_DELETED;
135 return JOB_STATUS_BLOCKED;
136 case LPQ_USER_INTERVENTION:
137 return JOB_STATUS_USER_INTERVENTION;
142 static int nt_printq_status(int v)
146 return PRINTER_STATUS_PAUSED;
155 /****************************************************************************
156 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
157 ****************************************************************************/
159 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
164 SAFE_FREE((*pp)->ctr.type);
168 /***************************************************************************
169 Disconnect from the client
170 ****************************************************************************/
172 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
176 /* weird if the test succeds !!! */
177 if (smb_connections==0) {
178 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
182 result = cli_spoolss_reply_close_printer(&cli, cli.mem_ctx, handle);
184 if (!W_ERROR_IS_OK(result))
185 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
186 dos_errstr(result)));
188 /* if it's the last connection, deconnect the IPC$ share */
189 if (smb_connections==1) {
190 if(!spoolss_disconnect_from_client(&cli))
193 message_deregister(MSG_PRINTER_NOTIFY);
199 /****************************************************************************
200 Functions to free a printer entry datastruct.
201 ****************************************************************************/
203 static void free_printer_entry(void *ptr)
205 Printer_entry *Printer = (Printer_entry *)ptr;
207 if (Printer->notify.client_connected==True)
208 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
210 Printer->notify.flags=0;
211 Printer->notify.options=0;
212 Printer->notify.localmachine[0]='\0';
213 Printer->notify.printerlocal=0;
214 free_spool_notify_option(&Printer->notify.option);
215 Printer->notify.option=NULL;
216 Printer->notify.client_connected=False;
218 /* Remove from the internal list. */
219 DLIST_REMOVE(printers_list, Printer);
224 /****************************************************************************
225 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
226 ****************************************************************************/
228 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
230 SPOOL_NOTIFY_OPTION *new_sp = NULL;
235 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
242 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
244 if (!new_sp->ctr.type) {
253 /****************************************************************************
254 find printer index by handle
255 ****************************************************************************/
257 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
259 Printer_entry *find_printer = NULL;
261 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
262 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
269 /****************************************************************************
270 Close printer index by handle.
271 ****************************************************************************/
273 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
275 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
278 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
282 close_policy_hnd(p, hnd);
287 /****************************************************************************
288 Delete a printer given a handle.
289 ****************************************************************************/
291 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
293 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
296 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
300 if (del_a_printer(Printer->dev.handlename) != 0) {
301 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
305 /* Check calling user has permission to delete printer. Note that
306 since we set the snum parameter to -1 only administrators can
307 delete the printer. This stops people with the Full Control
308 permission from deleting the printer. */
310 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
311 DEBUG(3, ("printer delete denied by security descriptor\n"));
312 return WERR_ACCESS_DENIED;
315 if (*lp_deleteprinter_cmd()) {
317 char *cmd = lp_deleteprinter_cmd();
322 /* Printer->dev.handlename equals portname equals sharename */
323 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
324 Printer->dev.handlename);
326 DEBUG(10,("Running [%s]\n", command));
327 ret = smbrun(command, NULL);
329 return WERR_BADFID; /* What to return here? */
331 DEBUGADD(10,("returned [%d]\n", ret));
333 /* Send SIGHUP to process group... is there a better way? */
336 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
340 return WERR_ACCESS_DENIED;
346 /****************************************************************************
347 Return the snum of a printer corresponding to an handle.
348 ****************************************************************************/
350 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
355 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
359 switch (Printer->printer_type) {
360 case PRINTER_HANDLE_IS_PRINTER:
361 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
362 *number = print_queue_snum(Printer->dev.handlename);
363 return (*number != -1);
364 case PRINTER_HANDLE_IS_PRINTSERVER:
371 /****************************************************************************
372 Set printer handle type.
373 Check if it's \\server or \\server\printer
374 ****************************************************************************/
376 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
378 DEBUG(3,("Setting printer type=%s\n", handlename));
380 if ( strlen(handlename) < 3 ) {
381 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
385 /* it's a print server */
386 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
387 DEBUGADD(4,("Printer is a print server\n"));
388 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
392 DEBUGADD(4,("Printer is a printer\n"));
393 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
399 /****************************************************************************
400 Set printer handle name.
401 ****************************************************************************/
403 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
406 int n_services=lp_numservices();
411 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
413 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
414 ZERO_STRUCT(Printer->dev.printerservername);
415 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
419 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
422 if (*handlename=='\\') {
423 aprinter=strchr_m(handlename+2, '\\');
430 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
433 * The original code allowed smbd to store a printer name that
434 * was different from the share name. This is not possible
435 * anymore, so I've simplified this loop greatly. Here
436 * we are just verifying that the printer name is a valid
437 * printer service defined in smb.conf
438 * --jerry [Fri Feb 15 11:17:46 CST 2002]
441 for (snum=0; snum<n_services; snum++) {
443 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
446 fstrcpy(sname, lp_servicename(snum));
448 DEBUGADD(5,("share:%s\n",sname));
450 if (! StrCaseCmp(sname, aprinter)) {
459 DEBUGADD(4,("Printer not found\n"));
463 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
465 ZERO_STRUCT(Printer->dev.handlename);
466 fstrcpy(Printer->dev.handlename, sname);
471 /****************************************************************************
472 Find first available printer slot. creates a printer handle for you.
473 ****************************************************************************/
475 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
477 Printer_entry *new_printer;
479 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
481 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
484 ZERO_STRUCTP(new_printer);
486 new_printer->notify.option=NULL;
488 /* Add to the internal list. */
489 DLIST_ADD(printers_list, new_printer);
491 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
492 SAFE_FREE(new_printer);
496 if (!set_printer_hnd_printertype(new_printer, name)) {
497 close_printer_handle(p, hnd);
501 if (!set_printer_hnd_name(new_printer, name)) {
502 close_printer_handle(p, hnd);
506 new_printer->access_granted = access_granted;
508 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
513 /****************************************************************************
514 Allocate more memory for a BUFFER.
515 ****************************************************************************/
517 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
525 /* damn, I'm doing the reverse operation of prs_grow() :) */
526 if (buffer_size < prs_data_size(ps))
529 extra_space = buffer_size - prs_data_size(ps);
532 * save the offset and move to the end of the buffer
533 * prs_grow() checks the extra_space against the offset
535 old_offset=prs_offset(ps);
536 prs_set_offset(ps, prs_data_size(ps));
538 if (!prs_grow(ps, extra_space))
541 prs_set_offset(ps, old_offset);
543 buffer->string_at_end=prs_data_size(ps);
547 /***************************************************************************
548 Always give preference Printer_entry.notify.option over
549 Printer_entry.notify.flags. Return True if we should send notification
550 events using SPOOLSS_RRPCN. False means that we should use
551 SPOOLSS_ROUTERREPLYPRINTER.
552 **************************************************************************/
553 static BOOL valid_notify_options(Printer_entry *printer)
555 if (printer->notify.option == NULL)
561 /***************************************************************************
562 Simple check to see if the client motify handle is set to watch for events
563 represented by 'flags'
565 FIXME!!!! only a stub right now --jerry
566 **************************************************************************/
568 static BOOL is_client_monitoring_event(Printer_entry *p, uint32 flags)
574 /***************************************************************************
575 Server wrapper for cli_spoolss_routerreplyprinter() since the client
576 function can only send a single change notification at a time.
578 FIXME!!! only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
580 **************************************************************************/
582 static WERROR srv_spoolss_routerreplyprinter (struct cli_state *reply_cli, TALLOC_CTX *mem_ctx,
583 POLICY_HND *pol, PRINTER_MESSAGE_INFO *info,
584 NT_PRINTER_INFO_LEVEL *printer)
587 uint32 condition = 0x0;
589 if (info->flags & PRINTER_MESSAGE_DRIVER)
590 condition = PRINTER_CHANGE_SET_PRINTER_DRIVER;
592 result = cli_spoolss_routerreplyprinter(reply_cli, mem_ctx, pol, condition,
593 printer->info_2->changeid);
598 /***********************************************************************
599 Wrapper around the decision of which RPC use to in the change
601 **********************************************************************/
603 static WERROR srv_spoolss_send_event_to_client(Printer_entry* Printer,
604 struct cli_state *send_cli, PRINTER_MESSAGE_INFO *msg,
605 NT_PRINTER_INFO_LEVEL *info)
609 if (valid_notify_options(Printer)) {
610 /* This is a single call that can send information about multiple changes */
611 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
612 msg->flags |= PRINTER_MESSAGE_ATTRIBUTES;
614 result = cli_spoolss_reply_rrpcn(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd,
618 /* This requires that the server send an individual event notification for each change */
619 result = srv_spoolss_routerreplyprinter(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd,
627 /***********************************************************************
628 Send a change notication message on all handles which have a call
630 **********************************************************************/
632 static void send_spoolss_event_notification(PRINTER_MESSAGE_INFO *msg)
634 Printer_entry *find_printer;
636 NT_PRINTER_INFO_LEVEL *printer = NULL;
639 DEBUG(0,("send_spoolss_event_notification: NULL msg pointer!\n"));
643 for(find_printer = printers_list; find_printer; find_printer = find_printer->next) {
646 * If the entry has a connected client we send the message. There should
647 * only be one of these normally when dealing with the NT/2k spooler.
648 * However, iterate over all to make sure we deal with user applications
649 * in addition to spooler service.
651 * While we are only maintaining a single connection to the client,
652 * the FindFirstPrinterChangeNotification() call is made on a printer
653 * handle, so "client_connected" represents the whether or not the
654 * client asked for change notication on this handle.
659 if (find_printer->notify.client_connected==True) {
661 /* does the client care about what changed? */
663 if (msg->flags && !is_client_monitoring_event(find_printer, msg->flags)) {
664 DEBUG(10,("send_spoolss_event_notification: Client [%s] not monitoring these events\n",
665 find_printer->client.machine));
669 if (find_printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
670 DEBUG(10,("send_spoolss_event_notification: printserver [%s]\n", find_printer->dev.printerservername ));
672 DEBUG(10,("send_spoolss_event_notification: printer [%s]\n", find_printer->dev.handlename));
675 * if handle is a printer, only send if the printer_name matches.
676 * ...else if handle is a printerserver, send to all
679 if (*msg->printer_name && (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
680 && !strequal(msg->printer_name, find_printer->dev.handlename))
682 DEBUG(10,("send_spoolss_event_notification: ignoring message sent to %s [%s]\n",
683 msg->printer_name, find_printer->dev.handlename ));
688 /* lookup the printer if we have a name if we don't already have a
689 valid NT_PRINTER_INFO_LEVEL structure. And yes I'm assuming we
690 will always have a non-empty msg.printer_name */
692 if (!printer || !printer->info_2 || strcmp(msg->printer_name, printer->info_2->printername))
696 free_a_printer(&printer, 2);
700 result = get_a_printer(&printer, 2, msg->printer_name);
701 if (!W_ERROR_IS_OK(result))
705 /* issue the client call */
707 result = srv_spoolss_send_event_to_client(find_printer, &cli, msg, printer);
709 if (!W_ERROR_IS_OK(result)) {
710 DEBUG(5,("send_spoolss_event_notification: Event notification failed [%s]\n",
711 dos_errstr(result)));
718 /***************************************************************************
719 Receive the notify message and decode the message. Do not send
720 notification if we sent this originally as that would result in
722 ****************************************************************************/
724 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
726 PRINTER_MESSAGE_INFO msg;
728 if (len < sizeof(msg)) {
729 DEBUG(2,("srv_spoolss_receive_message: got incorrect message size (%u)!\n", (unsigned int)len));
733 memcpy(&msg, buf, sizeof(PRINTER_MESSAGE_INFO));
735 DEBUG(10,("srv_spoolss_receive_message: Got message printer change [queue = %s] low=0x%x high=0x%x flags=0x%x\n",
736 msg.printer_name, (unsigned int)msg.low, (unsigned int)msg.high, msg.flags ));
738 /* Iterate the printer list */
740 send_spoolss_event_notification(&msg);
744 /***************************************************************************
746 ****************************************************************************/
748 static BOOL srv_spoolss_sendnotify(char* printer_name, uint32 high, uint32 low, uint32 flags)
750 char msg[sizeof(PRINTER_MESSAGE_INFO)];
751 PRINTER_MESSAGE_INFO info;
758 fstrcpy(info.printer_name, printer_name);
760 memcpy(msg, &info, sizeof(PRINTER_MESSAGE_INFO));
762 DEBUG(10,("srv_spoolss_sendnotify: printer change low=0x%x high=0x%x [%s], flags=0x%x\n",
763 low, high, printer_name, flags));
765 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, msg, sizeof(PRINTER_MESSAGE_INFO),
771 /********************************************************************
772 Send a message to ourself about new driver being installed
773 so we can upgrade the information for each printer bound to this
775 ********************************************************************/
777 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
779 int len = strlen(drivername);
784 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
787 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
791 /**********************************************************************
792 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
793 over all printers, upgrading ones as neessary
794 **********************************************************************/
796 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
800 int n_services = lp_numservices();
802 len = MIN(len,sizeof(drivername)-1);
803 strncpy(drivername, buf, len);
805 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
807 /* Iterate the printer list */
809 for (snum=0; snum<n_services; snum++) {
810 if (lp_snum_ok(snum) && lp_print_ok(snum) ) {
812 NT_PRINTER_INFO_LEVEL *printer = NULL;
814 result = get_a_printer(&printer, 2, lp_servicename(snum));
815 if (!W_ERROR_IS_OK(result))
818 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername)) {
819 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
820 /* all we care about currently is the change_id */
821 result = mod_a_printer(*printer, 2);
822 if (!W_ERROR_IS_OK(result)) {
823 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
824 dos_errstr(result)));
827 free_a_printer(&printer, 2);
834 /********************************************************************
835 Copy routines used by convert_to_openprinterex()
836 *******************************************************************/
838 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
846 DEBUG (8,("dup_devmode\n"));
848 /* bulk copy first */
850 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
854 /* dup the pointer members separately */
856 len = unistrlen(devmode->devicename.buffer);
858 d->devicename.buffer = talloc(ctx, len*2);
859 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
864 len = unistrlen(devmode->formname.buffer);
866 d->devicename.buffer = talloc(ctx, len*2);
867 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
871 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
876 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
878 if (!new_ctr || !ctr)
881 DEBUG(8,("copy_devmode_ctr\n"));
883 new_ctr->size = ctr->size;
884 new_ctr->devmode_ptr = ctr->devmode_ptr;
887 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
890 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
892 if (!new_def || !def)
895 DEBUG(8,("copy_printer_defaults\n"));
897 new_def->datatype_ptr = def->datatype_ptr;
899 if (def->datatype_ptr)
900 copy_unistr2(&new_def->datatype, &def->datatype);
902 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
904 new_def->access_required = def->access_required;
907 /********************************************************************
908 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
909 * SPOOL_Q_OPEN_PRINTER_EX structure
910 ********************************************************************/
912 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
917 DEBUG(8,("convert_to_openprinterex\n"));
919 q_u_ex->printername_ptr = q_u->printername_ptr;
921 if (q_u->printername_ptr)
922 copy_unistr2(&q_u_ex->printername, &q_u->printername);
924 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
927 /********************************************************************
928 * spoolss_open_printer
930 * called from the spoolss dispatcher
931 ********************************************************************/
933 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
935 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
936 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
944 /* convert the OpenPrinter() call to OpenPrinterEx() */
946 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
948 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
950 /* convert back to OpenPrinter() */
952 memcpy(r_u, &r_u_ex, sizeof(*r_u));
957 /********************************************************************
958 * spoolss_open_printer
960 * called from the spoolss dispatcher
961 ********************************************************************/
963 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
965 UNISTR2 *printername = NULL;
966 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
967 /* uint32 user_switch = q_u->user_switch; - notused */
968 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
969 POLICY_HND *handle = &r_u->handle;
973 struct current_user user;
974 Printer_entry *Printer=NULL;
976 if (q_u->printername_ptr != 0)
977 printername = &q_u->printername;
979 if (printername == NULL)
980 return WERR_INVALID_PRINTER_NAME;
982 /* some sanity check because you can open a printer or a print server */
983 /* aka: \\server\printer or \\server */
984 unistr2_to_ascii(name, printername, sizeof(name)-1);
986 DEBUGADD(3,("checking name: %s\n",name));
988 if (!open_printer_hnd(p, handle, name, 0))
989 return WERR_INVALID_PRINTER_NAME;
991 Printer=find_printer_index_by_hnd(p, handle);
993 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
994 Can't find printer handle we created for printer %s\n", name ));
995 close_printer_handle(p,handle);
996 return WERR_INVALID_PRINTER_NAME;
1000 if (printer_default->datatype_ptr != NULL)
1002 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
1003 set_printer_hnd_datatype(handle, datatype);
1006 set_printer_hnd_datatype(handle, "");
1010 First case: the user is opening the print server:
1012 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1013 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1015 Then both Win2k and WinNT clients try an OpenPrinterEx with
1016 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1017 or if the user is listed in the smb.conf printer admin parameter.
1019 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1020 client view printer folder, but does not show the MSAPW.
1022 Note: this test needs code to check access rights here too. Jeremy
1023 could you look at this?
1026 Second case: the user is opening a printer:
1027 NT doesn't let us connect to a printer if the connecting user
1028 doesn't have print permission.
1032 get_current_user(&user, p);
1034 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
1036 /* Printserver handles use global struct... */
1040 /* Map standard access rights to object specific access
1043 se_map_standard(&printer_default->access_required,
1044 &printserver_std_mapping);
1046 /* Deny any object specific bits that don't apply to print
1047 servers (i.e printer and job specific bits) */
1049 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1051 if (printer_default->access_required &
1052 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1053 DEBUG(3, ("access DENIED for non-printserver bits"));
1054 close_printer_handle(p, handle);
1055 return WERR_ACCESS_DENIED;
1058 /* Allow admin access */
1060 if (printer_default->access_required &
1061 SERVER_ACCESS_ADMINISTER) {
1063 if (!lp_ms_add_printer_wizard()) {
1064 close_printer_handle(p, handle);
1065 return WERR_ACCESS_DENIED;
1068 if (user.uid == 0 ||
1069 user_in_list(uidtoname(user.uid),
1070 lp_printer_admin(snum)))
1073 close_printer_handle(p, handle);
1074 return WERR_ACCESS_DENIED;
1077 /* We fall through to return WERR_OK */
1082 /* NT doesn't let us connect to a printer if the connecting user
1083 doesn't have print permission. */
1085 if (!get_printer_snum(p, handle, &snum))
1088 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1090 /* map an empty access mask to the minimum access mask */
1091 if (printer_default->access_required == 0x0)
1092 printer_default->access_required = PRINTER_ACCESS_USE;
1095 * If we are not serving the printer driver for this printer,
1096 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1097 * will keep NT clients happy --jerry
1100 if (lp_use_client_driver(snum)
1101 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1103 printer_default->access_required = PRINTER_ACCESS_USE;
1106 /* check smb.conf parameters and the the sec_desc */
1108 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1109 DEBUG(3, ("access DENIED for printer open\n"));
1110 close_printer_handle(p, handle);
1111 return WERR_ACCESS_DENIED;
1114 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1115 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1116 close_printer_handle(p, handle);
1117 return WERR_ACCESS_DENIED;
1120 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1121 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1123 printer_default->access_required = PRINTER_ACCESS_USE;
1125 DEBUG(4,("Setting printer access=%x\n", printer_default->access_required));
1126 Printer->access_granted = printer_default->access_required;
1129 * If we have a default device pointer in the
1130 * printer_default struct, then we need to get
1131 * the printer info from the tdb and if there is
1132 * no default devicemode there then we do a *SET*
1133 * here ! This is insanity.... JRA.
1137 * If the openprinterex rpc call contains a devmode,
1138 * it's a per-user one. This per-user devmode is derivated
1139 * from the global devmode. Openprinterex() contains a per-user
1140 * devmode for when you do EMF printing and spooling.
1141 * In the EMF case, the NT workstation is only doing half the job
1142 * of rendering the page. The other half is done by running the printer
1143 * driver on the server.
1144 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1145 * The EMF file only contains what is to be printed on the page.
1146 * So in order for the server to know how to print, the NT client sends
1147 * a devicemode attached to the openprinterex call.
1148 * But this devicemode is short lived, it's only valid for the current print job.
1150 * If Samba would have supported EMF spooling, this devicemode would
1151 * have been attached to the handle, to sent it to the driver to correctly
1152 * rasterize the EMF file.
1154 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1155 * we just act as a pass-thru between windows and the printer.
1157 * In order to know that Samba supports only RAW spooling, NT has to call
1158 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1159 * and until NT sends a RAW job, we refuse it.
1161 * But to call getprinter() or startdoc(), you first need a valid handle,
1162 * and to get an handle you have to call openprintex(). Hence why you have
1163 * a devicemode in the openprinterex() call.
1166 * Differences between NT4 and NT 2000.
1169 * On NT4, you only have a global devicemode. This global devicemode can be changed
1170 * by the administrator (or by a user with enough privs). Everytime a user
1171 * wants to print, the devicemode is resetted to the default. In Word, everytime
1172 * you print, the printer's characteristics are always reset to the global devicemode.
1176 * In W2K, there is the notion of per-user devicemode. The first time you use
1177 * a printer, a per-user devicemode is build from the global devicemode.
1178 * If you change your per-user devicemode, it is saved in the registry, under the
1179 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1180 * printer preferences available.
1182 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1183 * on the General Tab of the printer properties windows.
1185 * To change the global devicemode: it's the "Printing Defaults..." button
1186 * on the Advanced Tab of the printer properties window.
1194 if (printer_default->devmode_cont.devmode != NULL) {
1195 result = printer_write_default_dev( snum, printer_default);
1197 close_printer_handle(p, handle);
1207 /****************************************************************************
1208 ****************************************************************************/
1210 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1211 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1217 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1226 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1227 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1233 printer->info_3=NULL;
1234 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1238 printer->info_6=NULL;
1239 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1249 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
1250 NT_DEVICEMODE **pp_nt_devmode)
1252 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1255 * Ensure nt_devmode is a valid pointer
1256 * as we will be overwriting it.
1259 if (nt_devmode == NULL) {
1260 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1261 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1265 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1266 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1268 nt_devmode->specversion=devmode->specversion;
1269 nt_devmode->driverversion=devmode->driverversion;
1270 nt_devmode->size=devmode->size;
1271 nt_devmode->fields=devmode->fields;
1272 nt_devmode->orientation=devmode->orientation;
1273 nt_devmode->papersize=devmode->papersize;
1274 nt_devmode->paperlength=devmode->paperlength;
1275 nt_devmode->paperwidth=devmode->paperwidth;
1276 nt_devmode->scale=devmode->scale;
1277 nt_devmode->copies=devmode->copies;
1278 nt_devmode->defaultsource=devmode->defaultsource;
1279 nt_devmode->printquality=devmode->printquality;
1280 nt_devmode->color=devmode->color;
1281 nt_devmode->duplex=devmode->duplex;
1282 nt_devmode->yresolution=devmode->yresolution;
1283 nt_devmode->ttoption=devmode->ttoption;
1284 nt_devmode->collate=devmode->collate;
1286 nt_devmode->logpixels=devmode->logpixels;
1287 nt_devmode->bitsperpel=devmode->bitsperpel;
1288 nt_devmode->pelswidth=devmode->pelswidth;
1289 nt_devmode->pelsheight=devmode->pelsheight;
1290 nt_devmode->displayflags=devmode->displayflags;
1291 nt_devmode->displayfrequency=devmode->displayfrequency;
1292 nt_devmode->icmmethod=devmode->icmmethod;
1293 nt_devmode->icmintent=devmode->icmintent;
1294 nt_devmode->mediatype=devmode->mediatype;
1295 nt_devmode->dithertype=devmode->dithertype;
1296 nt_devmode->reserved1=devmode->reserved1;
1297 nt_devmode->reserved2=devmode->reserved2;
1298 nt_devmode->panningwidth=devmode->panningwidth;
1299 nt_devmode->panningheight=devmode->panningheight;
1302 * Only change private and driverextra if the incoming devmode
1303 * has a new one. JRA.
1306 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1307 SAFE_FREE(nt_devmode->private);
1308 nt_devmode->driverextra=devmode->driverextra;
1309 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1311 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1314 *pp_nt_devmode = nt_devmode;
1319 /********************************************************************
1320 * _spoolss_enddocprinter_internal.
1321 ********************************************************************/
1323 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1325 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1328 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1332 Printer->document_started=False;
1333 print_job_end(Printer->jobid,True);
1334 /* error codes unhandled so far ... */
1339 /********************************************************************
1340 * api_spoolss_closeprinter
1341 ********************************************************************/
1343 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1345 POLICY_HND *handle = &q_u->handle;
1347 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1349 if (Printer && Printer->document_started)
1350 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1352 if (!close_printer_handle(p, handle))
1355 /* clear the returned printer handle. Observed behavior
1356 from Win2k server. Don't think this really matters.
1357 Previous code just copied the value of the closed
1360 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1365 /********************************************************************
1366 * api_spoolss_deleteprinter
1368 ********************************************************************/
1370 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1372 POLICY_HND *handle = &q_u->handle;
1373 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1376 if (Printer && Printer->document_started)
1377 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1379 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1381 result = delete_printer_handle(p, handle);
1383 update_c_setprinter(False);
1385 if (W_ERROR_IS_OK(result)) {
1386 srv_spoolss_sendnotify(Printer->dev.handlename, 0, PRINTER_CHANGE_DELETE_PRINTER, 0x0);
1392 /*******************************************************************
1393 * static function to lookup the version id corresponding to an
1394 * long architecture string
1395 ******************************************************************/
1397 static int get_version_id (char * arch)
1400 struct table_node archi_table[]= {
1402 {"Windows 4.0", "WIN40", 0 },
1403 {"Windows NT x86", "W32X86", 2 },
1404 {"Windows NT R4000", "W32MIPS", 2 },
1405 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1406 {"Windows NT PowerPC", "W32PPC", 2 },
1410 for (i=0; archi_table[i].long_archi != NULL; i++)
1412 if (strcmp(arch, archi_table[i].long_archi) == 0)
1413 return (archi_table[i].version);
1419 /********************************************************************
1420 * _spoolss_deleteprinterdriver
1422 * We currently delete the driver for the architecture only.
1423 * This can leave the driver for other archtectures. However,
1424 * since every printer associates a "Windows NT x86" driver name
1425 * and we cannot delete that one while it is in use, **and** since
1426 * it is impossible to assign a driver to a Samba printer without
1427 * having the "Windows NT x86" driver installed,...
1429 * ....we should not get into trouble here.
1432 ********************************************************************/
1434 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
1435 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1439 NT_PRINTER_DRIVER_INFO_LEVEL info;
1442 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1443 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1445 /* check that we have a valid driver name first */
1446 if ((version=get_version_id(arch)) == -1) {
1447 /* this is what NT returns */
1448 return WERR_INVALID_ENVIRONMENT;
1452 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1453 return WERR_UNKNOWN_PRINTER_DRIVER;
1457 if (printer_driver_in_use(arch, driver))
1459 return WERR_PRINTER_DRIVER_IN_USE;
1462 return delete_printer_driver(info.info_3);
1465 /********************************************************************
1466 GetPrinterData on a printer server Handle.
1467 ********************************************************************/
1469 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1473 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1475 if (!strcmp(value, "W3SvcInstalled")) {
1477 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
1483 if (!strcmp(value, "BeepEnabled")) {
1485 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1487 SIVAL(*data, 0, 0x00);
1492 if (!strcmp(value, "EventLog")) {
1494 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1496 /* formally was 0x1b */
1497 SIVAL(*data, 0, 0x0);
1502 if (!strcmp(value, "NetPopup")) {
1504 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1506 SIVAL(*data, 0, 0x00);
1511 if (!strcmp(value, "MajorVersion")) {
1513 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1515 #ifndef EMULATE_WIN2K_HACK /* JERRY */
1524 if (!strcmp(value, "DefaultSpoolDirectory")) {
1527 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1529 *needed = 2*(strlen(string)+1);
1530 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1532 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1534 /* it's done by hand ready to go on the wire */
1535 for (i=0; i<strlen(string); i++) {
1536 (*data)[2*i]=string[i];
1537 (*data)[2*i+1]='\0';
1542 if (!strcmp(value, "Architecture")) {
1543 pstring string="Windows NT x86";
1545 *needed = 2*(strlen(string)+1);
1546 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1548 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1549 for (i=0; i<strlen(string); i++) {
1550 (*data)[2*i]=string[i];
1551 (*data)[2*i+1]='\0';
1559 /********************************************************************
1560 GetPrinterData on a printer Handle.
1561 ********************************************************************/
1563 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1564 fstring value, uint32 *type,
1565 uint8 **data, uint32 *needed, uint32 in_size )
1567 NT_PRINTER_INFO_LEVEL *printer = NULL;
1571 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1573 DEBUG(5,("getprinterdata_printer\n"));
1576 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1580 if(!get_printer_snum(p, handle, &snum))
1583 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1586 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1587 free_a_printer(&printer, 2);
1591 free_a_printer(&printer, 2);
1593 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1596 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1600 memset(*data, 0, in_size *sizeof(uint8));
1601 /* copy the min(in_size, len) */
1602 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1609 DEBUG(5,("getprinterdata_printer:copy done\n"));
1616 /********************************************************************
1617 * spoolss_getprinterdata
1618 ********************************************************************/
1620 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1622 POLICY_HND *handle = &q_u->handle;
1623 UNISTR2 *valuename = &q_u->valuename;
1624 uint32 in_size = q_u->size;
1625 uint32 *type = &r_u->type;
1626 uint32 *out_size = &r_u->size;
1627 uint8 **data = &r_u->data;
1628 uint32 *needed = &r_u->needed;
1632 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1635 * Reminder: when it's a string, the length is in BYTES
1636 * even if UNICODE is negociated.
1643 /* in case of problem, return some default values */
1647 DEBUG(4,("_spoolss_getprinterdata\n"));
1650 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1652 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1656 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1658 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1659 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1661 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1664 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1665 /* reply this param doesn't exist */
1667 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1673 /* error depends on handle type */
1675 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1676 return WERR_INVALID_PARAM;
1678 return WERR_BADFILE;
1681 if (*needed > *out_size)
1682 return WERR_MORE_DATA;
1687 /***************************************************************************
1688 Connect to the client.
1689 ****************************************************************************/
1691 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1696 * If it's the first connection, contact the client
1697 * and connect to the IPC$ share anonumously
1699 if (smb_connections==0) {
1700 fstring unix_printer;
1702 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1704 if(!spoolss_connect_to_client(&cli, unix_printer))
1707 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1713 result = cli_spoolss_reply_open_printer(&cli, cli.mem_ctx, printer, localprinter,
1716 if (!W_ERROR_IS_OK(result))
1717 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
1718 dos_errstr(result)));
1720 return (W_ERROR_IS_OK(result));
1723 /********************************************************************
1725 * ReplyFindFirstPrinterChangeNotifyEx
1727 * before replying OK: status=0 a rpc call is made to the workstation
1728 * asking ReplyOpenPrinter
1730 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1731 * called from api_spoolss_rffpcnex
1732 ********************************************************************/
1734 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1736 POLICY_HND *handle = &q_u->handle;
1737 uint32 flags = q_u->flags;
1738 uint32 options = q_u->options;
1739 UNISTR2 *localmachine = &q_u->localmachine;
1740 uint32 printerlocal = q_u->printerlocal;
1741 SPOOL_NOTIFY_OPTION *option = q_u->option;
1743 /* store the notify value in the printer struct */
1745 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1748 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1752 Printer->notify.flags=flags;
1753 Printer->notify.options=options;
1754 Printer->notify.printerlocal=printerlocal;
1756 if (Printer->notify.option)
1757 free_spool_notify_option(&Printer->notify.option);
1759 Printer->notify.option=dup_spool_notify_option(option);
1761 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1763 /* connect to the client machine and send a ReplyOpenPrinter */
1764 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1765 Printer->notify.printerlocal, 1,
1766 &Printer->notify.client_hnd))
1768 Printer->notify.client_connected=True;
1774 /*******************************************************************
1775 * fill a notify_info_data with the servername
1776 ********************************************************************/
1778 void spoolss_notify_server_name(int snum,
1779 SPOOL_NOTIFY_INFO_DATA *data,
1780 print_queue_struct *queue,
1781 NT_PRINTER_INFO_LEVEL *printer,
1782 TALLOC_CTX *mem_ctx)
1784 pstring temp_name, temp;
1787 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
1789 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
1791 data->notify_data.data.length = len / 2 - 1;
1792 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1794 if (!data->notify_data.data.string) {
1795 data->notify_data.data.length = 0;
1799 memcpy(data->notify_data.data.string, temp, len);
1802 /*******************************************************************
1803 * fill a notify_info_data with the printername (not including the servername).
1804 ********************************************************************/
1806 void spoolss_notify_printer_name(int snum,
1807 SPOOL_NOTIFY_INFO_DATA *data,
1808 print_queue_struct *queue,
1809 NT_PRINTER_INFO_LEVEL *printer,
1810 TALLOC_CTX *mem_ctx)
1815 /* the notify name should not contain the \\server\ part */
1816 char *p = strrchr(printer->info_2->printername, '\\');
1819 p = printer->info_2->printername;
1824 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
1826 data->notify_data.data.length = len / 2 - 1;
1827 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1829 if (!data->notify_data.data.string) {
1830 data->notify_data.data.length = 0;
1834 memcpy(data->notify_data.data.string, temp, len);
1837 /*******************************************************************
1838 * fill a notify_info_data with the servicename
1839 ********************************************************************/
1841 void spoolss_notify_share_name(int snum,
1842 SPOOL_NOTIFY_INFO_DATA *data,
1843 print_queue_struct *queue,
1844 NT_PRINTER_INFO_LEVEL *printer,
1845 TALLOC_CTX *mem_ctx)
1850 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
1852 data->notify_data.data.length = len / 2 - 1;
1853 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1855 if (!data->notify_data.data.string) {
1856 data->notify_data.data.length = 0;
1860 memcpy(data->notify_data.data.string, temp, len);
1863 /*******************************************************************
1864 * fill a notify_info_data with the port name
1865 ********************************************************************/
1867 void spoolss_notify_port_name(int snum,
1868 SPOOL_NOTIFY_INFO_DATA *data,
1869 print_queue_struct *queue,
1870 NT_PRINTER_INFO_LEVEL *printer,
1871 TALLOC_CTX *mem_ctx)
1876 /* even if it's strange, that's consistant in all the code */
1878 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
1880 data->notify_data.data.length = len / 2 - 1;
1881 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1883 if (!data->notify_data.data.string) {
1884 data->notify_data.data.length = 0;
1888 memcpy(data->notify_data.data.string, temp, len);
1891 /*******************************************************************
1892 * fill a notify_info_data with the printername
1893 * but it doesn't exist, have to see what to do
1894 ********************************************************************/
1896 void spoolss_notify_driver_name(int snum,
1897 SPOOL_NOTIFY_INFO_DATA *data,
1898 print_queue_struct *queue,
1899 NT_PRINTER_INFO_LEVEL *printer,
1900 TALLOC_CTX *mem_ctx)
1905 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
1906 data->notify_data.data.length = len / 2 - 1;
1907 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1909 if (!data->notify_data.data.string) {
1910 data->notify_data.data.length = 0;
1914 memcpy(data->notify_data.data.string, temp, len);
1917 /*******************************************************************
1918 * fill a notify_info_data with the comment
1919 ********************************************************************/
1921 void spoolss_notify_comment(int snum,
1922 SPOOL_NOTIFY_INFO_DATA *data,
1923 print_queue_struct *queue,
1924 NT_PRINTER_INFO_LEVEL *printer,
1925 TALLOC_CTX *mem_ctx)
1930 if (*printer->info_2->comment == '\0')
1931 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
1933 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
1935 data->notify_data.data.length = len / 2 - 1;
1936 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1938 if (!data->notify_data.data.string) {
1939 data->notify_data.data.length = 0;
1943 memcpy(data->notify_data.data.string, temp, len);
1946 /*******************************************************************
1947 * fill a notify_info_data with the comment
1948 * location = "Room 1, floor 2, building 3"
1949 ********************************************************************/
1951 void spoolss_notify_location(int snum,
1952 SPOOL_NOTIFY_INFO_DATA *data,
1953 print_queue_struct *queue,
1954 NT_PRINTER_INFO_LEVEL *printer,
1955 TALLOC_CTX *mem_ctx)
1960 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
1962 data->notify_data.data.length = len / 2 - 1;
1963 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1965 if (!data->notify_data.data.string) {
1966 data->notify_data.data.length = 0;
1970 memcpy(data->notify_data.data.string, temp, len);
1973 /*******************************************************************
1974 * fill a notify_info_data with the device mode
1975 * jfm:xxxx don't to it for know but that's a real problem !!!
1976 ********************************************************************/
1978 static void spoolss_notify_devmode(int snum,
1979 SPOOL_NOTIFY_INFO_DATA *data,
1980 print_queue_struct *queue,
1981 NT_PRINTER_INFO_LEVEL *printer,
1982 TALLOC_CTX *mem_ctx)
1986 /*******************************************************************
1987 * fill a notify_info_data with the separator file name
1988 ********************************************************************/
1990 void spoolss_notify_sepfile(int snum,
1991 SPOOL_NOTIFY_INFO_DATA *data,
1992 print_queue_struct *queue,
1993 NT_PRINTER_INFO_LEVEL *printer,
1994 TALLOC_CTX *mem_ctx)
1999 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2001 data->notify_data.data.length = len / 2 - 1;
2002 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2004 if (!data->notify_data.data.string) {
2005 data->notify_data.data.length = 0;
2009 memcpy(data->notify_data.data.string, temp, len);
2012 /*******************************************************************
2013 * fill a notify_info_data with the print processor
2014 * jfm:xxxx return always winprint to indicate we don't do anything to it
2015 ********************************************************************/
2017 void spoolss_notify_print_processor(int snum,
2018 SPOOL_NOTIFY_INFO_DATA *data,
2019 print_queue_struct *queue,
2020 NT_PRINTER_INFO_LEVEL *printer,
2021 TALLOC_CTX *mem_ctx)
2026 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2028 data->notify_data.data.length = len / 2 - 1;
2029 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2031 if (!data->notify_data.data.string) {
2032 data->notify_data.data.length = 0;
2036 memcpy(data->notify_data.data.string, temp, len);
2039 /*******************************************************************
2040 * fill a notify_info_data with the print processor options
2041 * jfm:xxxx send an empty string
2042 ********************************************************************/
2044 void spoolss_notify_parameters(int snum,
2045 SPOOL_NOTIFY_INFO_DATA *data,
2046 print_queue_struct *queue,
2047 NT_PRINTER_INFO_LEVEL *printer,
2048 TALLOC_CTX *mem_ctx)
2053 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2055 data->notify_data.data.length = len / 2 - 1;
2056 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2058 if (!data->notify_data.data.string) {
2059 data->notify_data.data.length = 0;
2063 memcpy(data->notify_data.data.string, temp, len);
2066 /*******************************************************************
2067 * fill a notify_info_data with the data type
2068 * jfm:xxxx always send RAW as data type
2069 ********************************************************************/
2071 void spoolss_notify_datatype(int snum,
2072 SPOOL_NOTIFY_INFO_DATA *data,
2073 print_queue_struct *queue,
2074 NT_PRINTER_INFO_LEVEL *printer,
2075 TALLOC_CTX *mem_ctx)
2080 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2082 data->notify_data.data.length = len / 2 - 1;
2083 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2085 if (!data->notify_data.data.string) {
2086 data->notify_data.data.length = 0;
2090 memcpy(data->notify_data.data.string, temp, len);
2093 /*******************************************************************
2094 * fill a notify_info_data with the security descriptor
2095 * jfm:xxxx send an null pointer to say no security desc
2096 * have to implement security before !
2097 ********************************************************************/
2099 static void spoolss_notify_security_desc(int snum,
2100 SPOOL_NOTIFY_INFO_DATA *data,
2101 print_queue_struct *queue,
2102 NT_PRINTER_INFO_LEVEL *printer,
2103 TALLOC_CTX *mem_ctx)
2105 data->notify_data.data.length=0;
2106 data->notify_data.data.string = NULL;
2109 /*******************************************************************
2110 * fill a notify_info_data with the attributes
2111 * jfm:xxxx a samba printer is always shared
2112 ********************************************************************/
2114 void spoolss_notify_attributes(int snum,
2115 SPOOL_NOTIFY_INFO_DATA *data,
2116 print_queue_struct *queue,
2117 NT_PRINTER_INFO_LEVEL *printer,
2118 TALLOC_CTX *mem_ctx)
2120 data->notify_data.value[0] = printer->info_2->attributes;
2121 data->notify_data.value[1] = 0;
2124 /*******************************************************************
2125 * fill a notify_info_data with the priority
2126 ********************************************************************/
2128 static void spoolss_notify_priority(int snum,
2129 SPOOL_NOTIFY_INFO_DATA *data,
2130 print_queue_struct *queue,
2131 NT_PRINTER_INFO_LEVEL *printer,
2132 TALLOC_CTX *mem_ctx)
2134 data->notify_data.value[0] = printer->info_2->priority;
2135 data->notify_data.value[1] = 0;
2138 /*******************************************************************
2139 * fill a notify_info_data with the default priority
2140 ********************************************************************/
2142 static void spoolss_notify_default_priority(int snum,
2143 SPOOL_NOTIFY_INFO_DATA *data,
2144 print_queue_struct *queue,
2145 NT_PRINTER_INFO_LEVEL *printer,
2146 TALLOC_CTX *mem_ctx)
2148 data->notify_data.value[0] = printer->info_2->default_priority;
2149 data->notify_data.value[1] = 0;
2152 /*******************************************************************
2153 * fill a notify_info_data with the start time
2154 ********************************************************************/
2156 static void spoolss_notify_start_time(int snum,
2157 SPOOL_NOTIFY_INFO_DATA *data,
2158 print_queue_struct *queue,
2159 NT_PRINTER_INFO_LEVEL *printer,
2160 TALLOC_CTX *mem_ctx)
2162 data->notify_data.value[0] = printer->info_2->starttime;
2163 data->notify_data.value[1] = 0;
2166 /*******************************************************************
2167 * fill a notify_info_data with the until time
2168 ********************************************************************/
2170 static void spoolss_notify_until_time(int snum,
2171 SPOOL_NOTIFY_INFO_DATA *data,
2172 print_queue_struct *queue,
2173 NT_PRINTER_INFO_LEVEL *printer,
2174 TALLOC_CTX *mem_ctx)
2176 data->notify_data.value[0] = printer->info_2->untiltime;
2177 data->notify_data.value[1] = 0;
2180 /*******************************************************************
2181 * fill a notify_info_data with the status
2182 ********************************************************************/
2184 static void spoolss_notify_status(int snum,
2185 SPOOL_NOTIFY_INFO_DATA *data,
2186 print_queue_struct *queue,
2187 NT_PRINTER_INFO_LEVEL *printer,
2188 TALLOC_CTX *mem_ctx)
2190 print_status_struct status;
2192 print_queue_length(snum, &status);
2193 data->notify_data.value[0]=(uint32) status.status;
2194 data->notify_data.value[1] = 0;
2197 /*******************************************************************
2198 * fill a notify_info_data with the number of jobs queued
2199 ********************************************************************/
2201 void spoolss_notify_cjobs(int snum,
2202 SPOOL_NOTIFY_INFO_DATA *data,
2203 print_queue_struct *queue,
2204 NT_PRINTER_INFO_LEVEL *printer,
2205 TALLOC_CTX *mem_ctx)
2207 data->notify_data.value[0] = print_queue_length(snum, NULL);
2208 data->notify_data.value[1] = 0;
2211 /*******************************************************************
2212 * fill a notify_info_data with the average ppm
2213 ********************************************************************/
2215 static void spoolss_notify_average_ppm(int snum,
2216 SPOOL_NOTIFY_INFO_DATA *data,
2217 print_queue_struct *queue,
2218 NT_PRINTER_INFO_LEVEL *printer,
2219 TALLOC_CTX *mem_ctx)
2221 /* always respond 8 pages per minutes */
2222 /* a little hard ! */
2223 data->notify_data.value[0] = printer->info_2->averageppm;
2224 data->notify_data.value[1] = 0;
2227 /*******************************************************************
2228 * fill a notify_info_data with username
2229 ********************************************************************/
2231 static void spoolss_notify_username(int snum,
2232 SPOOL_NOTIFY_INFO_DATA *data,
2233 print_queue_struct *queue,
2234 NT_PRINTER_INFO_LEVEL *printer,
2235 TALLOC_CTX *mem_ctx)
2240 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
2242 data->notify_data.data.length = len / 2 - 1;
2243 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2245 if (!data->notify_data.data.string) {
2246 data->notify_data.data.length = 0;
2250 memcpy(data->notify_data.data.string, temp, len);
2253 /*******************************************************************
2254 * fill a notify_info_data with job status
2255 ********************************************************************/
2257 static void spoolss_notify_job_status(int snum,
2258 SPOOL_NOTIFY_INFO_DATA *data,
2259 print_queue_struct *queue,
2260 NT_PRINTER_INFO_LEVEL *printer,
2261 TALLOC_CTX *mem_ctx)
2263 data->notify_data.value[0]=nt_printj_status(queue->status);
2264 data->notify_data.value[1] = 0;
2267 /*******************************************************************
2268 * fill a notify_info_data with job name
2269 ********************************************************************/
2271 static void spoolss_notify_job_name(int snum,
2272 SPOOL_NOTIFY_INFO_DATA *data,
2273 print_queue_struct *queue,
2274 NT_PRINTER_INFO_LEVEL *printer,
2275 TALLOC_CTX *mem_ctx)
2280 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
2282 data->notify_data.data.length = len / 2 - 1;
2283 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2285 if (!data->notify_data.data.string) {
2286 data->notify_data.data.length = 0;
2290 memcpy(data->notify_data.data.string, temp, len);
2293 /*******************************************************************
2294 * fill a notify_info_data with job status
2295 ********************************************************************/
2297 static void spoolss_notify_job_status_string(int snum,
2298 SPOOL_NOTIFY_INFO_DATA *data,
2299 print_queue_struct *queue,
2300 NT_PRINTER_INFO_LEVEL *printer,
2301 TALLOC_CTX *mem_ctx)
2304 * Now we're returning job status codes we just return a "" here. JRA.
2311 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2314 switch (queue->status) {
2319 p = ""; /* NT provides the paused string */
2328 #endif /* NO LONGER NEEDED. */
2330 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
2332 data->notify_data.data.length = len / 2 - 1;
2333 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2335 if (!data->notify_data.data.string) {
2336 data->notify_data.data.length = 0;
2340 memcpy(data->notify_data.data.string, temp, len);
2343 /*******************************************************************
2344 * fill a notify_info_data with job time
2345 ********************************************************************/
2347 static void spoolss_notify_job_time(int snum,
2348 SPOOL_NOTIFY_INFO_DATA *data,
2349 print_queue_struct *queue,
2350 NT_PRINTER_INFO_LEVEL *printer,
2351 TALLOC_CTX *mem_ctx)
2353 data->notify_data.value[0]=0x0;
2354 data->notify_data.value[1]=0;
2357 /*******************************************************************
2358 * fill a notify_info_data with job size
2359 ********************************************************************/
2361 static void spoolss_notify_job_size(int snum,
2362 SPOOL_NOTIFY_INFO_DATA *data,
2363 print_queue_struct *queue,
2364 NT_PRINTER_INFO_LEVEL *printer,
2365 TALLOC_CTX *mem_ctx)
2367 data->notify_data.value[0]=queue->size;
2368 data->notify_data.value[1]=0;
2371 /*******************************************************************
2372 * fill a notify_info_data with page info
2373 ********************************************************************/
2374 static void spoolss_notify_total_pages(int snum,
2375 SPOOL_NOTIFY_INFO_DATA *data,
2376 print_queue_struct *queue,
2377 NT_PRINTER_INFO_LEVEL *printer,
2378 TALLOC_CTX *mem_ctx)
2380 data->notify_data.value[0]=queue->page_count;
2381 data->notify_data.value[1]=0;
2384 /*******************************************************************
2385 * fill a notify_info_data with pages printed info.
2386 ********************************************************************/
2387 static void spoolss_notify_pages_printed(int snum,
2388 SPOOL_NOTIFY_INFO_DATA *data,
2389 print_queue_struct *queue,
2390 NT_PRINTER_INFO_LEVEL *printer,
2391 TALLOC_CTX *mem_ctx)
2393 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
2394 data->notify_data.value[1]=0;
2397 /*******************************************************************
2398 Fill a notify_info_data with job position.
2399 ********************************************************************/
2401 static void spoolss_notify_job_position(int snum,
2402 SPOOL_NOTIFY_INFO_DATA *data,
2403 print_queue_struct *queue,
2404 NT_PRINTER_INFO_LEVEL *printer,
2405 TALLOC_CTX *mem_ctx)
2407 data->notify_data.value[0]=queue->job;
2408 data->notify_data.value[1]=0;
2411 /*******************************************************************
2412 Fill a notify_info_data with submitted time.
2413 ********************************************************************/
2415 static void spoolss_notify_submitted_time(int snum,
2416 SPOOL_NOTIFY_INFO_DATA *data,
2417 print_queue_struct *queue,
2418 NT_PRINTER_INFO_LEVEL *printer,
2419 TALLOC_CTX *mem_ctx)
2426 t=gmtime(&queue->time);
2428 len = sizeof(SYSTEMTIME);
2430 data->notify_data.data.length = len;
2431 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2433 if (!data->notify_data.data.string) {
2434 data->notify_data.data.length = 0;
2438 make_systemtime(&st, t);
2441 * Systemtime must be linearized as a set of UINT16's.
2442 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2445 p = (char *)data->notify_data.data.string;
2446 SSVAL(p, 0, st.year);
2447 SSVAL(p, 2, st.month);
2448 SSVAL(p, 4, st.dayofweek);
2449 SSVAL(p, 6, st.day);
2450 SSVAL(p, 8, st.hour);
2451 SSVAL(p, 10, st.minute);
2452 SSVAL(p, 12, st.second);
2453 SSVAL(p, 14, st.milliseconds);
2458 struct s_notify_info_data_table
2464 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2465 print_queue_struct *queue,
2466 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2469 /* A table describing the various print notification constants and
2470 whether the notification data is a pointer to a variable sized
2471 buffer, a one value uint32 or a two value uint32. */
2473 struct s_notify_info_data_table notify_info_data_table[] =
2475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2489 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2490 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2491 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2492 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2493 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2494 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2495 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2496 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2497 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2498 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2499 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2500 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2511 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2512 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2513 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2514 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2515 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2516 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2517 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2518 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2519 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2520 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2521 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, spoolss_notify_total_pages },
2522 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, spoolss_notify_pages_printed },
2523 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2524 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2525 { END, END, "", END, NULL }
2528 /*******************************************************************
2529 Return the size of info_data structure.
2530 ********************************************************************/
2532 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2536 while (notify_info_data_table[i].type != END)
2538 if ( (notify_info_data_table[i].type == type ) &&
2539 (notify_info_data_table[i].field == field ) )
2541 return (notify_info_data_table[i].size);
2548 /*******************************************************************
2549 Return the type of notify_info_data.
2550 ********************************************************************/
2552 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2556 while (notify_info_data_table[i].type != END)
2558 if ( (notify_info_data_table[i].type == type ) &&
2559 (notify_info_data_table[i].field == field ) )
2561 if (notify_info_data_table[i].size == POINTER)
2575 /****************************************************************************
2576 ****************************************************************************/
2578 static int search_notify(uint16 type, uint16 field, int *value)
2583 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2585 if ( (notify_info_data_table[j].type == type ) &&
2586 (notify_info_data_table[j].field == field ) )
2591 if ( found && (notify_info_data_table[j].fn != NULL) )
2597 /****************************************************************************
2598 ****************************************************************************/
2600 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2602 info_data->type = type;
2603 info_data->field = field;
2604 info_data->reserved = 0;
2606 info_data->size = size_of_notify_info_data(type, field);
2607 info_data->enc_type = type_of_notify_info_data(type, field);
2611 /*******************************************************************
2613 * fill a notify_info struct with info asked
2615 ********************************************************************/
2617 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2618 snum, SPOOL_NOTIFY_OPTION_TYPE
2619 *option_type, uint32 id,
2620 TALLOC_CTX *mem_ctx)
2626 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2627 NT_PRINTER_INFO_LEVEL *printer = NULL;
2628 print_queue_struct *queue=NULL;
2630 type=option_type->type;
2632 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2633 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2634 option_type->count, lp_servicename(snum)));
2636 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2639 for(field_num=0; field_num<option_type->count; field_num++) {
2640 field = option_type->fields[field_num];
2641 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2643 if (!search_notify(type, field, &j) )
2646 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2647 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2650 else info->data = tid;
2652 current_data=&info->data[info->count];
2654 construct_info_data(current_data, type, field, id);
2656 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2657 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2659 notify_info_data_table[j].fn(snum, current_data, queue,
2665 free_a_printer(&printer, 2);
2669 /*******************************************************************
2671 * fill a notify_info struct with info asked
2673 ********************************************************************/
2675 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2676 SPOOL_NOTIFY_INFO *info,
2677 NT_PRINTER_INFO_LEVEL *printer,
2678 int snum, SPOOL_NOTIFY_OPTION_TYPE
2679 *option_type, uint32 id,
2680 TALLOC_CTX *mem_ctx)
2686 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2688 DEBUG(4,("construct_notify_jobs_info\n"));
2690 type = option_type->type;
2692 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2693 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2694 option_type->count));
2696 for(field_num=0; field_num<option_type->count; field_num++) {
2697 field = option_type->fields[field_num];
2699 if (!search_notify(type, field, &j) )
2702 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2703 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2706 else info->data = tid;
2708 current_data=&(info->data[info->count]);
2710 construct_info_data(current_data, type, field, id);
2711 notify_info_data_table[j].fn(snum, current_data, queue,
2720 * JFM: The enumeration is not that simple, it's even non obvious.
2722 * let's take an example: I want to monitor the PRINTER SERVER for
2723 * the printer's name and the number of jobs currently queued.
2724 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2725 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2727 * I have 3 printers on the back of my server.
2729 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2732 * 1 printer 1 name 1
2733 * 2 printer 1 cjob 1
2734 * 3 printer 2 name 2
2735 * 4 printer 2 cjob 2
2736 * 5 printer 3 name 3
2737 * 6 printer 3 name 3
2739 * that's the print server case, the printer case is even worse.
2742 /*******************************************************************
2744 * enumerate all printers on the printserver
2745 * fill a notify_info struct with info asked
2747 ********************************************************************/
2749 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2750 SPOOL_NOTIFY_INFO *info,
2751 TALLOC_CTX *mem_ctx)
2754 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2755 int n_services=lp_numservices();
2758 SPOOL_NOTIFY_OPTION *option;
2759 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2761 DEBUG(4,("printserver_notify_info\n"));
2766 option=Printer->notify.option;
2772 for (i=0; i<option->count; i++) {
2773 option_type=&(option->ctr.type[i]);
2775 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2778 for (snum=0; snum<n_services; snum++)
2779 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2780 if (construct_notify_printer_info
2781 (info, snum, option_type, id, mem_ctx))
2786 * Debugging information, don't delete.
2789 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2790 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2791 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2793 for (i=0; i<info->count; i++) {
2794 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2795 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2796 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2803 /*******************************************************************
2805 * fill a notify_info struct with info asked
2807 ********************************************************************/
2809 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2810 TALLOC_CTX *mem_ctx)
2813 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2816 SPOOL_NOTIFY_OPTION *option;
2817 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2819 print_queue_struct *queue=NULL;
2820 print_status_struct status;
2822 DEBUG(4,("printer_notify_info\n"));
2827 option=Printer->notify.option;
2833 get_printer_snum(p, hnd, &snum);
2835 for (i=0; i<option->count; i++) {
2836 option_type=&option->ctr.type[i];
2838 switch ( option_type->type ) {
2839 case PRINTER_NOTIFY_TYPE:
2840 if(construct_notify_printer_info(info, snum,
2846 case JOB_NOTIFY_TYPE: {
2847 NT_PRINTER_INFO_LEVEL *printer = NULL;
2849 count = print_queue_status(snum, &queue, &status);
2851 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
2852 lp_servicename(snum))))
2855 for (j=0; j<count; j++) {
2856 construct_notify_jobs_info(&queue[j], info,
2863 free_a_printer(&printer, 2);
2873 * Debugging information, don't delete.
2876 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2877 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2878 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2880 for (i=0; i<info->count; i++) {
2881 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2882 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2883 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2889 /********************************************************************
2891 ********************************************************************/
2893 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2895 POLICY_HND *handle = &q_u->handle;
2896 /* uint32 change = q_u->change; - notused. */
2897 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2898 SPOOL_NOTIFY_INFO *info = &r_u->info;
2900 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2901 WERROR result = WERR_BADFID;
2903 /* we always have a NOTIFY_INFO struct */
2907 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
2908 OUR_HANDLE(handle)));
2912 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2914 /* jfm: the change value isn't used right now.
2915 * we will honour it when
2916 * a) we'll be able to send notification to the client
2917 * b) we'll have a way to communicate between the spoolss process.
2919 * same thing for option->flags
2920 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2921 * I don't have a global notification system, I'm sending back all the
2922 * informations even when _NOTHING_ has changed.
2925 /* just ignore the SPOOL_NOTIFY_OPTION */
2927 switch (Printer->printer_type) {
2928 case PRINTER_HANDLE_IS_PRINTSERVER:
2929 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2932 case PRINTER_HANDLE_IS_PRINTER:
2933 result = printer_notify_info(p, handle, info, p->mem_ctx);
2941 /********************************************************************
2942 * construct_printer_info_0
2943 * fill a printer_info_0 struct
2944 ********************************************************************/
2946 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2950 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2951 counter_printer_0 *session_counter;
2952 uint32 global_counter;
2955 print_status_struct status;
2957 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2960 count = print_queue_length(snum, &status);
2962 /* check if we already have a counter for this printer */
2963 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2965 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2966 if (session_counter->snum == snum)
2970 /* it's the first time, add it to the list */
2971 if (session_counter==NULL) {
2972 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2973 free_a_printer(&ntprinter, 2);
2976 ZERO_STRUCTP(session_counter);
2977 session_counter->snum=snum;
2978 session_counter->counter=0;
2979 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2983 session_counter->counter++;
2986 * the global_counter should be stored in a TDB as it's common to all the clients
2987 * and should be zeroed on samba startup
2989 global_counter=session_counter->counter;
2991 pstrcpy(chaine,ntprinter->info_2->printername);
2993 init_unistr(&printer->printername, chaine);
2995 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
2996 init_unistr(&printer->servername, chaine);
2998 printer->cjobs = count;
2999 printer->total_jobs = 0;
3000 printer->total_bytes = 0;
3002 setuptime = (time_t)ntprinter->info_2->setuptime;
3003 t=gmtime(&setuptime);
3005 printer->year = t->tm_year+1900;
3006 printer->month = t->tm_mon+1;
3007 printer->dayofweek = t->tm_wday;
3008 printer->day = t->tm_mday;
3009 printer->hour = t->tm_hour;
3010 printer->minute = t->tm_min;
3011 printer->second = t->tm_sec;
3012 printer->milliseconds = 0;
3014 printer->global_counter = global_counter;
3015 printer->total_pages = 0;
3016 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3017 printer->major_version = 0x0004; /* NT 4 */
3018 printer->build_version = 0x0565; /* build 1381 */
3020 printer->major_version = 0x0005; /* NT 5 */
3021 printer->build_version = 0x0893; /* build 2195 */
3023 printer->unknown7 = 0x1;
3024 printer->unknown8 = 0x0;
3025 printer->unknown9 = 0x0;
3026 printer->session_counter = session_counter->counter;
3027 printer->unknown11 = 0x0;
3028 printer->printer_errors = 0x0; /* number of print failure */
3029 printer->unknown13 = 0x0;
3030 printer->unknown14 = 0x1;
3031 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3032 printer->unknown16 = 0x0;
3033 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3034 printer->unknown18 = 0x0;
3035 printer->status = nt_printq_status(status.status);
3036 printer->unknown20 = 0x0;
3037 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3038 printer->unknown22 = 0x0;
3039 printer->unknown23 = 0x6; /* 6 ???*/
3040 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3041 printer->unknown25 = 0;
3042 printer->unknown26 = 0;
3043 printer->unknown27 = 0;
3044 printer->unknown28 = 0;
3045 printer->unknown29 = 0;
3047 free_a_printer(&ntprinter,2);
3051 /********************************************************************
3052 * construct_printer_info_1
3053 * fill a printer_info_1 struct
3054 ********************************************************************/
3056 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3060 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3062 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3065 printer->flags=flags;
3067 if (*ntprinter->info_2->comment == '\0') {
3068 init_unistr(&printer->comment, lp_comment(snum));
3069 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3070 ntprinter->info_2->drivername, lp_comment(snum));
3073 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3074 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3075 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3078 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3080 init_unistr(&printer->description, chaine);
3081 init_unistr(&printer->name, chaine2);
3083 free_a_printer(&ntprinter,2);
3088 /****************************************************************************
3089 Free a DEVMODE struct.
3090 ****************************************************************************/
3092 static void free_dev_mode(DEVICEMODE *dev)
3097 SAFE_FREE(dev->private);
3101 /****************************************************************************
3102 Create a DEVMODE struct. Returns malloced memory.
3103 ****************************************************************************/
3105 static DEVICEMODE *construct_dev_mode(int snum)
3109 NT_PRINTER_INFO_LEVEL *printer = NULL;
3110 NT_DEVICEMODE *ntdevmode = NULL;
3111 DEVICEMODE *devmode = NULL;
3113 DEBUG(7,("construct_dev_mode\n"));
3115 DEBUGADD(8,("getting printer characteristics\n"));
3117 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
3118 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3122 ZERO_STRUCTP(devmode);
3124 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3127 if (printer->info_2->devmode)
3128 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
3130 if (ntdevmode == NULL)
3133 DEBUGADD(8,("loading DEVICEMODE\n"));
3135 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
3136 init_unistr(&devmode->devicename, adevice);
3138 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
3139 init_unistr(&devmode->formname, aform);
3141 devmode->specversion = ntdevmode->specversion;
3142 devmode->driverversion = ntdevmode->driverversion;
3143 devmode->size = ntdevmode->size;
3144 devmode->driverextra = ntdevmode->driverextra;
3145 devmode->fields = ntdevmode->fields;
3147 devmode->orientation = ntdevmode->orientation;
3148 devmode->papersize = ntdevmode->papersize;
3149 devmode->paperlength = ntdevmode->paperlength;
3150 devmode->paperwidth = ntdevmode->paperwidth;
3151 devmode->scale = ntdevmode->scale;
3152 devmode->copies = ntdevmode->copies;
3153 devmode->defaultsource = ntdevmode->defaultsource;
3154 devmode->printquality = ntdevmode->printquality;
3155 devmode->color = ntdevmode->color;
3156 devmode->duplex = ntdevmode->duplex;
3157 devmode->yresolution = ntdevmode->yresolution;
3158 devmode->ttoption = ntdevmode->ttoption;
3159 devmode->collate = ntdevmode->collate;
3160 devmode->icmmethod = ntdevmode->icmmethod;
3161 devmode->icmintent = ntdevmode->icmintent;
3162 devmode->mediatype = ntdevmode->mediatype;
3163 devmode->dithertype = ntdevmode->dithertype;
3165 if (ntdevmode->private != NULL) {
3166 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3170 free_nt_devicemode(&ntdevmode);
3171 free_a_printer(&printer,2);
3178 free_nt_devicemode(&ntdevmode);
3180 free_a_printer(&printer,2);
3181 free_dev_mode(devmode);
3186 /********************************************************************
3187 * construct_printer_info_2
3188 * fill a printer_info_2 struct
3189 ********************************************************************/
3191 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
3194 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3196 print_status_struct status;
3198 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3201 count = print_queue_length(snum, &status);
3203 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3204 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3205 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
3206 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
3207 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
3209 if (*ntprinter->info_2->comment == '\0')
3210 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
3212 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3214 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
3215 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
3216 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
3217 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
3218 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
3220 printer->attributes = ntprinter->info_2->attributes;
3222 printer->priority = ntprinter->info_2->priority; /* priority */
3223 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
3224 printer->starttime = ntprinter->info_2->starttime; /* starttime */
3225 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
3226 printer->status = nt_printq_status(status.status); /* status */
3227 printer->cjobs = count; /* jobs */
3228 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
3230 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
3231 DEBUG(8, ("Returning NULL Devicemode!\n"));
3234 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3235 /* steal the printer info sec_desc structure. [badly done]. */
3236 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3237 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
3238 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
3239 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
3242 printer->secdesc = NULL;
3245 free_a_printer(&ntprinter, 2);
3249 /********************************************************************
3250 * construct_printer_info_3
3251 * fill a printer_info_3 struct
3252 ********************************************************************/
3254 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
3256 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3257 PRINTER_INFO_3 *printer = NULL;
3259 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3263 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
3264 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3268 ZERO_STRUCTP(printer);
3270 printer->flags = 4; /* These are the components of the SD we are returning. */
3271 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
3272 /* steal the printer info sec_desc structure. [badly done]. */
3273 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
3277 * Set the flags for the components we are returning.
3280 if (printer->secdesc->owner_sid)
3281 printer->flags |= OWNER_SECURITY_INFORMATION;
3283 if (printer->secdesc->grp_sid)
3284 printer->flags |= GROUP_SECURITY_INFORMATION;
3286 if (printer->secdesc->dacl)
3287 printer->flags |= DACL_SECURITY_INFORMATION;
3289 if (printer->secdesc->sacl)
3290 printer->flags |= SACL_SECURITY_INFORMATION;
3293 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
3294 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
3295 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
3298 free_a_printer(&ntprinter, 2);
3300 *pp_printer = printer;
3304 /********************************************************************
3305 * construct_printer_info_4
3306 * fill a printer_info_4 struct
3307 ********************************************************************/
3309 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
3311 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3313 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3316 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3317 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
3318 printer->attributes = ntprinter->info_2->attributes;
3320 free_a_printer(&ntprinter, 2);
3324 /********************************************************************
3325 * construct_printer_info_5
3326 * fill a printer_info_5 struct
3327 ********************************************************************/
3329 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
3331 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3333 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3336 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
3337 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
3338 printer->attributes = ntprinter->info_2->attributes;
3339 printer->device_not_selected_timeout = 0x3a98;
3340 printer->transmission_retry_timeout = 0xafc8;
3342 free_a_printer(&ntprinter, 2);
3346 /********************************************************************
3347 Spoolss_enumprinters.
3348 ********************************************************************/
3350 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3354 int n_services=lp_numservices();
3355 PRINTER_INFO_1 *tp, *printers=NULL;
3356 PRINTER_INFO_1 current_prt;
3358 DEBUG(4,("enum_all_printers_info_1\n"));
3360 for (snum=0; snum<n_services; snum++) {
3361 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3362 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3364 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
3365 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
3366 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3367 SAFE_FREE(printers);
3372 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
3374 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
3380 /* check the required size. */
3381 for (i=0; i<*returned; i++)
3382 (*needed) += spoolss_size_printer_info_1(&printers[i]);
3384 if (!alloc_buffer_size(buffer, *needed))
3385 return WERR_INSUFFICIENT_BUFFER;
3387 /* fill the buffer with the structures */
3388 for (i=0; i<*returned; i++)
3389 smb_io_printer_info_1("", buffer, &printers[i], 0);
3392 SAFE_FREE(printers);
3394 if (*needed > offered) {
3396 return WERR_INSUFFICIENT_BUFFER;
3402 /********************************************************************
3403 enum_all_printers_info_1_local.
3404 *********************************************************************/
3406 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3408 DEBUG(4,("enum_all_printers_info_1_local\n"));
3410 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3413 /********************************************************************
3414 enum_all_printers_info_1_name.
3415 *********************************************************************/
3417 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3421 DEBUG(4,("enum_all_printers_info_1_name\n"));
3423 if ((name[0] == '\\') && (name[1] == '\\'))
3426 if (is_myname_or_ipaddr(s)) {
3427 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3430 return WERR_INVALID_NAME;
3433 /********************************************************************
3434 enum_all_printers_info_1_remote.
3435 *********************************************************************/
3437 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3439 PRINTER_INFO_1 *printer;
3440 fstring printername;
3443 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3445 /* JFM: currently it's more a place holder than anything else.
3446 * In the spooler world there is a notion of server registration.
3447 * the print servers are registring (sp ?) on the PDC (in the same domain)
3449 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3452 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3457 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3458 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3459 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3461 init_unistr(&printer->description, desc);
3462 init_unistr(&printer->name, printername);
3463 init_unistr(&printer->comment, comment);
3464 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3466 /* check the required size. */
3467 *needed += spoolss_size_printer_info_1(printer);
3469 if (!alloc_buffer_size(buffer, *needed)) {
3471 return WERR_INSUFFICIENT_BUFFER;
3474 /* fill the buffer with the structures */
3475 smb_io_printer_info_1("", buffer, printer, 0);
3480 if (*needed > offered) {
3482 return WERR_INSUFFICIENT_BUFFER;
3488 /********************************************************************
3489 enum_all_printers_info_1_network.
3490 *********************************************************************/
3492 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3494 DEBUG(4,("enum_all_printers_info_1_network\n"));
3496 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3499 /********************************************************************
3500 * api_spoolss_enumprinters
3502 * called from api_spoolss_enumprinters (see this to understand)
3503 ********************************************************************/
3505 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3509 int n_services=lp_numservices();
3510 PRINTER_INFO_2 *tp, *printers=NULL;
3511 PRINTER_INFO_2 current_prt;
3513 for (snum=0; snum<n_services; snum++) {
3514 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3515 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3517 if (construct_printer_info_2(¤t_prt, snum)) {
3518 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3519 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3520 SAFE_FREE(printers);
3525 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3526 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
3532 /* check the required size. */
3533 for (i=0; i<*returned; i++)
3534 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3536 if (!alloc_buffer_size(buffer, *needed)) {
3537 for (i=0; i<*returned; i++) {
3538 free_devmode(printers[i].devmode);
3540 SAFE_FREE(printers);
3541 return WERR_INSUFFICIENT_BUFFER;
3544 /* fill the buffer with the structures */
3545 for (i=0; i<*returned; i++)
3546 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3549 for (i=0; i<*returned; i++) {
3550 free_devmode(printers[i].devmode);
3552 SAFE_FREE(printers);
3554 if (*needed > offered) {
3556 return WERR_INSUFFICIENT_BUFFER;
3562 /********************************************************************
3563 * handle enumeration of printers at level 1
3564 ********************************************************************/
3566 static WERROR enumprinters_level1( uint32 flags, fstring name,
3567 NEW_BUFFER *buffer, uint32 offered,
3568 uint32 *needed, uint32 *returned)
3570 /* Not all the flags are equals */
3572 if (flags & PRINTER_ENUM_LOCAL)
3573 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3575 if (flags & PRINTER_ENUM_NAME)
3576 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3578 if (flags & PRINTER_ENUM_REMOTE)
3579 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3581 if (flags & PRINTER_ENUM_NETWORK)
3582 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3584 return WERR_OK; /* NT4sp5 does that */
3587 /********************************************************************
3588 * handle enumeration of printers at level 2
3589 ********************************************************************/
3591 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3592 NEW_BUFFER *buffer, uint32 offered,
3593 uint32 *needed, uint32 *returned)
3595 char *s = servername;
3597 if (flags & PRINTER_ENUM_LOCAL) {
3598 return enum_all_printers_info_2(buffer, offered, needed, returned);
3601 if (flags & PRINTER_ENUM_NAME) {
3602 if ((servername[0] == '\\') && (servername[1] == '\\'))
3604 if (is_myname_or_ipaddr(s))
3605 return enum_all_printers_info_2(buffer, offered, needed, returned);
3607 return WERR_INVALID_NAME;
3610 if (flags & PRINTER_ENUM_REMOTE)
3611 return WERR_UNKNOWN_LEVEL;
3616 /********************************************************************
3617 * handle enumeration of printers at level 5
3618 ********************************************************************/
3620 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3621 NEW_BUFFER *buffer, uint32 offered,
3622 uint32 *needed, uint32 *returned)
3624 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3628 /********************************************************************
3629 * api_spoolss_enumprinters
3631 * called from api_spoolss_enumprinters (see this to understand)
3632 ********************************************************************/
3634 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3636 uint32 flags = q_u->flags;
3637 UNISTR2 *servername = &q_u->servername;
3638 uint32 level = q_u->level;
3639 NEW_BUFFER *buffer = NULL;
3640 uint32 offered = q_u->offered;
3641 uint32 *needed = &r_u->needed;
3642 uint32 *returned = &r_u->returned;
3646 /* that's an [in out] buffer */
3647 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3648 buffer = r_u->buffer;
3650 DEBUG(4,("_spoolss_enumprinters\n"));
3657 * flags==PRINTER_ENUM_NAME
3658 * if name=="" then enumerates all printers
3659 * if name!="" then enumerate the printer
3660 * flags==PRINTER_ENUM_REMOTE
3661 * name is NULL, enumerate printers
3662 * Level 2: name!="" enumerates printers, name can't be NULL
3663 * Level 3: doesn't exist
3664 * Level 4: does a local registry lookup
3665 * Level 5: same as Level 2
3668 unistr2_to_ascii(name, servername, sizeof(name)-1);
3673 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3675 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3677 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3682 return WERR_UNKNOWN_LEVEL;
3685 /****************************************************************************
3686 ****************************************************************************/
3688 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3690 PRINTER_INFO_0 *printer=NULL;
3692 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3695 construct_printer_info_0(printer, snum);
3697 /* check the required size. */
3698 *needed += spoolss_size_printer_info_0(printer);
3700 if (!alloc_buffer_size(buffer, *needed)) {
3702 return WERR_INSUFFICIENT_BUFFER;
3705 /* fill the buffer with the structures */
3706 smb_io_printer_info_0("", buffer, printer, 0);
3711 if (*needed > offered) {
3712 return WERR_INSUFFICIENT_BUFFER;
3718 /****************************************************************************
3719 ****************************************************************************/
3721 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3723 PRINTER_INFO_1 *printer=NULL;
3725 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3728 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3730 /* check the required size. */
3731 *needed += spoolss_size_printer_info_1(printer);
3733 if (!alloc_buffer_size(buffer, *needed)) {
3735 return WERR_INSUFFICIENT_BUFFER;
3738 /* fill the buffer with the structures */
3739 smb_io_printer_info_1("", buffer, printer, 0);
3744 if (*needed > offered) {
3745 return WERR_INSUFFICIENT_BUFFER;
3751 /****************************************************************************
3752 ****************************************************************************/
3754 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3756 PRINTER_INFO_2 *printer=NULL;
3758 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3761 construct_printer_info_2(printer, snum);
3763 /* check the required size. */
3764 *needed += spoolss_size_printer_info_2(printer);
3766 if (!alloc_buffer_size(buffer, *needed)) {
3767 free_printer_info_2(printer);
3768 return WERR_INSUFFICIENT_BUFFER;
3771 /* fill the buffer with the structures */
3772 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3773 free_printer_info_2(printer);
3778 free_printer_info_2(printer);
3780 if (*needed > offered) {
3781 return WERR_INSUFFICIENT_BUFFER;
3787 /****************************************************************************
3788 ****************************************************************************/
3790 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3792 PRINTER_INFO_3 *printer=NULL;
3794 if (!construct_printer_info_3(&printer, snum))
3797 /* check the required size. */
3798 *needed += spoolss_size_printer_info_3(printer);
3800 if (!alloc_buffer_size(buffer, *needed)) {
3801 free_printer_info_3(printer);
3802 return WERR_INSUFFICIENT_BUFFER;
3805 /* fill the buffer with the structures */
3806 smb_io_printer_info_3("", buffer, printer, 0);
3809 free_printer_info_3(printer);
3811 if (*needed > offered) {
3812 return WERR_INSUFFICIENT_BUFFER;
3818 /****************************************************************************
3819 ****************************************************************************/
3821 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3823 PRINTER_INFO_4 *printer=NULL;
3825 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
3828 if (!construct_printer_info_4(printer, snum))
3831 /* check the required size. */
3832 *needed += spoolss_size_printer_info_4(printer);
3834 if (!alloc_buffer_size(buffer, *needed)) {
3835 free_printer_info_4(printer);
3836 return WERR_INSUFFICIENT_BUFFER;
3839 /* fill the buffer with the structures */
3840 smb_io_printer_info_4("", buffer, printer, 0);
3843 free_printer_info_4(printer);
3845 if (*needed > offered) {
3846 return WERR_INSUFFICIENT_BUFFER;
3852 /****************************************************************************
3853 ****************************************************************************/
3855 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3857 PRINTER_INFO_5 *printer=NULL;
3859 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
3862 if (!construct_printer_info_5(printer, snum))
3865 /* check the required size. */
3866 *needed += spoolss_size_printer_info_5(printer);
3868 if (!alloc_buffer_size(buffer, *needed)) {
3869 free_printer_info_5(printer);
3870 return WERR_INSUFFICIENT_BUFFER;
3873 /* fill the buffer with the structures */
3874 smb_io_printer_info_5("", buffer, printer, 0);
3877 free_printer_info_5(printer);
3879 if (*needed > offered) {
3880 return WERR_INSUFFICIENT_BUFFER;
3886 /****************************************************************************
3887 ****************************************************************************/
3889 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3891 POLICY_HND *handle = &q_u->handle;
3892 uint32 level = q_u->level;
3893 NEW_BUFFER *buffer = NULL;
3894 uint32 offered = q_u->offered;
3895 uint32 *needed = &r_u->needed;
3899 /* that's an [in out] buffer */
3900 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3901 buffer = r_u->buffer;
3905 if (!get_printer_snum(p, handle, &snum))
3910 return getprinter_level_0(snum, buffer, offered, needed);
3912 return getprinter_level_1(snum, buffer, offered, needed);
3914 return getprinter_level_2(snum, buffer, offered, needed);
3916 return getprinter_level_3(snum, buffer, offered, needed);
3918 return getprinter_level_4(snum, buffer, offered, needed);
3920 return getprinter_level_5(snum, buffer, offered, needed);
3922 return WERR_UNKNOWN_LEVEL;
3925 /********************************************************************
3926 * fill a DRIVER_INFO_1 struct
3927 ********************************************************************/
3929 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3931 init_unistr( &info->name, driver.info_3->name);
3934 /********************************************************************
3935 * construct_printer_driver_info_1
3936 ********************************************************************/
3938 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3940 NT_PRINTER_INFO_LEVEL *printer = NULL;
3941 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3943 ZERO_STRUCT(driver);
3945 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3946 return WERR_INVALID_PRINTER_NAME;
3948 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3949 return WERR_UNKNOWN_PRINTER_DRIVER;
3951 fill_printer_driver_info_1(info, driver, servername, architecture);
3953 free_a_printer(&printer,2);
3958 /********************************************************************
3959 * construct_printer_driver_info_2
3960 * fill a printer_info_2 struct
3961 ********************************************************************/
3963 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3967 info->version=driver.info_3->cversion;
3969 init_unistr( &info->name, driver.info_3->name );
3970 init_unistr( &info->architecture, driver.info_3->environment );
3973 if (strlen(driver.info_3->driverpath)) {
3974 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3975 init_unistr( &info->driverpath, temp );
3977 init_unistr( &info->driverpath, "" );
3979 if (strlen(driver.info_3->datafile)) {
3980 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3981 init_unistr( &info->datafile, temp );
3983 init_unistr( &info->datafile, "" );
3985 if (strlen(driver.info_3->configfile)) {
3986 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3987 init_unistr( &info->configfile, temp );
3989 init_unistr( &info->configfile, "" );
3992 /********************************************************************
3993 * construct_printer_driver_info_2
3994 * fill a printer_info_2 struct
3995 ********************************************************************/
3997 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3999 NT_PRINTER_INFO_LEVEL *printer = NULL;
4000 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4002 ZERO_STRUCT(printer);
4003 ZERO_STRUCT(driver);
4005 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4006 return WERR_INVALID_PRINTER_NAME;
4008 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4009 return WERR_UNKNOWN_PRINTER_DRIVER;
4011 fill_printer_driver_info_2(info, driver, servername);
4013 free_a_printer(&printer,2);
4018 /********************************************************************
4019 * copy a strings array and convert to UNICODE
4021 * convert an array of ascii string to a UNICODE string
4022 ********************************************************************/
4024 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
4032 DEBUG(6,("init_unistr_array\n"));
4036 if (char_array == NULL)
4040 if (!v) v = ""; /* hack to handle null lists */
4042 if (strlen(v) == 0) break;
4043 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
4044 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4045 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
4046 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4050 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
4055 (*uni_array)[j]=0x0000;
4058 DEBUGADD(6,("last one:done\n"));
4061 /********************************************************************
4062 * construct_printer_info_3
4063 * fill a printer_info_3 struct
4064 ********************************************************************/
4066 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4072 info->version=driver.info_3->cversion;
4074 init_unistr( &info->name, driver.info_3->name );
4075 init_unistr( &info->architecture, driver.info_3->environment );
4077 if (strlen(driver.info_3->driverpath)) {
4078 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4079 init_unistr( &info->driverpath, temp );
4081 init_unistr( &info->driverpath, "" );
4083 if (strlen(driver.info_3->datafile)) {
4084 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4085 init_unistr( &info->datafile, temp );
4087 init_unistr( &info->datafile, "" );
4089 if (strlen(driver.info_3->configfile)) {
4090 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4091 init_unistr( &info->configfile, temp );
4093 init_unistr( &info->configfile, "" );
4095 if (strlen(driver.info_3->helpfile)) {
4096 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4097 init_unistr( &info->helpfile, temp );
4099 init_unistr( &info->helpfile, "" );
4101 init_unistr( &info->monitorname, driver.info_3->monitorname );
4102 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4104 info->dependentfiles=NULL;
4105 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4108 /********************************************************************
4109 * construct_printer_info_3
4110 * fill a printer_info_3 struct
4111 ********************************************************************/
4113 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
4115 NT_PRINTER_INFO_LEVEL *printer = NULL;
4116 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4118 ZERO_STRUCT(driver);
4120 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4121 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4122 if (!W_ERROR_IS_OK(status))
4123 return WERR_INVALID_PRINTER_NAME;
4125 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4126 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4131 * I put this code in during testing. Helpful when commenting out the
4132 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4133 * as win2k always queries the driver using an infor level of 6.
4134 * I've left it in (but ifdef'd out) because I'll probably
4135 * use it in experimentation again in the future. --jerry 22/01/2002
4138 if (!W_ERROR_IS_OK(status)) {
4140 * Is this a W2k client ?
4143 /* Yes - try again with a WinNT driver. */
4145 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4146 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
4150 if (!W_ERROR_IS_OK(status)) {
4151 free_a_printer(&printer,2);
4152 return WERR_UNKNOWN_PRINTER_DRIVER;
4160 fill_printer_driver_info_3(info, driver, servername);
4162 free_a_printer(&printer,2);
4167 /********************************************************************
4168 * construct_printer_info_6
4169 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4170 ********************************************************************/
4172 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4178 memset(&nullstr, '\0', sizeof(fstring));
4180 info->version=driver.info_3->cversion;
4182 init_unistr( &info->name, driver.info_3->name );
4183 init_unistr( &info->architecture, driver.info_3->environment );
4185 if (strlen(driver.info_3->driverpath)) {
4186 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4187 init_unistr( &info->driverpath, temp );
4189 init_unistr( &info->driverpath, "" );
4191 if (strlen(driver.info_3->datafile)) {
4192 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4193 init_unistr( &info->datafile, temp );
4195 init_unistr( &info->datafile, "" );
4197 if (strlen(driver.info_3->configfile)) {
4198 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4199 init_unistr( &info->configfile, temp );
4201 init_unistr( &info->configfile, "" );
4203 if (strlen(driver.info_3->helpfile)) {
4204 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
4205 init_unistr( &info->helpfile, temp );
4207 init_unistr( &info->helpfile, "" );
4209 init_unistr( &info->monitorname, driver.info_3->monitorname );
4210 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
4212 info->dependentfiles=NULL;
4213 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
4215 info->previousdrivernames=NULL;
4216 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
4218 info->driver_date.low=0;
4219 info->driver_date.high=0;
4222 info->driver_version_low=0;
4223 info->driver_version_high=0;
4225 init_unistr( &info->mfgname, "");
4226 init_unistr( &info->oem_url, "");
4227 init_unistr( &info->hardware_id, "");
4228 init_unistr( &info->provider, "");
4231 /********************************************************************
4232 * construct_printer_info_6
4233 * fill a printer_info_6 struct
4234 ********************************************************************/
4236 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
4238 NT_PRINTER_INFO_LEVEL *printer = NULL;
4239 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4241 ZERO_STRUCT(driver);
4243 status=get_a_printer(&printer, 2, lp_servicename(snum) );
4244 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4245 if (!W_ERROR_IS_OK(status))
4246 return WERR_INVALID_PRINTER_NAME;
4248 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4249 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4250 if (!W_ERROR_IS_OK(status)) {
4252 * Is this a W2k client ?
4256 free_a_printer(&printer,2);
4257 return WERR_UNKNOWN_PRINTER_DRIVER;
4260 /* Yes - try again with a WinNT driver. */
4262 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4263 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
4264 if (!W_ERROR_IS_OK(status)) {
4265 free_a_printer(&printer,2);
4266 return WERR_UNKNOWN_PRINTER_DRIVER;
4270 fill_printer_driver_info_6(info, driver, servername);
4272 free_a_printer(&printer,2);
4277 /****************************************************************************
4278 ****************************************************************************/
4280 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
4282 SAFE_FREE(info->dependentfiles);
4285 /****************************************************************************
4286 ****************************************************************************/
4288 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
4290 SAFE_FREE(info->dependentfiles);
4294 /****************************************************************************
4295 ****************************************************************************/
4297 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4299 DRIVER_INFO_1 *info=NULL;
4302 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
4305 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
4306 if (!W_ERROR_IS_OK(status)) {
4311 /* check the required size. */
4312 *needed += spoolss_size_printer_driver_info_1(info);
4314 if (!alloc_buffer_size(buffer, *needed)) {
4316 return WERR_INSUFFICIENT_BUFFER;
4319 /* fill the buffer with the structures */
4320 smb_io_printer_driver_info_1("", buffer, info, 0);
4325 if (*needed > offered)
4326 return WERR_INSUFFICIENT_BUFFER;
4331 /****************************************************************************
4332 ****************************************************************************/
4334 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4336 DRIVER_INFO_2 *info=NULL;
4339 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
4342 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
4343 if (!W_ERROR_IS_OK(status)) {
4348 /* check the required size. */
4349 *needed += spoolss_size_printer_driver_info_2(info);
4351 if (!alloc_buffer_size(buffer, *needed)) {
4353 return WERR_INSUFFICIENT_BUFFER;
4356 /* fill the buffer with the structures */
4357 smb_io_printer_driver_info_2("", buffer, info, 0);
4362 if (*needed > offered)
4363 return WERR_INSUFFICIENT_BUFFER;
4368 /****************************************************************************
4369 ****************************************************************************/
4371 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4378 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
4379 if (!W_ERROR_IS_OK(status)) {
4383 /* check the required size. */
4384 *needed += spoolss_size_printer_driver_info_3(&info);
4386 if (!alloc_buffer_size(buffer, *needed)) {
4387 free_printer_driver_info_3(&info);
4388 return WERR_INSUFFICIENT_BUFFER;
4391 /* fill the buffer with the structures */
4392 smb_io_printer_driver_info_3("", buffer, &info, 0);
4394 free_printer_driver_info_3(&info);
4396 if (*needed > offered)
4397 return WERR_INSUFFICIENT_BUFFER;
4402 /****************************************************************************
4403 ****************************************************************************/
4405 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4412 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
4413 if (!W_ERROR_IS_OK(status)) {
4417 /* check the required size. */
4418 *needed += spoolss_size_printer_driver_info_6(&info);
4420 if (!alloc_buffer_size(buffer, *needed)) {
4421 free_printer_driver_info_6(&info);
4422 return WERR_INSUFFICIENT_BUFFER;
4425 /* fill the buffer with the structures */
4426 smb_io_printer_driver_info_6("", buffer, &info, 0);
4428 free_printer_driver_info_6(&info);
4430 if (*needed > offered)
4431 return WERR_INSUFFICIENT_BUFFER;
4436 /****************************************************************************
4437 ****************************************************************************/
4439 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
4441 POLICY_HND *handle = &q_u->handle;
4442 UNISTR2 *uni_arch = &q_u->architecture;
4443 uint32 level = q_u->level;
4444 uint32 clientmajorversion = q_u->clientmajorversion;
4445 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
4446 NEW_BUFFER *buffer = NULL;
4447 uint32 offered = q_u->offered;
4448 uint32 *needed = &r_u->needed;
4449 uint32 *servermajorversion = &r_u->servermajorversion;
4450 uint32 *serverminorversion = &r_u->serverminorversion;
4453 fstring architecture;
4456 /* that's an [in out] buffer */
4457 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4458 buffer = r_u->buffer;
4460 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4463 *servermajorversion=0;
4464 *serverminorversion=0;
4466 pstrcpy(servername, get_called_name());
4467 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4469 if (!get_printer_snum(p, handle, &snum))
4474 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4476 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4478 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4480 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4483 return WERR_UNKNOWN_LEVEL;
4486 /****************************************************************************
4487 ****************************************************************************/
4489 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4491 POLICY_HND *handle = &q_u->handle;
4493 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4496 DEBUG(3,("Error in startpageprinter printer handle\n"));
4500 Printer->page_started=True;
4504 /****************************************************************************
4505 ****************************************************************************/
4507 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4509 POLICY_HND *handle = &q_u->handle;
4511 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4514 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
4518 Printer->page_started=False;
4519 print_job_endpage(Printer->jobid);
4524 /********************************************************************
4525 * api_spoolss_getprinter
4526 * called from the spoolss dispatcher
4528 ********************************************************************/
4530 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4532 POLICY_HND *handle = &q_u->handle;
4533 /* uint32 level = q_u->doc_info_container.level; - notused. */
4534 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4535 uint32 *jobid = &r_u->jobid;
4537 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4541 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4542 struct current_user user;
4545 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4549 get_current_user(&user, p);
4552 * a nice thing with NT is it doesn't listen to what you tell it.
4553 * when asked to send _only_ RAW datas, it tries to send datas
4556 * So I add checks like in NT Server ...
4558 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4559 * there's a bug in NT client-side code, so we'll fix it in the
4560 * server-side code. *nnnnnggggh!*
4563 if (info_1->p_datatype != 0) {
4564 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4565 if (strcmp(datatype, "RAW") != 0) {
4567 return WERR_INVALID_DATATYPE;
4571 /* get the share number of the printer */
4572 if (!get_printer_snum(p, handle, &snum)) {
4576 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4578 Printer->jobid = print_job_start(&user, snum, jobname);
4580 /* An error occured in print_job_start() so return an appropriate
4583 if (Printer->jobid == -1) {
4584 return map_werror_from_unix(errno);
4587 Printer->document_started=True;
4588 (*jobid) = Printer->jobid;
4593 /********************************************************************
4594 * api_spoolss_getprinter
4595 * called from the spoolss dispatcher
4597 ********************************************************************/
4599 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4601 POLICY_HND *handle = &q_u->handle;
4603 return _spoolss_enddocprinter_internal(p, handle);
4606 /****************************************************************************
4607 ****************************************************************************/
4609 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4611 POLICY_HND *handle = &q_u->handle;
4612 uint32 buffer_size = q_u->buffer_size;
4613 uint8 *buffer = q_u->buffer;
4614 uint32 *buffer_written = &q_u->buffer_size2;
4616 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4619 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
4620 r_u->buffer_written = q_u->buffer_size2;
4624 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4627 r_u->buffer_written = q_u->buffer_size2;
4632 /********************************************************************
4633 * api_spoolss_getprinter
4634 * called from the spoolss dispatcher
4636 ********************************************************************/
4638 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4641 struct current_user user;
4643 WERROR errcode = WERR_BADFUNC;
4644 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4646 get_current_user(&user, p);
4649 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4653 if (!get_printer_snum(p, handle, &snum))
4657 case PRINTER_CONTROL_PAUSE:
4658 if (print_queue_pause(&user, snum, &errcode)) {
4662 case PRINTER_CONTROL_RESUME:
4663 case PRINTER_CONTROL_UNPAUSE:
4664 if (print_queue_resume(&user, snum, &errcode)) {
4668 case PRINTER_CONTROL_PURGE:
4669 if (print_queue_purge(&user, snum, &errcode)) {
4674 return WERR_UNKNOWN_LEVEL;
4680 /********************************************************************
4681 * api_spoolss_abortprinter
4682 ********************************************************************/
4684 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4686 POLICY_HND *handle = &q_u->handle;
4688 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4691 /********************************************************************
4692 * called by spoolss_api_setprinter
4693 * when updating a printer description
4694 ********************************************************************/
4696 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4697 const SPOOL_PRINTER_INFO_LEVEL *info,
4698 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4700 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4701 struct current_user user;
4705 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4707 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4708 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
4709 OUR_HANDLE(handle)));
4711 result = WERR_BADFID;
4715 /* NT seems to like setting the security descriptor even though
4716 nothing may have actually changed. This causes annoying
4717 dialog boxes when the user doesn't have permission to change
4718 the security descriptor. */
4720 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4722 if (DEBUGLEVEL >= 10) {
4726 the_acl = old_secdesc_ctr->sec->dacl;
4727 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4728 PRINTERNAME(snum), the_acl->num_aces));
4730 for (i = 0; i < the_acl->num_aces; i++) {
4733 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4735 DEBUG(10, ("%s 0x%08x\n", sid_str,
4736 the_acl->ace[i].info.mask));
4739 the_acl = secdesc_ctr->sec->dacl;
4742 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4743 PRINTERNAME(snum), the_acl->num_aces));
4745 for (i = 0; i < the_acl->num_aces; i++) {
4748 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4750 DEBUG(10, ("%s 0x%08x\n", sid_str,
4751 the_acl->ace[i].info.mask));
4754 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4758 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4760 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4765 /* Work out which user is performing the operation */
4767 get_current_user(&user, p);
4769 /* Check the user has permissions to change the security
4770 descriptor. By experimentation with two NT machines, the user
4771 requires Full Access to the printer to change security
4774 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4775 result = WERR_ACCESS_DENIED;
4779 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4786 /********************************************************************
4787 Do Samba sanity checks on a printer info struct.
4788 this has changed purpose: it now "canonicalises" printer
4789 info from a client rather than just checking it is correct
4790 ********************************************************************/
4792 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4794 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4795 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4797 /* we force some elements to "correct" values */
4798 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
4799 fstrcpy(info->sharename, lp_servicename(snum));
4800 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4801 get_called_name(), info->sharename);
4802 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
4807 /****************************************************************************
4808 ****************************************************************************/
4810 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4812 char *cmd = lp_addprinter_cmd();
4815 pstring driverlocation;
4819 fstring remote_machine = "%m";
4821 /* build driver path... only 9X architecture is needed for legacy reasons */
4822 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4824 /* change \ to \\ for the shell */
4825 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4827 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4828 cmd, printer->info_2->printername, printer->info_2->sharename,
4829 printer->info_2->portname, printer->info_2->drivername,
4830 printer->info_2->location, driverlocation, remote_machine);
4832 /* Convert script args to unix-codepage */
4833 DEBUG(10,("Running [%s]\n", command));
4834 ret = smbrun(command, &fd);
4835 DEBUGADD(10,("returned [%d]\n", ret));
4844 /* Get lines and convert them back to dos-codepage */
4845 qlines = fd_lines_load(fd, &numlines);
4846 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4850 /* Set the portname to what the script says the portname should be. */
4851 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4852 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4854 /* Send SIGHUP to process group... is there a better way? */
4859 file_lines_free(qlines);
4861 update_server_announce_as_printserver();
4868 /* Return true if two devicemodes are equal */
4870 #define DEVMODE_CHECK_INT(field) \
4871 if (d1->field != d2->field) { \
4872 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4873 d1->field, d2->field)); \
4877 /************************************************************************
4878 Handy, but currently unused functions
4879 ***********************************************************************/
4881 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4883 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4886 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4887 return False; /* if either is exclusively NULL are not equal */
4890 if (!strequal(d1->devicename, d2->devicename)) {
4891 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4895 if (!strequal(d1->formname, d2->formname)) {
4896 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4900 DEVMODE_CHECK_INT(specversion);
4901 DEVMODE_CHECK_INT(driverversion);
4902 DEVMODE_CHECK_INT(driverextra);
4903 DEVMODE_CHECK_INT(orientation);
4904 DEVMODE_CHECK_INT(papersize);
4905 DEVMODE_CHECK_INT(paperlength);
4906 DEVMODE_CHECK_INT(paperwidth);
4907 DEVMODE_CHECK_INT(scale);
4908 DEVMODE_CHECK_INT(copies);
4909 DEVMODE_CHECK_INT(defaultsource);
4910 DEVMODE_CHECK_INT(printquality);
4911 DEVMODE_CHECK_INT(color);
4912 DEVMODE_CHECK_INT(duplex);
4913 DEVMODE_CHECK_INT(yresolution);
4914 DEVMODE_CHECK_INT(ttoption);
4915 DEVMODE_CHECK_INT(collate);
4916 DEVMODE_CHECK_INT(logpixels);
4918 DEVMODE_CHECK_INT(fields);
4919 DEVMODE_CHECK_INT(bitsperpel);
4920 DEVMODE_CHECK_INT(pelswidth);
4921 DEVMODE_CHECK_INT(pelsheight);
4922 DEVMODE_CHECK_INT(displayflags);
4923 DEVMODE_CHECK_INT(displayfrequency);
4924 DEVMODE_CHECK_INT(icmmethod);
4925 DEVMODE_CHECK_INT(icmintent);
4926 DEVMODE_CHECK_INT(mediatype);
4927 DEVMODE_CHECK_INT(dithertype);
4928 DEVMODE_CHECK_INT(reserved1);
4929 DEVMODE_CHECK_INT(reserved2);
4930 DEVMODE_CHECK_INT(panningwidth);
4931 DEVMODE_CHECK_INT(panningheight);
4933 /* compare the private data if it exists */
4934 if (!d1->driverextra && !d2->driverextra) goto equal;
4937 DEVMODE_CHECK_INT(driverextra);
4939 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4940 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4945 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4949 /* Return true if two NT_PRINTER_PARAM structures are equal */
4951 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4952 NT_PRINTER_PARAM *p2)
4954 if (!p1 && !p2) goto equal;
4956 if ((!p1 && p2) || (p1 && !p2)) {
4957 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4961 /* Compare lists of printer parameters */
4965 NT_PRINTER_PARAM *q = p1;
4967 /* Find the parameter in the second structure */
4971 if (strequal(p1->value, q->value)) {
4973 if (p1->type != q->type) {
4974 DEBUG(10, ("nt_printer_param_equal():"
4975 "types for %s differ (%d != %d)\n",
4976 p1->value, p1->type,
4981 if (p1->data_len != q->data_len) {
4982 DEBUG(10, ("nt_printer_param_equal():"
4983 "len for %s differs (%d != %d)\n",
4984 p1->value, p1->data_len,
4989 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4992 DEBUG(10, ("nt_printer_param_equal():"
4993 "data for %s differs\n", p1->value));
5003 DEBUG(10, ("nt_printer_param_equal(): param %s "
5004 "does not exist\n", p1->value));
5013 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
5017 /********************************************************************
5018 * Called by update_printer when trying to work out whether to
5019 * actually update printer info.
5020 ********************************************************************/
5022 #define PI_CHECK_INT(field) \
5023 if (pi1->field != pi2->field) { \
5024 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
5025 pi1->field, pi2->field)); \
5029 #define PI_CHECK_STR(field) \
5030 if (!strequal(pi1->field, pi2->field)) { \
5031 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
5032 pi1->field, pi2->field)); \
5036 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
5037 NT_PRINTER_INFO_LEVEL *p2)
5039 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
5041 /* Trivial conditions */
5043 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
5047 if ((!p1 && p2) || (p1 && !p2) ||
5048 (!p1->info_2 && p2->info_2) ||
5049 (p1->info_2 && !p2->info_2)) {
5050 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
5055 /* Compare two nt_printer_info_level structures. Don't compare
5056 status or cjobs as they seem to have something to do with the
5062 /* Don't check the attributes as we stomp on the value in
5063 check_printer_ok() anyway. */
5066 PI_CHECK_INT(attributes);
5069 PI_CHECK_INT(priority);
5070 PI_CHECK_INT(default_priority);
5071 PI_CHECK_INT(starttime);
5072 PI_CHECK_INT(untiltime);
5073 PI_CHECK_INT(averageppm);
5075 /* Yuck - don't check the printername or servername as the
5076 mod_a_printer() code plays games with them. You can't
5077 change the printername or the sharename through this interface
5080 PI_CHECK_STR(sharename);
5081 PI_CHECK_STR(portname);
5082 PI_CHECK_STR(drivername);
5083 PI_CHECK_STR(comment);
5084 PI_CHECK_STR(location);
5086 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
5090 PI_CHECK_STR(sepfile);
5091 PI_CHECK_STR(printprocessor);
5092 PI_CHECK_STR(datatype);
5093 PI_CHECK_STR(parameters);
5095 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
5099 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
5103 PI_CHECK_INT(changeid);
5104 PI_CHECK_INT(c_setprinter);
5105 PI_CHECK_INT(setuptime);
5108 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
5114 /********************************************************************
5115 * Called by spoolss_api_setprinter
5116 * when updating a printer description.
5117 ********************************************************************/
5119 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5120 const SPOOL_PRINTER_INFO_LEVEL *info,
5121 DEVICEMODE *devmode)
5124 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5125 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5126 PRINTER_MESSAGE_INFO msg;
5129 DEBUG(8,("update_printer\n"));
5136 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5137 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5138 result = WERR_UNKNOWN_LEVEL;
5143 result = WERR_BADFID;
5147 if (!get_printer_snum(p, handle, &snum)) {
5148 result = WERR_BADFID;
5152 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5153 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5154 result = WERR_BADFID;
5158 DEBUGADD(8,("Converting info_2 struct\n"));
5161 * convert_printer_info converts the incoming
5162 * info from the client and overwrites the info
5163 * just read from the tdb in the pointer 'printer'.
5166 if (!convert_printer_info(info, printer, level)) {
5167 result = WERR_NOMEM;
5172 /* we have a valid devmode
5173 convert it and link it*/
5175 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5176 if (!convert_devicemode(printer->info_2->printername, devmode,
5177 &printer->info_2->devmode)) {
5178 result = WERR_NOMEM;
5183 /* Do sanity check on the requested changes for Samba */
5185 if (!check_printer_ok(printer->info_2, snum)) {
5186 result = WERR_INVALID_PARAM;
5193 * Another one of those historical misunderstandings...
5194 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5195 * I'm leaving it here as a reminder. --jerry
5198 if (nt_printer_info_level_equal(printer, old_printer)) {
5199 DEBUG(3, ("update_printer: printer info has not changed\n"));
5206 /* Check calling user has permission to update printer description */
5208 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5209 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5210 result = WERR_ACCESS_DENIED;
5214 /* Call addprinter hook */
5216 if (*lp_addprinter_cmd()) {
5217 if ( !add_printer_hook(printer) ) {
5218 result = WERR_ACCESS_DENIED;
5224 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5225 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5226 * requires Win32 client code (see other notes elsewhere in the code).
5228 if (printer->info_2->devmode &&
5229 printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) {
5231 DEBUG(10,("update_printer: Save printer driver init data\n"));
5232 printer->info_2->devmode->displayfrequency = 0;
5234 if (update_driver_init(*printer, 2)!=0) {
5235 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5236 result = WERR_ACCESS_DENIED;
5241 * When a *new* driver is bound to a printer, the drivername is used to
5242 * lookup previously saved driver initialization info, which is then
5243 * bound to the printer, simulating what happens in the Windows arch.
5245 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){
5246 set_driver_init(printer, 2);
5247 msg.flags |= PRINTER_MESSAGE_DRIVER;
5251 /* Update printer info */
5252 result = mod_a_printer(*printer, 2);
5254 /* flag which changes actually occured. This is a small subset of
5255 all the possible changes */
5257 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5258 msg.flags |= PRINTER_MESSAGE_COMMENT;
5260 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5261 msg.flags |= PRINTER_MESSAGE_SHARENAME;
5263 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5264 msg.flags |= PRINTER_MESSAGE_PORT;
5266 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5267 msg.flags |= PRINTER_MESSAGE_LOCATION;
5269 msg.low = PRINTER_CHANGE_ADD_PRINTER;
5270 fstrcpy(msg.printer_name, printer->info_2->printername);
5272 /* only send a notify if something changed */
5274 srv_spoolss_sendnotify(msg.printer_name, 0, PRINTER_CHANGE_ADD_PRINTER, msg.flags);
5278 free_a_printer(&printer, 2);
5279 free_a_printer(&old_printer, 2);
5285 /****************************************************************************
5286 ****************************************************************************/
5288 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
5290 POLICY_HND *handle = &q_u->handle;
5291 uint32 level = q_u->level;
5292 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5293 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
5294 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
5295 uint32 command = q_u->command;
5297 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5300 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5304 /* check the level */
5307 return control_printer(handle, command, p);
5309 return update_printer(p, handle, level, info, devmode_ctr.devmode);
5311 return update_printer_sec(handle, level, info, p,
5314 return WERR_UNKNOWN_LEVEL;
5318 /****************************************************************************
5319 ****************************************************************************/
5321 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
5323 POLICY_HND *handle = &q_u->handle;
5325 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5328 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5332 if (Printer->notify.client_connected==True)
5333 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
5335 Printer->notify.flags=0;
5336 Printer->notify.options=0;
5337 Printer->notify.localmachine[0]='\0';
5338 Printer->notify.printerlocal=0;
5339 if (Printer->notify.option)
5340 free_spool_notify_option(&Printer->notify.option);
5341 Printer->notify.client_connected=False;
5346 /****************************************************************************
5347 ****************************************************************************/
5349 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
5351 /* that's an [in out] buffer (despite appearences to the contrary) */
5352 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5355 return WERR_INVALID_PARAM; /* this is what a NT server
5356 returns for AddJob. AddJob
5357 must fail on non-local
5361 /****************************************************************************
5362 ****************************************************************************/
5364 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
5365 int position, int snum)
5371 t=gmtime(&queue->time);
5372 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5374 job_info->jobid=queue->job;
5375 init_unistr(&job_info->printername, lp_servicename(snum));
5376 init_unistr(&job_info->machinename, temp_name);
5377 init_unistr(&job_info->username, queue->fs_user);
5378 init_unistr(&job_info->document, queue->fs_file);
5379 init_unistr(&job_info->datatype, "RAW");
5380 init_unistr(&job_info->text_status, "");
5381 job_info->status=nt_printj_status(queue->status);
5382 job_info->priority=queue->priority;
5383 job_info->position=position;
5384 job_info->totalpages=queue->page_count;
5385 job_info->pagesprinted=0;
5387 make_systemtime(&job_info->submitted, t);
5390 /****************************************************************************
5391 ****************************************************************************/
5393 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
5394 int position, int snum,
5395 NT_PRINTER_INFO_LEVEL *ntprinter,
5396 DEVICEMODE *devmode)
5402 t=gmtime(&queue->time);
5403 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
5405 job_info->jobid=queue->job;
5407 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
5409 init_unistr(&job_info->printername, chaine);
5411 init_unistr(&job_info->machinename, temp_name);
5412 init_unistr(&job_info->username, queue->fs_user);
5413 init_unistr(&job_info->document, queue->fs_file);
5414 init_unistr(&job_info->notifyname, queue->fs_user);
5415 init_unistr(&job_info->datatype, "RAW");
5416 init_unistr(&job_info->printprocessor, "winprint");
5417 init_unistr(&job_info->parameters, "");
5418 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
5419 init_unistr(&job_info->text_status, "");
5421 /* and here the security descriptor */
5423 job_info->status=nt_printj_status(queue->status);
5424 job_info->priority=queue->priority;
5425 job_info->position=position;
5426 job_info->starttime=0;
5427 job_info->untiltime=0;
5428 job_info->totalpages=queue->page_count;
5429 job_info->size=queue->size;
5430 make_systemtime(&(job_info->submitted), t);
5431 job_info->timeelapsed=0;
5432 job_info->pagesprinted=0;
5434 job_info->devmode = devmode;
5439 /****************************************************************************
5440 Enumjobs at level 1.
5441 ****************************************************************************/
5443 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
5444 NEW_BUFFER *buffer, uint32 offered,
5445 uint32 *needed, uint32 *returned)
5450 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
5457 for (i=0; i<*returned; i++)
5458 fill_job_info_1(&info[i], &queue[i], i, snum);
5462 /* check the required size. */
5463 for (i=0; i<*returned; i++)
5464 (*needed) += spoolss_size_job_info_1(&info[i]);
5466 if (!alloc_buffer_size(buffer, *needed)) {
5468 return WERR_INSUFFICIENT_BUFFER;
5471 /* fill the buffer with the structures */
5472 for (i=0; i<*returned; i++)
5473 smb_io_job_info_1("", buffer, &info[i], 0);
5478 if (*needed > offered) {
5480 return WERR_INSUFFICIENT_BUFFER;
5486 /****************************************************************************
5487 Enumjobs at level 2.
5488 ****************************************************************************/
5490 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5491 NEW_BUFFER *buffer, uint32 offered,
5492 uint32 *needed, uint32 *returned)
5494 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5495 JOB_INFO_2 *info = NULL;
5498 DEVICEMODE *devmode = NULL;
5500 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5503 result = WERR_NOMEM;
5507 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5508 if (!W_ERROR_IS_OK(result)) {
5513 if (!(devmode = construct_dev_mode(snum))) {
5515 result = WERR_NOMEM;
5519 for (i=0; i<*returned; i++)
5520 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
5523 free_a_printer(&ntprinter, 2);
5526 /* check the required size. */
5527 for (i=0; i<*returned; i++)
5528 (*needed) += spoolss_size_job_info_2(&info[i]);
5530 if (*needed > offered) {
5532 result = WERR_INSUFFICIENT_BUFFER;
5536 if (!alloc_buffer_size(buffer, *needed)) {
5538 result = WERR_INSUFFICIENT_BUFFER;
5542 /* fill the buffer with the structures */
5543 for (i=0; i<*returned; i++)
5544 smb_io_job_info_2("", buffer, &info[i], 0);
5549 free_a_printer(&ntprinter, 2);
5550 free_devmode(devmode);
5557 /****************************************************************************
5559 ****************************************************************************/
5561 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5563 POLICY_HND *handle = &q_u->handle;
5564 /* uint32 firstjob = q_u->firstjob; - notused. */
5565 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5566 uint32 level = q_u->level;
5567 NEW_BUFFER *buffer = NULL;
5568 uint32 offered = q_u->offered;
5569 uint32 *needed = &r_u->needed;
5570 uint32 *returned = &r_u->returned;
5573 print_status_struct prt_status;
5574 print_queue_struct *queue=NULL;
5576 /* that's an [in out] buffer */
5577 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5578 buffer = r_u->buffer;
5580 DEBUG(4,("_spoolss_enumjobs\n"));
5585 if (!get_printer_snum(p, handle, &snum))
5588 *returned = print_queue_status(snum, &queue, &prt_status);
5589 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5591 if (*returned == 0) {
5598 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5600 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5604 return WERR_UNKNOWN_LEVEL;
5608 /****************************************************************************
5609 ****************************************************************************/
5611 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5616 /****************************************************************************
5617 ****************************************************************************/
5619 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5621 POLICY_HND *handle = &q_u->handle;
5622 uint32 jobid = q_u->jobid;
5623 /* uint32 level = q_u->level; - notused. */
5624 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5625 uint32 command = q_u->command;
5627 struct current_user user;
5629 WERROR errcode = WERR_BADFUNC;
5631 if (!get_printer_snum(p, handle, &snum)) {
5635 if (!print_job_exists(jobid)) {
5636 return WERR_INVALID_PRINTER_NAME;
5639 get_current_user(&user, p);
5642 case JOB_CONTROL_CANCEL:
5643 case JOB_CONTROL_DELETE:
5644 if (print_job_delete(&user, jobid, &errcode)) {
5648 case JOB_CONTROL_PAUSE:
5649 if (print_job_pause(&user, jobid, &errcode)) {
5653 case JOB_CONTROL_RESTART:
5654 case JOB_CONTROL_RESUME:
5655 if (print_job_resume(&user, jobid, &errcode)) {
5660 return WERR_UNKNOWN_LEVEL;
5666 /****************************************************************************
5667 Enumerates all printer drivers at level 1.
5668 ****************************************************************************/
5670 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5675 fstring *list = NULL;
5677 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5678 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5682 #define MAX_VERSION 4
5684 for (version=0; version<MAX_VERSION; version++) {
5686 ndrivers=get_ntdrivers(&list, architecture, version);
5687 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5693 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5694 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5695 SAFE_FREE(driver_info_1);
5699 else driver_info_1 = tdi1;
5702 for (i=0; i<ndrivers; i++) {
5704 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5705 ZERO_STRUCT(driver);
5706 status = get_a_printer_driver(&driver, 3, list[i],
5707 architecture, version);
5708 if (!W_ERROR_IS_OK(status)) {
5712 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5713 free_a_printer_driver(driver, 3);
5716 *returned+=ndrivers;
5720 /* check the required size. */
5721 for (i=0; i<*returned; i++) {
5722 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5723 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5726 if (!alloc_buffer_size(buffer, *needed)) {
5727 SAFE_FREE(driver_info_1);
5728 return WERR_INSUFFICIENT_BUFFER;
5731 /* fill the buffer with the driver structures */
5732 for (i=0; i<*returned; i++) {
5733 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5734 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5737 SAFE_FREE(driver_info_1);
5739 if (*needed > offered) {
5741 return WERR_INSUFFICIENT_BUFFER;
5747 /****************************************************************************
5748 Enumerates all printer drivers at level 2.
5749 ****************************************************************************/
5751 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5756 fstring *list = NULL;
5758 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5759 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5763 #define MAX_VERSION 4
5765 for (version=0; version<MAX_VERSION; version++) {
5767 ndrivers=get_ntdrivers(&list, architecture, version);
5768 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5774 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5775 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5776 SAFE_FREE(driver_info_2);
5780 else driver_info_2 = tdi2;
5783 for (i=0; i<ndrivers; i++) {
5786 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5787 ZERO_STRUCT(driver);
5788 status = get_a_printer_driver(&driver, 3, list[i],
5789 architecture, version);
5790 if (!W_ERROR_IS_OK(status)) {
5794 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5795 free_a_printer_driver(driver, 3);
5798 *returned+=ndrivers;
5802 /* check the required size. */
5803 for (i=0; i<*returned; i++) {
5804 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5805 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5808 if (!alloc_buffer_size(buffer, *needed)) {
5809 SAFE_FREE(driver_info_2);
5810 return WERR_INSUFFICIENT_BUFFER;
5813 /* fill the buffer with the form structures */
5814 for (i=0; i<*returned; i++) {
5815 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5816 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5819 SAFE_FREE(driver_info_2);
5821 if (*needed > offered) {
5823 return WERR_INSUFFICIENT_BUFFER;
5829 /****************************************************************************
5830 Enumerates all printer drivers at level 3.
5831 ****************************************************************************/
5833 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5838 fstring *list = NULL;
5840 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5841 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5845 #define MAX_VERSION 4
5847 for (version=0; version<MAX_VERSION; version++) {
5849 ndrivers=get_ntdrivers(&list, architecture, version);
5850 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5856 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5857 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5858 SAFE_FREE(driver_info_3);
5862 else driver_info_3 = tdi3;
5865 for (i=0; i<ndrivers; i++) {
5868 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5869 ZERO_STRUCT(driver);
5870 status = get_a_printer_driver(&driver, 3, list[i],
5871 architecture, version);
5872 if (!W_ERROR_IS_OK(status)) {
5876 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5877 free_a_printer_driver(driver, 3);
5880 *returned+=ndrivers;
5884 /* check the required size. */
5885 for (i=0; i<*returned; i++) {
5886 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5887 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5890 if (!alloc_buffer_size(buffer, *needed)) {
5891 SAFE_FREE(driver_info_3);
5892 return WERR_INSUFFICIENT_BUFFER;
5895 /* fill the buffer with the driver structures */
5896 for (i=0; i<*returned; i++) {
5897 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5898 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5901 for (i=0; i<*returned; i++)
5902 SAFE_FREE(driver_info_3[i].dependentfiles);
5904 SAFE_FREE(driver_info_3);
5906 if (*needed > offered) {
5908 return WERR_INSUFFICIENT_BUFFER;
5914 /****************************************************************************
5915 Enumerates all printer drivers.
5916 ****************************************************************************/
5918 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5920 /* UNISTR2 *name = &q_u->name; - notused. */
5921 UNISTR2 *environment = &q_u->environment;
5922 uint32 level = q_u->level;
5923 NEW_BUFFER *buffer = NULL;
5924 uint32 offered = q_u->offered;
5925 uint32 *needed = &r_u->needed;
5926 uint32 *returned = &r_u->returned;
5928 fstring *list = NULL;
5930 fstring architecture;
5932 /* that's an [in out] buffer */
5933 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5934 buffer = r_u->buffer;
5936 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5937 fstrcpy(servername, get_called_name());
5941 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5945 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5947 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5949 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5953 return WERR_UNKNOWN_LEVEL;
5957 /****************************************************************************
5958 ****************************************************************************/
5960 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5962 form->flag=list->flag;
5963 init_unistr(&form->name, list->name);
5964 form->width=list->width;
5965 form->length=list->length;
5966 form->left=list->left;
5967 form->top=list->top;
5968 form->right=list->right;
5969 form->bottom=list->bottom;
5972 /****************************************************************************
5973 ****************************************************************************/
5975 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5977 /* POLICY_HND *handle = &q_u->handle; - notused. */
5978 uint32 level = q_u->level;
5979 NEW_BUFFER *buffer = NULL;
5980 uint32 offered = q_u->offered;
5981 uint32 *needed = &r_u->needed;
5982 uint32 *numofforms = &r_u->numofforms;
5983 uint32 numbuiltinforms;
5985 nt_forms_struct *list=NULL;
5986 nt_forms_struct *builtinlist=NULL;
5991 /* that's an [in out] buffer */
5992 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5993 buffer = r_u->buffer;
5995 DEBUG(4,("_spoolss_enumforms\n"));
5996 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5997 DEBUGADD(5,("Info level [%d]\n", level));
5999 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6000 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6001 *numofforms = get_ntforms(&list);
6002 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6003 *numofforms += numbuiltinforms;
6005 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6009 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6014 /* construct the list of form structures */
6015 for (i=0; i<numbuiltinforms; i++) {
6016 DEBUGADD(6,("Filling form number [%d]\n",i));
6017 fill_form_1(&forms_1[i], &builtinlist[i]);
6020 SAFE_FREE(builtinlist);
6022 for (; i<*numofforms; i++) {
6023 DEBUGADD(6,("Filling form number [%d]\n",i));
6024 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6029 /* check the required size. */
6030 for (i=0; i<numbuiltinforms; i++) {
6031 DEBUGADD(6,("adding form [%d]'s size\n",i));
6032 buffer_size += spoolss_size_form_1(&forms_1[i]);
6034 for (; i<*numofforms; i++) {
6035 DEBUGADD(6,("adding form [%d]'s size\n",i));
6036 buffer_size += spoolss_size_form_1(&forms_1[i]);
6039 *needed=buffer_size;
6041 if (!alloc_buffer_size(buffer, buffer_size)){
6043 return WERR_INSUFFICIENT_BUFFER;
6046 /* fill the buffer with the form structures */
6047 for (i=0; i<numbuiltinforms; i++) {
6048 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6049 smb_io_form_1("", buffer, &forms_1[i], 0);
6051 for (; i<*numofforms; i++) {
6052 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6053 smb_io_form_1("", buffer, &forms_1[i], 0);
6058 if (*needed > offered) {
6060 return WERR_INSUFFICIENT_BUFFER;
6067 SAFE_FREE(builtinlist);
6068 return WERR_UNKNOWN_LEVEL;
6073 /****************************************************************************
6074 ****************************************************************************/
6076 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6078 /* POLICY_HND *handle = &q_u->handle; - notused. */
6079 uint32 level = q_u->level;
6080 UNISTR2 *uni_formname = &q_u->formname;
6081 NEW_BUFFER *buffer = NULL;
6082 uint32 offered = q_u->offered;
6083 uint32 *needed = &r_u->needed;
6085 nt_forms_struct *list=NULL;
6086 nt_forms_struct builtin_form;
6091 int numofforms=0, i=0;
6093 /* that's an [in out] buffer */
6094 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6095 buffer = r_u->buffer;
6097 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6099 DEBUG(4,("_spoolss_getform\n"));
6100 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6101 DEBUGADD(5,("Info level [%d]\n", level));
6103 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6104 if (!foundBuiltin) {
6105 numofforms = get_ntforms(&list);
6106 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6108 if (numofforms == 0)
6115 fill_form_1(&form_1, &builtin_form);
6118 /* Check if the requested name is in the list of form structures */
6119 for (i=0; i<numofforms; i++) {
6121 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6123 if (strequal(form_name, list[i].name)) {
6124 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6125 fill_form_1(&form_1, &list[i]);
6131 if (i == numofforms) {
6135 /* check the required size. */
6137 *needed=spoolss_size_form_1(&form_1);
6139 if (!alloc_buffer_size(buffer, buffer_size)){
6140 return WERR_INSUFFICIENT_BUFFER;
6143 if (*needed > offered) {
6144 return WERR_INSUFFICIENT_BUFFER;
6147 /* fill the buffer with the form structures */
6148 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6149 smb_io_form_1("", buffer, &form_1, 0);
6155 return WERR_UNKNOWN_LEVEL;
6159 /****************************************************************************
6160 ****************************************************************************/
6162 static void fill_port_1(PORT_INFO_1 *port, char *name)
6164 init_unistr(&port->port_name, name);
6167 /****************************************************************************
6168 ****************************************************************************/
6170 static void fill_port_2(PORT_INFO_2 *port, char *name)
6172 init_unistr(&port->port_name, name);
6173 init_unistr(&port->monitor_name, "Local Monitor");
6174 init_unistr(&port->description, "Local Port");
6175 #define PORT_TYPE_WRITE 1
6176 port->port_type=PORT_TYPE_WRITE;
6180 /****************************************************************************
6182 ****************************************************************************/
6184 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6186 PORT_INFO_1 *ports=NULL;
6189 if (*lp_enumports_cmd()) {
6190 char *cmd = lp_enumports_cmd();
6197 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6199 DEBUG(10,("Running [%s]\n", command));
6200 ret = smbrun(command, &fd);
6201 DEBUG(10,("Returned [%d]\n", ret));
6205 /* Is this the best error to return here? */
6206 return WERR_ACCESS_DENIED;
6210 qlines = fd_lines_load(fd, &numlines);
6211 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6215 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6216 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6217 dos_errstr(WERR_NOMEM)));
6218 file_lines_free(qlines);
6222 for (i=0; i<numlines; i++) {
6223 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6224 fill_port_1(&ports[i], qlines[i]);
6227 file_lines_free(qlines);
6230 *returned = numlines;
6233 *returned = 1; /* Sole Samba port returned. */
6235 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6238 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6240 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6243 /* check the required size. */
6244 for (i=0; i<*returned; i++) {
6245 DEBUGADD(6,("adding port [%d]'s size\n", i));
6246 *needed += spoolss_size_port_info_1(&ports[i]);
6249 if (!alloc_buffer_size(buffer, *needed)) {
6251 return WERR_INSUFFICIENT_BUFFER;
6254 /* fill the buffer with the ports structures */
6255 for (i=0; i<*returned; i++) {
6256 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6257 smb_io_port_1("", buffer, &ports[i], 0);
6262 if (*needed > offered) {
6264 return WERR_INSUFFICIENT_BUFFER;
6270 /****************************************************************************
6272 ****************************************************************************/
6274 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6276 PORT_INFO_2 *ports=NULL;
6279 if (*lp_enumports_cmd()) {
6280 char *cmd = lp_enumports_cmd();
6289 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
6290 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
6292 path = lp_lockdir();
6294 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
6295 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
6298 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
6299 ret = smbrun(command, &fd);
6300 DEBUGADD(10,("returned [%d]\n", ret));
6304 /* Is this the best error to return here? */
6305 return WERR_ACCESS_DENIED;
6309 qlines = fd_lines_load(fd, &numlines);
6310 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6314 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
6315 file_lines_free(qlines);
6319 for (i=0; i<numlines; i++) {
6320 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6321 fill_port_2(&(ports[i]), qlines[i]);
6324 file_lines_free(qlines);
6327 *returned = numlines;
6333 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
6336 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6338 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
6341 /* check the required size. */
6342 for (i=0; i<*returned; i++) {
6343 DEBUGADD(6,("adding port [%d]'s size\n", i));
6344 *needed += spoolss_size_port_info_2(&ports[i]);
6347 if (!alloc_buffer_size(buffer, *needed)) {
6349 return WERR_INSUFFICIENT_BUFFER;
6352 /* fill the buffer with the ports structures */
6353 for (i=0; i<*returned; i++) {
6354 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6355 smb_io_port_2("", buffer, &ports[i], 0);
6360 if (*needed > offered) {
6362 return WERR_INSUFFICIENT_BUFFER;
6368 /****************************************************************************
6370 ****************************************************************************/
6372 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
6374 /* UNISTR2 *name = &q_u->name; - notused. */
6375 uint32 level = q_u->level;
6376 NEW_BUFFER *buffer = NULL;
6377 uint32 offered = q_u->offered;
6378 uint32 *needed = &r_u->needed;
6379 uint32 *returned = &r_u->returned;
6381 /* that's an [in out] buffer */
6382 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6383 buffer = r_u->buffer;
6385 DEBUG(4,("_spoolss_enumports\n"));
6392 return enumports_level_1(buffer, offered, needed, returned);
6394 return enumports_level_2(buffer, offered, needed, returned);
6396 return WERR_UNKNOWN_LEVEL;
6400 /****************************************************************************
6401 ****************************************************************************/
6403 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
6404 const SPOOL_PRINTER_INFO_LEVEL *info,
6405 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
6406 uint32 user_switch, const SPOOL_USER_CTR *user,
6409 NT_PRINTER_INFO_LEVEL *printer = NULL;
6412 WERROR err = WERR_OK;
6414 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
6415 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6419 ZERO_STRUCTP(printer);
6421 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6422 if (!convert_printer_info(info, printer, 2)) {
6423 free_a_printer(&printer, 2);
6427 /* check to see if the printer already exists */
6429 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
6430 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6431 printer->info_2->sharename));
6432 free_a_printer(&printer, 2);
6433 return WERR_PRINTER_ALREADY_EXISTS;
6436 if (*lp_addprinter_cmd() )
6437 if ( !add_printer_hook(printer) ) {
6438 free_a_printer(&printer,2);
6439 return WERR_ACCESS_DENIED;
6442 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
6443 printer->info_2->sharename);
6445 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
6446 free_a_printer(&printer,2);
6447 return WERR_ACCESS_DENIED;
6450 /* you must be a printer admin to add a new printer */
6451 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6452 free_a_printer(&printer,2);
6453 return WERR_ACCESS_DENIED;
6457 * Do sanity check on the requested changes for Samba.
6460 if (!check_printer_ok(printer->info_2, snum)) {
6461 free_a_printer(&printer,2);
6462 return WERR_INVALID_PARAM;
6466 * When a printer is created, the drivername bound to the printer is used
6467 * to lookup previously saved driver initialization info, which is then
6468 * bound to the new printer, simulating what happens in the Windows arch.
6472 set_driver_init(printer, 2);
6474 /* A valid devmode was included, convert and link it
6476 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6478 if (!convert_devicemode(printer->info_2->printername, devmode,
6479 &printer->info_2->devmode))
6483 set_driver_init(printer, 2);
6485 /* write the ASCII on disk */
6486 err = mod_a_printer(*printer, 2);
6487 if (!W_ERROR_IS_OK(err)) {
6488 free_a_printer(&printer,2);
6492 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
6493 /* Handle open failed - remove addition. */
6494 del_a_printer(printer->info_2->sharename);
6495 free_a_printer(&printer,2);
6496 return WERR_ACCESS_DENIED;
6499 update_c_setprinter(False);
6501 srv_spoolss_sendnotify(printer->info_2->printername, 0, PRINTER_CHANGE_ADD_PRINTER, 0x0);
6503 free_a_printer(&printer,2);
6508 /****************************************************************************
6509 ****************************************************************************/
6511 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6513 UNISTR2 *uni_srv_name = &q_u->server_name;
6514 uint32 level = q_u->level;
6515 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6516 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6517 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6518 uint32 user_switch = q_u->user_switch;
6519 SPOOL_USER_CTR *user = &q_u->user_ctr;
6520 POLICY_HND *handle = &r_u->handle;
6524 /* we don't handle yet */
6525 /* but I know what to do ... */
6526 return WERR_UNKNOWN_LEVEL;
6528 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6530 user_switch, user, handle);
6532 return WERR_UNKNOWN_LEVEL;
6536 /****************************************************************************
6537 ****************************************************************************/
6539 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6541 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
6542 uint32 level = q_u->level;
6543 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6544 WERROR err = WERR_OK;
6545 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6546 struct current_user user;
6547 fstring driver_name;
6549 ZERO_STRUCT(driver);
6551 get_current_user(&user, p);
6553 if (!convert_printer_driver_info(info, &driver, level)) {
6558 DEBUG(5,("Cleaning driver's information\n"));
6559 err = clean_up_driver_struct(driver, level, &user);
6560 if (!W_ERROR_IS_OK(err))
6563 DEBUG(5,("Moving driver to final destination\n"));
6564 if(!move_driver_to_download_area(driver, level, &user, &err)) {
6565 if (W_ERROR_IS_OK(err))
6566 err = WERR_ACCESS_DENIED;
6570 if (add_a_printer_driver(driver, level)!=0) {
6571 err = WERR_ACCESS_DENIED;
6575 /* BEGIN_ADMIN_LOG */
6578 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6579 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
6580 fstrcpy(driver_name, driver.info_3->name);
6583 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6584 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
6585 fstrcpy(driver_name, driver.info_6->name);
6591 * I think this is where he DrvUpgradePrinter() hook would be
6592 * be called in a driver's interface DLL on a Windows NT 4.0/2k
6593 * server. Right now, we just need to send ourselves a message
6594 * to update each printer bound to this driver. --jerry
6597 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
6598 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
6602 /* if driver is not 9x, delete existing driver init data */
6604 if ((level == 3 && driver.info_3->cversion != 0) ||
6605 (level == 6 && driver.info_6->version != 0)) {
6606 if (!del_driver_init(driver_name))
6607 DEBUG(3,("_spoolss_addprinterdriver: del_driver_init(%s) failed!\n", driver_name));
6609 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n", driver_name));
6613 free_a_printer_driver(driver, level);
6617 /****************************************************************************
6618 ****************************************************************************/
6620 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6622 init_unistr(&info->name, name);
6625 /****************************************************************************
6626 ****************************************************************************/
6628 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6632 pstring short_archi;
6633 DRIVER_DIRECTORY_1 *info=NULL;
6635 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6637 if (get_short_archi(short_archi, long_archi)==False)
6638 return WERR_INVALID_ENVIRONMENT;
6640 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6643 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6645 DEBUG(4,("printer driver directory: [%s]\n", path));
6647 fill_driverdir_1(info, path);
6649 *needed += spoolss_size_driverdir_info_1(info);
6651 if (!alloc_buffer_size(buffer, *needed)) {
6653 return WERR_INSUFFICIENT_BUFFER;
6656 smb_io_driverdir_1("", buffer, info, 0);
6660 if (*needed > offered)
6661 return WERR_INSUFFICIENT_BUFFER;
6666 /****************************************************************************
6667 ****************************************************************************/
6669 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6671 UNISTR2 *name = &q_u->name;
6672 UNISTR2 *uni_environment = &q_u->environment;
6673 uint32 level = q_u->level;
6674 NEW_BUFFER *buffer = NULL;
6675 uint32 offered = q_u->offered;
6676 uint32 *needed = &r_u->needed;
6678 /* that's an [in out] buffer */
6679 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6680 buffer = r_u->buffer;
6682 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6688 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6690 return WERR_UNKNOWN_LEVEL;
6694 /****************************************************************************
6695 ****************************************************************************/
6697 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6699 POLICY_HND *handle = &q_u->handle;
6700 uint32 idx = q_u->index;
6701 uint32 in_value_len = q_u->valuesize;
6702 uint32 in_data_len = q_u->datasize;
6703 uint32 *out_max_value_len = &r_u->valuesize;
6704 uint16 **out_value = &r_u->value;
6705 uint32 *out_value_len = &r_u->realvaluesize;
6706 uint32 *out_type = &r_u->type;
6707 uint32 *out_max_data_len = &r_u->datasize;
6708 uint8 **data_out = &r_u->data;
6709 uint32 *out_data_len = &r_u->realdatasize;
6711 NT_PRINTER_INFO_LEVEL *printer = NULL;
6716 uint32 biggest_valuesize;
6717 uint32 biggest_datasize;
6719 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6725 ZERO_STRUCT(printer);
6729 *out_max_data_len=0;
6733 DEBUG(5,("spoolss_enumprinterdata\n"));
6736 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6740 if (!get_printer_snum(p,handle, &snum))
6743 result = get_a_printer(&printer, 2, lp_servicename(snum));
6744 if (!W_ERROR_IS_OK(result))
6748 * The NT machine wants to know the biggest size of value and data
6750 * cf: MSDN EnumPrinterData remark section
6752 if ( (in_value_len==0) && (in_data_len==0) ) {
6753 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6757 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6758 * if this parameter size doesn't exist.
6759 * Ok - my opinion here is that the client is not asking for the greatest
6760 * possible size of all the parameters, but is asking specifically for the size needed
6761 * for this specific parameter. In that case we can remove the loop below and
6762 * simplify this lookup code considerably. JF - comments welcome. JRA.
6765 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6767 free_a_printer(&printer, 2);
6768 return WERR_NO_MORE_ITEMS;
6775 biggest_valuesize=0;
6778 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6779 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6780 if (data_len > biggest_datasize) biggest_datasize=data_len;
6782 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6788 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6789 *out_value_len=2*(1+biggest_valuesize);
6790 *out_data_len=biggest_datasize;
6792 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6794 free_a_printer(&printer, 2);
6799 * the value len is wrong in NT sp3
6800 * that's the number of bytes not the number of unicode chars
6803 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6806 free_a_printer(&printer, 2);
6808 /* out_value should default to "" or else NT4 has
6809 problems unmarshalling the response */
6811 *out_max_value_len=(in_value_len/sizeof(uint16));
6812 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
6815 *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
6817 /* the data is counted in bytes */
6818 *out_max_data_len = in_data_len;
6819 *out_data_len = in_data_len;
6820 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
6823 return WERR_NO_MORE_ITEMS;
6826 free_a_printer(&printer, 2);
6830 * - counted in bytes in the request
6831 * - counted in UNICODE chars in the max reply
6832 * - counted in bytes in the real size
6834 * take a pause *before* coding not *during* coding
6837 *out_max_value_len=(in_value_len/sizeof(uint16));
6838 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6843 *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6847 /* the data is counted in bytes */
6848 *out_max_data_len=in_data_len;
6849 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6854 memcpy(*data_out, data, (size_t)data_len);
6855 *out_data_len=data_len;
6862 /****************************************************************************
6863 ****************************************************************************/
6865 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6867 POLICY_HND *handle = &q_u->handle;
6868 UNISTR2 *value = &q_u->value;
6869 uint32 type = q_u->type;
6870 /* uint32 max_len = q_u->max_len; - notused. */
6871 uint8 *data = q_u->data;
6872 uint32 real_len = q_u->real_len;
6873 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6875 NT_PRINTER_INFO_LEVEL *printer = NULL;
6876 NT_PRINTER_PARAM *param = NULL, old_param;
6878 WERROR status = WERR_OK;
6879 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6881 DEBUG(5,("spoolss_setprinterdata\n"));
6884 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6888 if (!get_printer_snum(p,handle, &snum))
6891 ZERO_STRUCT(old_param);
6894 * Access check : NT returns "access denied" if you make a
6895 * SetPrinterData call without the necessary privildge.
6896 * we were originally returning OK if nothing changed
6897 * which made Win2k issue **a lot** of SetPrinterData
6898 * when connecting to a printer --jerry
6901 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6902 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
6903 status = WERR_ACCESS_DENIED;
6907 /* Check if we are making any changes or not. Return true if
6908 nothing is actually changing. This is not needed anymore but
6909 has been left in as an optimization to keep from from
6910 writing to disk as often --jerry */
6912 status = get_a_printer(&printer, 2, lp_servicename(snum));
6913 if (!W_ERROR_IS_OK(status))
6916 convert_specific_param(¶m, value , type, data, real_len);
6918 unlink_specific_param_if_exist(printer->info_2, param);
6921 * When client side code sets a magic printer data key, detect it and save
6922 * the current printer data and the magic key's data (its the DEVMODE) for
6923 * future printer/driver initializations.
6925 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6927 * Set devmode and printer initialization info
6929 status = save_driver_init(printer, 2, param);
6932 add_a_specific_param(printer->info_2, ¶m);
6933 status = mod_a_printer(*printer, 2);
6937 free_a_printer(&printer, 2);
6939 free_nt_printer_param(¶m);
6940 SAFE_FREE(old_param.data);
6945 /****************************************************************************
6946 ****************************************************************************/
6948 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
6950 POLICY_HND *handle = &q_u->handle;
6951 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6954 DEBUG(5,("_spoolss_resetprinter\n"));
6957 * All we do is to check to see if the handle and queue is valid.
6958 * This call really doesn't mean anything to us because we only
6959 * support RAW printing. --jerry
6963 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6967 if (!get_printer_snum(p,handle, &snum))
6971 /* blindly return success */
6976 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6978 POLICY_HND *handle = &q_u->handle;
6979 UNISTR2 *value = &q_u->valuename;
6981 NT_PRINTER_INFO_LEVEL *printer = NULL;
6982 NT_PRINTER_PARAM param;
6984 WERROR status = WERR_OK;
6985 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6987 DEBUG(5,("spoolss_deleteprinterdata\n"));
6990 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6994 if (!get_printer_snum(p, handle, &snum))
6997 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6998 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
6999 return WERR_ACCESS_DENIED;
7002 status = get_a_printer(&printer, 2, lp_servicename(snum));
7003 if (!W_ERROR_IS_OK(status))
7006 ZERO_STRUCTP(¶m);
7007 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
7009 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
7010 status = WERR_INVALID_PARAM;
7012 status = mod_a_printer(*printer, 2);
7014 free_a_printer(&printer, 2);
7018 /****************************************************************************
7019 ****************************************************************************/
7021 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7023 POLICY_HND *handle = &q_u->handle;
7024 /* uint32 level = q_u->level; - notused. */
7025 FORM *form = &q_u->form;
7026 nt_forms_struct tmpForm;
7028 WERROR status = WERR_OK;
7029 NT_PRINTER_INFO_LEVEL *printer = NULL;
7032 nt_forms_struct *list=NULL;
7033 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7035 DEBUG(5,("spoolss_addform\n"));
7038 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7042 if (!get_printer_snum(p,handle, &snum))
7045 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7046 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7047 status = WERR_ACCESS_DENIED;
7051 /* can't add if builtin */
7052 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7053 return WERR_ALREADY_EXISTS;
7056 count=get_ntforms(&list);
7057 if(!add_a_form(&list, form, &count))
7059 write_ntforms(&list, count);
7062 * ChangeID must always be set
7065 status = get_a_printer(&printer, 2, lp_servicename(snum));
7066 if (!W_ERROR_IS_OK(status))
7069 status = mod_a_printer(*printer, 2);
7070 if (!W_ERROR_IS_OK(status))
7074 free_a_printer(&printer, 2);
7080 /****************************************************************************
7081 ****************************************************************************/
7083 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7085 POLICY_HND *handle = &q_u->handle;
7086 UNISTR2 *form_name = &q_u->name;
7087 nt_forms_struct tmpForm;
7089 WERROR ret = WERR_OK;
7090 nt_forms_struct *list=NULL;
7091 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7093 WERROR status = WERR_OK;
7094 NT_PRINTER_INFO_LEVEL *printer = NULL;
7096 DEBUG(5,("spoolss_deleteform\n"));
7099 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7103 if (!get_printer_snum(p, handle, &snum))
7106 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7107 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
7108 return WERR_ACCESS_DENIED;
7111 /* can't delete if builtin */
7112 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7113 return WERR_INVALID_PARAM;
7116 count = get_ntforms(&list);
7117 if(!delete_a_form(&list, form_name, &count, &ret))
7118 return WERR_INVALID_PARAM;
7121 * ChangeID must always be set
7124 status = get_a_printer(&printer, 2, lp_servicename(snum));
7125 if (!W_ERROR_IS_OK(status))
7128 status = mod_a_printer(*printer, 2);
7129 if (!W_ERROR_IS_OK(status))
7133 free_a_printer(&printer, 2);
7139 /****************************************************************************
7140 ****************************************************************************/
7142 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7144 POLICY_HND *handle = &q_u->handle;
7145 /* UNISTR2 *uni_name = &q_u->name; - notused. */
7146 /* uint32 level = q_u->level; - notused. */
7147 FORM *form = &q_u->form;
7148 nt_forms_struct tmpForm;
7150 WERROR status = WERR_OK;
7151 NT_PRINTER_INFO_LEVEL *printer = NULL;
7154 nt_forms_struct *list=NULL;
7155 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7157 DEBUG(5,("spoolss_setform\n"));
7160 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7164 if (!get_printer_snum(p, handle, &snum))
7167 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7168 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7169 return WERR_ACCESS_DENIED;
7172 /* can't set if builtin */
7173 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7174 return WERR_INVALID_PARAM;
7177 count=get_ntforms(&list);
7178 update_a_form(&list, form, count);
7179 write_ntforms(&list, count);
7182 * ChangeID must always be set
7185 status = get_a_printer(&printer, 2, lp_servicename(snum));
7186 if (!W_ERROR_IS_OK(status))
7189 status = mod_a_printer(*printer, 2);
7190 if (!W_ERROR_IS_OK(status))
7194 free_a_printer(&printer, 2);
7200 /****************************************************************************
7201 enumprintprocessors level 1.
7202 ****************************************************************************/
7204 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7206 PRINTPROCESSOR_1 *info_1=NULL;
7208 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
7213 init_unistr(&info_1->name, "winprint");
7215 *needed += spoolss_size_printprocessor_info_1(info_1);
7217 if (!alloc_buffer_size(buffer, *needed))
7218 return WERR_INSUFFICIENT_BUFFER;
7220 smb_io_printprocessor_info_1("", buffer, info_1, 0);
7224 if (*needed > offered) {
7226 return WERR_INSUFFICIENT_BUFFER;
7232 /****************************************************************************
7233 ****************************************************************************/
7235 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
7237 /* UNISTR2 *name = &q_u->name; - notused. */
7238 /* UNISTR2 *environment = &q_u->environment; - notused. */
7239 uint32 level = q_u->level;
7240 NEW_BUFFER *buffer = NULL;
7241 uint32 offered = q_u->offered;
7242 uint32 *needed = &r_u->needed;
7243 uint32 *returned = &r_u->returned;
7245 /* that's an [in out] buffer */
7246 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7247 buffer = r_u->buffer;
7249 DEBUG(5,("spoolss_enumprintprocessors\n"));
7252 * Enumerate the print processors ...
7254 * Just reply with "winprint", to keep NT happy
7255 * and I can use my nice printer checker.
7263 return enumprintprocessors_level_1(buffer, offered, needed, returned);
7265 return WERR_UNKNOWN_LEVEL;
7269 /****************************************************************************
7270 enumprintprocdatatypes level 1.
7271 ****************************************************************************/
7273 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7275 PRINTPROCDATATYPE_1 *info_1=NULL;
7277 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
7282 init_unistr(&info_1->name, "RAW");
7284 *needed += spoolss_size_printprocdatatype_info_1(info_1);
7286 if (!alloc_buffer_size(buffer, *needed))
7287 return WERR_INSUFFICIENT_BUFFER;
7289 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
7293 if (*needed > offered) {
7295 return WERR_INSUFFICIENT_BUFFER;
7301 /****************************************************************************
7302 ****************************************************************************/
7304 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
7306 /* UNISTR2 *name = &q_u->name; - notused. */
7307 /* UNISTR2 *processor = &q_u->processor; - notused. */
7308 uint32 level = q_u->level;
7309 NEW_BUFFER *buffer = NULL;
7310 uint32 offered = q_u->offered;
7311 uint32 *needed = &r_u->needed;
7312 uint32 *returned = &r_u->returned;
7314 /* that's an [in out] buffer */
7315 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7316 buffer = r_u->buffer;
7318 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7325 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
7327 return WERR_UNKNOWN_LEVEL;
7331 /****************************************************************************
7332 enumprintmonitors level 1.
7333 ****************************************************************************/
7335 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7337 PRINTMONITOR_1 *info_1=NULL;
7339 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
7344 init_unistr(&info_1->name, "Local Port");
7346 *needed += spoolss_size_printmonitor_info_1(info_1);
7348 if (!alloc_buffer_size(buffer, *needed))
7349 return WERR_INSUFFICIENT_BUFFER;
7351 smb_io_printmonitor_info_1("", buffer, info_1, 0);
7355 if (*needed > offered) {
7357 return WERR_INSUFFICIENT_BUFFER;
7363 /****************************************************************************
7364 enumprintmonitors level 2.
7365 ****************************************************************************/
7367 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7369 PRINTMONITOR_2 *info_2=NULL;
7371 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
7376 init_unistr(&info_2->name, "Local Port");
7377 init_unistr(&info_2->environment, "Windows NT X86");
7378 init_unistr(&info_2->dll_name, "localmon.dll");
7380 *needed += spoolss_size_printmonitor_info_2(info_2);
7382 if (!alloc_buffer_size(buffer, *needed))
7383 return WERR_INSUFFICIENT_BUFFER;
7385 smb_io_printmonitor_info_2("", buffer, info_2, 0);
7389 if (*needed > offered) {
7391 return WERR_INSUFFICIENT_BUFFER;
7397 /****************************************************************************
7398 ****************************************************************************/
7400 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
7402 /* UNISTR2 *name = &q_u->name; - notused. */
7403 uint32 level = q_u->level;
7404 NEW_BUFFER *buffer = NULL;
7405 uint32 offered = q_u->offered;
7406 uint32 *needed = &r_u->needed;
7407 uint32 *returned = &r_u->returned;
7409 /* that's an [in out] buffer */
7410 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7411 buffer = r_u->buffer;
7413 DEBUG(5,("spoolss_enumprintmonitors\n"));
7416 * Enumerate the print monitors ...
7418 * Just reply with "Local Port", to keep NT happy
7419 * and I can use my nice printer checker.
7427 return enumprintmonitors_level_1(buffer, offered, needed, returned);
7429 return enumprintmonitors_level_2(buffer, offered, needed, returned);
7431 return WERR_UNKNOWN_LEVEL;
7435 /****************************************************************************
7436 ****************************************************************************/
7438 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7442 JOB_INFO_1 *info_1=NULL;
7444 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
7446 if (info_1 == NULL) {
7451 for (i=0; i<count && found==False; i++) {
7452 if (queue[i].job==(int)jobid)
7459 /* NT treats not found as bad param... yet another bad choice */
7460 return WERR_INVALID_PARAM;
7463 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
7467 *needed += spoolss_size_job_info_1(info_1);
7469 if (!alloc_buffer_size(buffer, *needed)) {
7471 return WERR_INSUFFICIENT_BUFFER;
7474 smb_io_job_info_1("", buffer, info_1, 0);
7478 if (*needed > offered)
7479 return WERR_INSUFFICIENT_BUFFER;
7484 /****************************************************************************
7485 ****************************************************************************/
7487 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7492 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
7494 DEVICEMODE *devmode = NULL;
7496 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
7498 ZERO_STRUCTP(info_2);
7500 if (info_2 == NULL) {
7505 for (i=0; i<count && found==False; i++) {
7506 if (queue[i].job==(int)jobid)
7511 /* NT treats not found as bad param... yet another bad
7513 ret = WERR_INVALID_PARAM;
7517 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
7518 if (!W_ERROR_IS_OK(ret))
7520 if (construct_dev_mode(snum) == NULL) {
7525 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
7527 *needed += spoolss_size_job_info_2(info_2);
7529 if (!alloc_buffer_size(buffer, *needed)) {
7530 ret = WERR_INSUFFICIENT_BUFFER;
7534 smb_io_job_info_2("", buffer, info_2, 0);
7536 if (*needed > offered) {
7537 ret = WERR_INSUFFICIENT_BUFFER;
7544 /* Cleanup allocated memory */
7547 free_job_info_2(info_2); /* Also frees devmode */
7549 free_a_printer(&ntprinter, 2);
7554 /****************************************************************************
7555 ****************************************************************************/
7557 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
7559 POLICY_HND *handle = &q_u->handle;
7560 uint32 jobid = q_u->jobid;
7561 uint32 level = q_u->level;
7562 NEW_BUFFER *buffer = NULL;
7563 uint32 offered = q_u->offered;
7564 uint32 *needed = &r_u->needed;
7568 print_queue_struct *queue=NULL;
7569 print_status_struct prt_status;
7571 /* that's an [in out] buffer */
7572 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7573 buffer = r_u->buffer;
7575 DEBUG(5,("spoolss_getjob\n"));
7579 if (!get_printer_snum(p, handle, &snum))
7582 count = print_queue_status(snum, &queue, &prt_status);
7584 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7585 count, prt_status.status, prt_status.message));
7589 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
7591 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
7594 return WERR_UNKNOWN_LEVEL;
7598 /********************************************************************
7599 * spoolss_getprinterdataex
7600 ********************************************************************/
7602 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
7604 POLICY_HND *handle = &q_u->handle;
7605 uint32 in_size = q_u->size;
7606 uint32 *type = &r_u->type;
7607 uint32 *out_size = &r_u->size;
7608 uint8 **data = &r_u->data;
7609 uint32 *needed = &r_u->needed;
7612 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7615 DEBUG(4,("_spoolss_getprinterdataex\n"));
7617 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7618 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
7620 /* in case of problem, return some default values */
7627 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
7629 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7634 /* Is the handle to a printer or to the server? */
7636 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
7638 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7639 return WERR_INVALID_PARAM;
7644 * From MSDN documentation of GetPrinterDataEx: pass request
7645 * to GetPrinterData if key is "PrinterDriverData". This is
7646 * the only key we really support. Other keys to implement:
7652 if (strcmp(key, "PrinterDriverData") != 0)
7653 return WERR_BADFILE;
7655 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7656 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
7657 type, data, needed, in_size);
7662 DEBUG(5, ("value not found, allocating %d\n", *out_size));
7664 /* reply this param doesn't exist */
7666 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
7672 return WERR_INVALID_PARAM;
7675 if (*needed > *out_size)
7676 return WERR_MORE_DATA;
7681 /********************************************************************
7682 * spoolss_setprinterdata
7683 ********************************************************************/
7685 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
7687 SPOOL_Q_SETPRINTERDATA q_u_local;
7688 SPOOL_R_SETPRINTERDATA r_u_local;
7691 DEBUG(4,("_spoolss_setprinterdataex\n"));
7693 /* From MSDN documentation of SetPrinterDataEx: pass request to
7694 SetPrinterData if key is "PrinterDriverData" */
7696 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7698 if (strcmp(key, "PrinterDriverData") != 0)
7699 return WERR_INVALID_PARAM;
7701 ZERO_STRUCT(q_u_local);
7702 ZERO_STRUCT(r_u_local);
7704 /* make a copy to call _spoolss_setprinterdata() */
7706 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7707 copy_unistr2(&q_u_local.value, &q_u->value);
7708 q_u_local.type = q_u->type;
7709 q_u_local.max_len = q_u->max_len;
7710 q_u_local.data = q_u->data;
7711 q_u_local.real_len = q_u->real_len;
7712 q_u_local.numeric_data = q_u->numeric_data;
7714 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
7717 /********************************************************************
7718 * spoolss_enumprinterkey
7719 ********************************************************************/
7721 /* constants for EnumPrinterKey() */
7722 #define ENUMERATED_KEY_SIZE 19
7724 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
7727 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
7730 char *PrinterKey = "PrinterDriverData";
7732 DEBUG(4,("_spoolss_enumprinterkey\n"));
7734 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7737 * we only support enumating all keys (key == "")
7738 * Of course, the only key we support is the "PrinterDriverData"
7741 if (strlen(key) == 0)
7743 r_u->needed = ENUMERATED_KEY_SIZE *2;
7744 if (q_u->size < r_u->needed)
7745 return WERR_MORE_DATA;
7748 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
7750 enumkeys[i] = (uint16)(*ptr);
7754 /* tag of with 2 '\0's */
7755 enumkeys[i++] = '\0';
7758 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
7759 return WERR_BADFILE;
7764 /* The "PrinterDriverData" key should have no subkeys */
7765 if (strcmp(key, PrinterKey) == 0)
7768 if (q_u->size < r_u->needed)
7769 return WERR_MORE_DATA;
7771 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
7772 return WERR_BADFILE;
7778 /* The return value for an unknown key is documented in MSDN
7779 EnumPrinterKey description */
7780 return WERR_BADFILE;
7783 /********************************************************************
7784 * spoolss_enumprinterdataex
7785 ********************************************************************/
7787 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
7789 POLICY_HND *handle = &q_u->handle;
7790 uint32 in_size = q_u->size;
7793 NT_PRINTER_INFO_LEVEL *printer = NULL;
7794 PRINTER_ENUM_VALUES *enum_values = NULL;
7796 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7805 DEBUG(4,("_spoolss_enumprinterdataex\n"));
7808 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
7814 * The only key we support is "PrinterDriverData". This should return
7815 > an array of all the key/value pairs returned by EnumPrinterDataSee
7816 * _spoolss_getprinterdataex() for details --jerry
7819 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7820 if (strcmp(key, "PrinterDriverData") != 0)
7822 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
7823 return WERR_INVALID_PARAM;
7827 if (!get_printer_snum(p,handle, &snum))
7830 ZERO_STRUCT(printer);
7831 result = get_a_printer(&printer, 2, lp_servicename(snum));
7832 if (!W_ERROR_IS_OK(result))
7837 * loop through all params and build the array to pass
7838 * back to the client
7845 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
7847 PRINTER_ENUM_VALUES *ptr;
7850 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7852 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7854 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7855 result = WERR_NOMEM;
7861 init_unistr(&enum_values[num_entries].valuename, value);
7862 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7863 enum_values[num_entries].type = type;
7865 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7866 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7867 result = WERR_NOMEM;
7870 memcpy(enum_values[num_entries].data, data, data_len);
7871 enum_values[num_entries].data_len = data_len + add_len;
7873 /* keep track of the size of the array in bytes */
7875 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7881 r_u->needed = needed;
7882 r_u->returned = num_entries;
7884 if (needed > in_size) {
7885 result = WERR_MORE_DATA;
7889 /* copy data into the reply */
7891 r_u->ctr.size = r_u->needed;
7892 r_u->ctr.size_of_array = r_u->returned;
7893 r_u->ctr.values = enum_values;
7898 free_a_printer(&printer, 2);
7903 /****************************************************************************
7904 ****************************************************************************/
7906 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
7908 init_unistr(&info->name, name);
7911 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
7912 UNISTR2 *environment,
7919 pstring short_archi;
7920 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
7922 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
7924 if (get_short_archi(short_archi, long_archi)==FALSE)
7925 return WERR_INVALID_ENVIRONMENT;
7927 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
7930 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
7932 fill_printprocessordirectory_1(info, path);
7934 *needed += spoolss_size_printprocessordirectory_info_1(info);
7936 if (!alloc_buffer_size(buffer, *needed)) {
7938 return WERR_INSUFFICIENT_BUFFER;
7941 smb_io_printprocessordirectory_1("", buffer, info, 0);
7945 if (*needed > offered)
7946 return WERR_INSUFFICIENT_BUFFER;
7951 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
7953 uint32 level = q_u->level;
7954 NEW_BUFFER *buffer = NULL;
7955 uint32 offered = q_u->offered;
7956 uint32 *needed = &r_u->needed;
7958 /* that's an [in out] buffer */
7959 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7960 buffer = r_u->buffer;
7962 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7968 return getprintprocessordirectory_level_1
7969 (&q_u->name, &q_u->environment, buffer, offered, needed);
7971 return WERR_UNKNOWN_LEVEL;
7974 return WERR_ACCESS_DENIED;