2 * Unix SMB/Netbios implementation.
4 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-2000,
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7 * Copyright (C) Jean François Micouleau 1998-2000.
8 * Copyright (C) Jeremy Allison 2001.
9 * Copyright (C) Gerald Carter 2000-2001.
10 * Copyright (C) Tim Potter 2001.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
32 extern pstring global_myname;
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
38 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
39 #define PRINTER_HANDLE_IS_PRINTER 0
40 #define PRINTER_HANDLE_IS_PRINTSERVER 1
49 /* structure to store the printer handles */
50 /* and a reference to what it's pointing to */
51 /* and the notify info asked about */
52 /* that's the central struct */
53 typedef struct _Printer{
54 BOOL document_started;
56 int jobid; /* jobid in printing backend */
60 fstring printerservername;
69 SPOOL_NOTIFY_OPTION *option;
70 POLICY_HND client_hnd;
71 uint32 client_connected;
79 typedef struct _counter_printer_0 {
87 static ubi_dlList counter_list;
89 static struct cli_state cli;
90 static uint32 smb_connections=0;
92 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
94 /* translate between internal status numbers and NT status numbers */
95 static int nt_printj_status(int v)
101 return JOB_STATUS_PAUSED;
103 return JOB_STATUS_SPOOLING;
105 return JOB_STATUS_PRINTING;
107 return JOB_STATUS_ERROR;
109 return JOB_STATUS_DELETING;
111 return JOB_STATUS_OFFLINE;
113 return JOB_STATUS_PAPEROUT;
115 return JOB_STATUS_PRINTED;
117 return JOB_STATUS_DELETED;
119 return JOB_STATUS_BLOCKED;
120 case LPQ_USER_INTERVENTION:
121 return JOB_STATUS_USER_INTERVENTION;
126 static int nt_printq_status(int v)
130 return PRINTER_STATUS_PAUSED;
139 /****************************************************************************
140 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
141 ****************************************************************************/
143 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
148 SAFE_FREE((*pp)->ctr.type);
152 /***************************************************************************
153 Disconnect from the client
154 ****************************************************************************/
156 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
160 /* weird if the test succeds !!! */
161 if (smb_connections==0) {
162 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
167 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
169 /* if it's the last connection, deconnect the IPC$ share */
170 if (smb_connections==1) {
171 if(!spoolss_disconnect_from_client(&cli))
174 message_deregister(MSG_PRINTER_NOTIFY);
180 /****************************************************************************
181 Functions to free a printer entry datastruct.
182 ****************************************************************************/
184 static void free_printer_entry(void *ptr)
186 Printer_entry *Printer = (Printer_entry *)ptr;
188 if (Printer->notify.client_connected==True)
189 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
191 Printer->notify.flags=0;
192 Printer->notify.options=0;
193 Printer->notify.localmachine[0]='\0';
194 Printer->notify.printerlocal=0;
195 free_spool_notify_option(&Printer->notify.option);
196 Printer->notify.option=NULL;
197 Printer->notify.client_connected=False;
202 /****************************************************************************
203 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
204 ****************************************************************************/
206 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
208 SPOOL_NOTIFY_OPTION *new_sp = NULL;
213 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
220 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
222 if (!new_sp->ctr.type) {
231 /****************************************************************************
232 find printer index by handle
233 ****************************************************************************/
235 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
237 Printer_entry *find_printer = NULL;
239 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
240 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
247 /****************************************************************************
248 close printer index by handle
249 ****************************************************************************/
251 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
253 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
256 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
260 close_policy_hnd(p, hnd);
265 /****************************************************************************
266 delete a printer given a handle
267 ****************************************************************************/
268 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
270 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
273 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
277 if (del_a_printer(Printer->dev.handlename) != 0) {
278 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
282 /* Check calling user has permission to delete printer. Note that
283 since we set the snum parameter to -1 only administrators can
284 delete the printer. This stops people with the Full Control
285 permission from deleting the printer. */
287 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
288 DEBUG(3, ("printer delete denied by security descriptor\n"));
289 return WERR_ACCESS_DENIED;
292 if (*lp_deleteprinter_cmd()) {
294 char *cmd = lp_deleteprinter_cmd();
299 /* Printer->dev.handlename equals portname equals sharename */
300 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
301 Printer->dev.handlename);
303 DEBUG(10,("Running [%s]\n", command));
304 ret = smbrun(command, NULL);
306 return WERR_BADFID; /* What to return here? */
308 DEBUGADD(10,("returned [%d]\n", ret));
310 /* Send SIGHUP to process group... is there a better way? */
313 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
317 return WERR_ACCESS_DENIED;
323 /****************************************************************************
324 return the snum of a printer corresponding to an handle
325 ****************************************************************************/
326 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
328 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
331 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
335 switch (Printer->printer_type) {
336 case PRINTER_HANDLE_IS_PRINTER:
337 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
338 *number = print_queue_snum(Printer->dev.handlename);
339 return (*number != -1);
340 case PRINTER_HANDLE_IS_PRINTSERVER:
347 /****************************************************************************
348 set printer handle type.
349 ****************************************************************************/
350 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
355 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
359 DEBUG(4,("Setting printer access=%x\n", access_required));
360 Printer->access = access_required;
364 /****************************************************************************
365 Set printer handle type.
366 Check if it's \\server or \\server\printer
367 ****************************************************************************/
369 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
371 DEBUG(3,("Setting printer type=%s\n", handlename));
373 if ( strlen(handlename) < 3 ) {
374 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
378 /* it's a print server */
379 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
380 DEBUGADD(4,("Printer is a print server\n"));
381 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
385 DEBUGADD(4,("Printer is a printer\n"));
386 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
392 /****************************************************************************
393 Set printer handle name.
394 ****************************************************************************/
396 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
398 NT_PRINTER_INFO_LEVEL *printer = NULL;
400 int n_services=lp_numservices();
404 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
406 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
407 ZERO_STRUCT(Printer->dev.printerservername);
408 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
412 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
415 if (*handlename=='\\') {
416 aprinter=strchr_m(handlename+2, '\\');
423 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
426 * store the Samba share name in it
427 * in back we have the long printer name
428 * need to iterate all the snum and do a
429 * get_a_printer each time to find the printer
430 * faster to do it here than later.
433 for (snum=0;snum<n_services && found==False;snum++) {
436 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
439 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
441 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
444 printername=strchr_m(printer->info_2->printername+2, '\\');
447 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
448 printer->info_2->printername, aprinter ));
450 if ( strlen(printername) != strlen(aprinter) ) {
451 free_a_printer(&printer, 2);
455 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
456 free_a_printer(&printer, 2);
464 * if we haven't found a printer with the given handlename
465 * then it can be a share name as you can open both \\server\printer and
470 * we still check if the printer description file exists as NT won't be happy
471 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
475 DEBUGADD(5,("Printer not found, checking for share now\n"));
477 for (snum=0;snum<n_services && found==False;snum++) {
479 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
482 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
484 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
487 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
488 printer->info_2->printername, aprinter ));
490 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
491 free_a_printer(&printer, 2);
495 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
496 free_a_printer(&printer, 2);
505 DEBUGADD(4,("Printer not found\n"));
510 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
511 printer->info_2->printername, lp_servicename(snum),snum));
513 ZERO_STRUCT(Printer->dev.handlename);
514 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
516 free_a_printer(&printer, 2);
521 /****************************************************************************
522 find first available printer slot. creates a printer handle for you.
523 ****************************************************************************/
525 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
527 Printer_entry *new_printer;
529 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
531 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
534 ZERO_STRUCTP(new_printer);
536 new_printer->notify.option=NULL;
538 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
539 SAFE_FREE(new_printer);
543 if (!set_printer_hnd_printertype(new_printer, name)) {
544 close_printer_handle(p, hnd);
548 if (!set_printer_hnd_name(new_printer, name)) {
549 close_printer_handle(p, hnd);
553 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
558 /********************************************************************
559 Return True is the handle is a print server.
560 ********************************************************************/
562 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
564 Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
569 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
575 /****************************************************************************
576 allocate more memory for a BUFFER.
577 ****************************************************************************/
578 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
586 /* damn, I'm doing the reverse operation of prs_grow() :) */
587 if (buffer_size < prs_data_size(ps))
590 extra_space = buffer_size - prs_data_size(ps);
593 * save the offset and move to the end of the buffer
594 * prs_grow() checks the extra_space against the offset
596 old_offset=prs_offset(ps);
597 prs_set_offset(ps, prs_data_size(ps));
599 if (!prs_grow(ps, extra_space))
602 prs_set_offset(ps, old_offset);
604 buffer->string_at_end=prs_data_size(ps);
609 /***************************************************************************
610 receive the notify message
611 ****************************************************************************/
613 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
617 struct pipes_struct *p;
619 struct handle_list *hl;
622 fstrcpy(printer,buf);
625 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
629 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
632 * We need to enumerate all printers. The handle list is shared
633 * across pipes of the same name, so just find the first open
638 for ( p = get_first_pipe(); p; get_next_pipe(p)) {
639 if (strequal(p->name, "spoolss")) {
640 hl = p->pipe_handles;
646 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
650 /* Iterate the printer list on this pipe. */
651 for (pol = hl->Policy; pol; pol = pol->next ) {
652 Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
658 * if the entry is the given printer or if it's a printerserver
659 * we send the message
662 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
663 if (strcmp(find_printer->dev.handlename, printer))
666 if (find_printer->notify.client_connected==True)
667 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
671 /***************************************************************************
673 ****************************************************************************/
674 static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle)
678 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
681 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
685 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
686 fstrcpy(printer, Printer->dev.handlename);
688 fstrcpy(printer, "");
690 /*srv_spoolss_receive_message(printer);*/
691 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
693 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
698 /********************************************************************
699 * spoolss_open_printer
701 * called from the spoolss dispatcher
702 ********************************************************************/
704 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
707 WERROR result = WERR_OK;
710 UNISTR2 *printername = NULL;
711 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
712 /* uint32 user_switch = q_u->user_switch; - notused */
713 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
714 POLICY_HND *handle = &r_u->handle;
718 struct current_user user;
720 if (q_u->printername_ptr != 0)
721 printername = &q_u->printername;
723 if (printername == NULL)
724 return WERR_INVALID_PRINTER_NAME;
726 /* some sanity check because you can open a printer or a print server */
727 /* aka: \\server\printer or \\server */
728 unistr2_to_ascii(name, printername, sizeof(name)-1);
730 DEBUGADD(3,("checking name: %s\n",name));
732 if (!open_printer_hnd(p, handle, name))
733 return WERR_INVALID_PRINTER_NAME;
736 if (printer_default->datatype_ptr != NULL)
738 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
739 set_printer_hnd_datatype(handle, datatype);
742 set_printer_hnd_datatype(handle, "");
745 if (!set_printer_hnd_accesstype(p, handle, printer_default->access_required)) {
746 close_printer_handle(p, handle);
747 return WERR_ACCESS_DENIED;
751 First case: the user is opening the print server:
753 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
754 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
756 Then both Win2k and WinNT clients try an OpenPrinterEx with
757 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
758 or if the user is listed in the smb.conf printer admin parameter.
760 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
761 client view printer folder, but does not show the MSAPW.
763 Note: this test needs code to check access rights here too. Jeremy
764 could you look at this?
767 Second case: the user is opening a printer:
768 NT doesn't let us connect to a printer if the connecting user
769 doesn't have print permission.
773 get_current_user(&user, p);
775 if (handle_is_printserver(p, handle)) {
776 if (printer_default->access_required == 0) {
779 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
781 /* Printserver handles use global struct... */
784 if (!lp_ms_add_printer_wizard()) {
785 close_printer_handle(p, handle);
786 return WERR_ACCESS_DENIED;
788 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
792 close_printer_handle(p, handle);
793 return WERR_ACCESS_DENIED;
799 /* NT doesn't let us connect to a printer if the connecting user
800 doesn't have print permission. */
802 if (!get_printer_snum(p, handle, &snum))
805 /* map an empty access mask to the minimum access mask */
806 if (printer_default->access_required == 0x0)
807 printer_default->access_required = PRINTER_ACCESS_USE;
811 * If we are not serving the printer driver for this printer,
812 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
813 * will keep NT clients happy --jerry
816 if (lp_use_client_driver(snum)
817 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
819 printer_default->access_required = PRINTER_ACCESS_USE;
822 if (!print_access_check(&user, snum, printer_default->access_required)) {
823 DEBUG(3, ("access DENIED for printer open\n"));
824 close_printer_handle(p, handle);
825 return WERR_ACCESS_DENIED;
829 * If we have a default device pointer in the
830 * printer_default struct, then we need to get
831 * the printer info from the tdb and if there is
832 * no default devicemode there then we do a *SET*
833 * here ! This is insanity.... JRA.
837 * If the openprinterex rpc call contains a devmode,
838 * it's a per-user one. This per-user devmode is derivated
839 * from the global devmode. Openprinterex() contains a per-user
840 * devmode for when you do EMF printing and spooling.
841 * In the EMF case, the NT workstation is only doing half the job
842 * of rendering the page. The other half is done by running the printer
843 * driver on the server.
844 * The EMF file doesn't contain the page description (paper size, orientation, ...).
845 * The EMF file only contains what is to be printed on the page.
846 * So in order for the server to know how to print, the NT client sends
847 * a devicemode attached to the openprinterex call.
848 * But this devicemode is short lived, it's only valid for the current print job.
850 * If Samba would have supported EMF spooling, this devicemode would
851 * have been attached to the handle, to sent it to the driver to correctly
852 * rasterize the EMF file.
854 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
855 * we just act as a pass-thru between windows and the printer.
857 * In order to know that Samba supports only RAW spooling, NT has to call
858 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
859 * and until NT sends a RAW job, we refuse it.
861 * But to call getprinter() or startdoc(), you first need a valid handle,
862 * and to get an handle you have to call openprintex(). Hence why you have
863 * a devicemode in the openprinterex() call.
866 * Differences between NT4 and NT 2000.
869 * On NT4, you only have a global devicemode. This global devicemode can be changed
870 * by the administrator (or by a user with enough privs). Everytime a user
871 * wants to print, the devicemode is resetted to the default. In Word, everytime
872 * you print, the printer's characteristics are always reset to the global devicemode.
876 * In W2K, there is the notion of per-user devicemode. The first time you use
877 * a printer, a per-user devicemode is build from the global devicemode.
878 * If you change your per-user devicemode, it is saved in the registry, under the
879 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
880 * printer preferences available.
882 * To change the per-user devicemode: it's the "Printing Preferences ..." button
883 * on the General Tab of the printer properties windows.
885 * To change the global devicemode: it's the "Printing Defaults..." button
886 * on the Advanced Tab of the printer properties window.
894 if (printer_default->devmode_cont.devmode != NULL) {
895 result = printer_write_default_dev( snum, printer_default);
897 close_printer_handle(p, handle);
907 /****************************************************************************
908 ****************************************************************************/
909 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
910 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
916 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
925 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
926 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
932 printer->info_3=NULL;
933 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
937 printer->info_6=NULL;
938 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
948 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
949 NT_DEVICEMODE **pp_nt_devmode)
951 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
954 * Ensure nt_devmode is a valid pointer
955 * as we will be overwriting it.
958 if (nt_devmode == NULL) {
959 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
960 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
964 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
965 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
967 nt_devmode->specversion=devmode->specversion;
968 nt_devmode->driverversion=devmode->driverversion;
969 nt_devmode->size=devmode->size;
970 nt_devmode->fields=devmode->fields;
971 nt_devmode->orientation=devmode->orientation;
972 nt_devmode->papersize=devmode->papersize;
973 nt_devmode->paperlength=devmode->paperlength;
974 nt_devmode->paperwidth=devmode->paperwidth;
975 nt_devmode->scale=devmode->scale;
976 nt_devmode->copies=devmode->copies;
977 nt_devmode->defaultsource=devmode->defaultsource;
978 nt_devmode->printquality=devmode->printquality;
979 nt_devmode->color=devmode->color;
980 nt_devmode->duplex=devmode->duplex;
981 nt_devmode->yresolution=devmode->yresolution;
982 nt_devmode->ttoption=devmode->ttoption;
983 nt_devmode->collate=devmode->collate;
985 nt_devmode->logpixels=devmode->logpixels;
986 nt_devmode->bitsperpel=devmode->bitsperpel;
987 nt_devmode->pelswidth=devmode->pelswidth;
988 nt_devmode->pelsheight=devmode->pelsheight;
989 nt_devmode->displayflags=devmode->displayflags;
990 nt_devmode->displayfrequency=devmode->displayfrequency;
991 nt_devmode->icmmethod=devmode->icmmethod;
992 nt_devmode->icmintent=devmode->icmintent;
993 nt_devmode->mediatype=devmode->mediatype;
994 nt_devmode->dithertype=devmode->dithertype;
995 nt_devmode->reserved1=devmode->reserved1;
996 nt_devmode->reserved2=devmode->reserved2;
997 nt_devmode->panningwidth=devmode->panningwidth;
998 nt_devmode->panningheight=devmode->panningheight;
1001 * Only change private and driverextra if the incoming devmode
1002 * has a new one. JRA.
1005 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1006 SAFE_FREE(nt_devmode->private);
1007 nt_devmode->driverextra=devmode->driverextra;
1008 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1010 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1013 *pp_nt_devmode = nt_devmode;
1018 /********************************************************************
1019 * _spoolss_enddocprinter_internal.
1020 ********************************************************************/
1022 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1024 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1027 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1031 Printer->document_started=False;
1032 print_job_end(Printer->jobid,True);
1033 /* error codes unhandled so far ... */
1038 /********************************************************************
1039 * api_spoolss_closeprinter
1040 ********************************************************************/
1042 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1044 POLICY_HND *handle = &q_u->handle;
1046 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1048 if (Printer && Printer->document_started)
1049 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1051 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1053 if (!close_printer_handle(p, handle))
1059 /********************************************************************
1060 * api_spoolss_deleteprinter
1062 ********************************************************************/
1064 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1066 POLICY_HND *handle = &q_u->handle;
1067 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1070 if (Printer && Printer->document_started)
1071 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1073 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1075 result = delete_printer_handle(p, handle);
1077 if (W_ERROR_IS_OK(result)) {
1078 srv_spoolss_sendnotify(p, handle);
1084 /*******************************************************************
1085 * static function to lookup the version id corresponding to an
1086 * long architecture string
1087 ******************************************************************/
1088 static int get_version_id (char * arch)
1091 struct table_node archi_table[]= {
1093 {"Windows 4.0", "WIN40", 0 },
1094 {"Windows NT x86", "W32X86", 2 },
1095 {"Windows NT R4000", "W32MIPS", 2 },
1096 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1097 {"Windows NT PowerPC", "W32PPC", 2 },
1101 for (i=0; archi_table[i].long_archi != NULL; i++)
1103 if (strcmp(arch, archi_table[i].long_archi) == 0)
1104 return (archi_table[i].version);
1110 /********************************************************************
1111 * _spoolss_deleteprinterdriver
1113 * We currently delete the driver for the architecture only.
1114 * This can leave the driver for other archtectures. However,
1115 * since every printer associates a "Windows NT x86" driver name
1116 * and we cannot delete that one while it is in use, **and** since
1117 * it is impossible to assign a driver to a Samba printer without
1118 * having the "Windows NT x86" driver installed,...
1120 * ....we should not get into trouble here.
1123 ********************************************************************/
1125 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
1126 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1130 NT_PRINTER_DRIVER_INFO_LEVEL info;
1133 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1134 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1136 /* check that we have a valid driver name first */
1137 if ((version=get_version_id(arch)) == -1) {
1138 /* this is what NT returns */
1139 return WERR_INVALID_ENVIRONMENT;
1143 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1144 return WERR_UNKNOWN_PRINTER_DRIVER;
1148 if (printer_driver_in_use(arch, driver))
1150 return WERR_PRINTER_DRIVER_IN_USE;
1153 return delete_printer_driver(info.info_3);
1157 /********************************************************************
1158 GetPrinterData on a printer server Handle.
1159 ********************************************************************/
1160 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1164 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1166 if (!strcmp(value, "BeepEnabled")) {
1168 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1170 SIVAL(*data, 0, 0x01);
1175 if (!strcmp(value, "EventLog")) {
1177 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1179 SIVAL(*data, 0, 0x1B);
1184 if (!strcmp(value, "NetPopup")) {
1186 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1188 SIVAL(*data, 0, 0x01);
1193 if (!strcmp(value, "MajorVersion")) {
1195 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1197 SIVAL(*data, 0, 0x02);
1202 if (!strcmp(value, "DefaultSpoolDirectory")) {
1203 pstring string="You are using a Samba server";
1205 *needed = 2*(strlen(string)+1);
1206 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1208 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1210 /* it's done by hand ready to go on the wire */
1211 for (i=0; i<strlen(string); i++) {
1212 (*data)[2*i]=string[i];
1213 (*data)[2*i+1]='\0';
1218 if (!strcmp(value, "Architecture")) {
1219 pstring string="Windows NT x86";
1221 *needed = 2*(strlen(string)+1);
1222 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1224 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1225 for (i=0; i<strlen(string); i++) {
1226 (*data)[2*i]=string[i];
1227 (*data)[2*i+1]='\0';
1235 /********************************************************************
1236 GetPrinterData on a printer Handle.
1237 ********************************************************************/
1238 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1239 fstring value, uint32 *type,
1240 uint8 **data, uint32 *needed, uint32 in_size )
1242 NT_PRINTER_INFO_LEVEL *printer = NULL;
1246 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1248 DEBUG(5,("getprinterdata_printer\n"));
1251 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1255 if(!get_printer_snum(p, handle, &snum))
1258 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1261 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1262 free_a_printer(&printer, 2);
1266 free_a_printer(&printer, 2);
1268 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1271 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1275 memset(*data, 0, in_size *sizeof(uint8));
1276 /* copy the min(in_size, len) */
1277 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1284 DEBUG(5,("getprinterdata_printer:copy done\n"));
1291 /********************************************************************
1292 * spoolss_getprinterdata
1293 ********************************************************************/
1295 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1297 POLICY_HND *handle = &q_u->handle;
1298 UNISTR2 *valuename = &q_u->valuename;
1299 uint32 in_size = q_u->size;
1300 uint32 *type = &r_u->type;
1301 uint32 *out_size = &r_u->size;
1302 uint8 **data = &r_u->data;
1303 uint32 *needed = &r_u->needed;
1307 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1310 * Reminder: when it's a string, the length is in BYTES
1311 * even if UNICODE is negociated.
1318 /* in case of problem, return some default values */
1322 DEBUG(4,("_spoolss_getprinterdata\n"));
1325 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1327 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1331 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1333 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1334 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1336 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1339 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1340 /* reply this param doesn't exist */
1342 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1348 return WERR_INVALID_PARAM;
1351 if (*needed > *out_size)
1352 return WERR_STATUS_MORE_ENTRIES;
1357 /***************************************************************************
1358 connect to the client
1359 ****************************************************************************/
1360 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1365 * If it's the first connection, contact the client
1366 * and connect to the IPC$ share anonumously
1368 if (smb_connections==0) {
1369 fstring unix_printer;
1371 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1373 if(!spoolss_connect_to_client(&cli, unix_printer))
1375 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1381 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1387 /********************************************************************
1389 * ReplyFindFirstPrinterChangeNotifyEx
1391 * jfmxxxx: before replying OK: status=0
1392 * should do a rpc call to the workstation asking ReplyOpenPrinter
1393 * have to code it, later.
1395 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1396 * called from api_spoolss_rffpcnex
1397 ********************************************************************/
1399 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1401 POLICY_HND *handle = &q_u->handle;
1402 uint32 flags = q_u->flags;
1403 uint32 options = q_u->options;
1404 UNISTR2 *localmachine = &q_u->localmachine;
1405 uint32 printerlocal = q_u->printerlocal;
1406 SPOOL_NOTIFY_OPTION *option = q_u->option;
1408 /* store the notify value in the printer struct */
1410 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1413 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1417 Printer->notify.flags=flags;
1418 Printer->notify.options=options;
1419 Printer->notify.printerlocal=printerlocal;
1421 if (Printer->notify.option)
1422 free_spool_notify_option(&Printer->notify.option);
1424 Printer->notify.option=dup_spool_notify_option(option);
1426 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1428 /* connect to the client machine and send a ReplyOpenPrinter */
1429 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1430 Printer->notify.printerlocal, 1,
1431 &Printer->notify.client_hnd))
1432 Printer->notify.client_connected=True;
1437 /*******************************************************************
1438 * fill a notify_info_data with the servername
1439 ********************************************************************/
1441 static void spoolss_notify_server_name(int snum,
1442 SPOOL_NOTIFY_INFO_DATA *data,
1443 print_queue_struct *queue,
1444 NT_PRINTER_INFO_LEVEL *printer,
1445 TALLOC_CTX *mem_ctx)
1447 pstring temp_name, temp;
1450 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1452 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
1454 data->notify_data.data.length = len / 2;
1455 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1457 if (!data->notify_data.data.string) {
1458 data->notify_data.data.length = 0;
1462 memcpy(data->notify_data.data.string, temp, len);
1465 /*******************************************************************
1466 * fill a notify_info_data with the printername (not including the servername).
1467 ********************************************************************/
1468 static void spoolss_notify_printer_name(int snum,
1469 SPOOL_NOTIFY_INFO_DATA *data,
1470 print_queue_struct *queue,
1471 NT_PRINTER_INFO_LEVEL *printer,
1472 TALLOC_CTX *mem_ctx)
1477 /* the notify name should not contain the \\server\ part */
1478 char *p = strrchr_m(printer->info_2->printername, '\\');
1481 p = printer->info_2->printername;
1486 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
1487 data->notify_data.data.length = len / 2;
1488 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1490 if (!data->notify_data.data.string) {
1491 data->notify_data.data.length = 0;
1495 memcpy(data->notify_data.data.string, temp, len);
1498 /*******************************************************************
1499 * fill a notify_info_data with the servicename
1500 ********************************************************************/
1501 static void spoolss_notify_share_name(int snum,
1502 SPOOL_NOTIFY_INFO_DATA *data,
1503 print_queue_struct *queue,
1504 NT_PRINTER_INFO_LEVEL *printer,
1505 TALLOC_CTX *mem_ctx)
1510 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
1512 data->notify_data.data.length = len / 2;
1513 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1515 if (!data->notify_data.data.string) {
1516 data->notify_data.data.length = 0;
1520 memcpy(data->notify_data.data.string, temp, len);
1523 /*******************************************************************
1524 * fill a notify_info_data with the port name
1525 ********************************************************************/
1526 static void spoolss_notify_port_name(int snum,
1527 SPOOL_NOTIFY_INFO_DATA *data,
1528 print_queue_struct *queue,
1529 NT_PRINTER_INFO_LEVEL *printer,
1530 TALLOC_CTX *mem_ctx)
1535 /* even if it's strange, that's consistant in all the code */
1537 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
1539 data->notify_data.data.length = len / 2;
1540 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1542 if (!data->notify_data.data.string) {
1543 data->notify_data.data.length = 0;
1547 memcpy(data->notify_data.data.string, temp, len);
1550 /*******************************************************************
1551 * fill a notify_info_data with the printername
1552 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1553 * but it doesn't exist, have to see what to do
1554 ********************************************************************/
1555 static void spoolss_notify_driver_name(int snum,
1556 SPOOL_NOTIFY_INFO_DATA *data,
1557 print_queue_struct *queue,
1558 NT_PRINTER_INFO_LEVEL *printer,
1559 TALLOC_CTX *mem_ctx)
1564 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
1565 data->notify_data.data.length = len / 2;
1566 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1568 if (!data->notify_data.data.string) {
1569 data->notify_data.data.length = 0;
1573 memcpy(data->notify_data.data.string, temp, len);
1576 /*******************************************************************
1577 * fill a notify_info_data with the comment
1578 ********************************************************************/
1579 static void spoolss_notify_comment(int snum,
1580 SPOOL_NOTIFY_INFO_DATA *data,
1581 print_queue_struct *queue,
1582 NT_PRINTER_INFO_LEVEL *printer,
1583 TALLOC_CTX *mem_ctx)
1588 if (*printer->info_2->comment == '\0')
1589 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
1592 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
1594 data->notify_data.data.length = len / 2;
1595 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1597 if (!data->notify_data.data.string) {
1598 data->notify_data.data.length = 0;
1602 memcpy(data->notify_data.data.string, temp, len);
1605 /*******************************************************************
1606 * fill a notify_info_data with the comment
1607 * jfm:xxxx incorrect, have to create a new smb.conf option
1608 * location = "Room 1, floor 2, building 3"
1609 ********************************************************************/
1610 static void spoolss_notify_location(int snum,
1611 SPOOL_NOTIFY_INFO_DATA *data,
1612 print_queue_struct *queue,
1613 NT_PRINTER_INFO_LEVEL *printer,
1614 TALLOC_CTX *mem_ctx)
1619 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
1621 data->notify_data.data.length = len / 2;
1622 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1624 if (!data->notify_data.data.string) {
1625 data->notify_data.data.length = 0;
1629 memcpy(data->notify_data.data.string, temp, len);
1632 /*******************************************************************
1633 * fill a notify_info_data with the device mode
1634 * jfm:xxxx don't to it for know but that's a real problem !!!
1635 ********************************************************************/
1636 static void spoolss_notify_devmode(int snum,
1637 SPOOL_NOTIFY_INFO_DATA *data,
1638 print_queue_struct *queue,
1639 NT_PRINTER_INFO_LEVEL *printer,
1640 TALLOC_CTX *mem_ctx)
1644 /*******************************************************************
1645 * fill a notify_info_data with the separator file name
1646 * jfm:xxxx just return no file could add an option to smb.conf
1647 * separator file = "separator.txt"
1648 ********************************************************************/
1649 static void spoolss_notify_sepfile(int snum,
1650 SPOOL_NOTIFY_INFO_DATA *data,
1651 print_queue_struct *queue,
1652 NT_PRINTER_INFO_LEVEL *printer,
1653 TALLOC_CTX *mem_ctx)
1658 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
1660 data->notify_data.data.length = len / 2;
1661 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1663 if (!data->notify_data.data.string) {
1664 data->notify_data.data.length = 0;
1668 memcpy(data->notify_data.data.string, temp, len);
1671 /*******************************************************************
1672 * fill a notify_info_data with the print processor
1673 * jfm:xxxx return always winprint to indicate we don't do anything to it
1674 ********************************************************************/
1675 static void spoolss_notify_print_processor(int snum,
1676 SPOOL_NOTIFY_INFO_DATA *data,
1677 print_queue_struct *queue,
1678 NT_PRINTER_INFO_LEVEL *printer,
1679 TALLOC_CTX *mem_ctx)
1684 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
1686 data->notify_data.data.length = len / 2;
1687 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1689 if (!data->notify_data.data.string) {
1690 data->notify_data.data.length = 0;
1694 memcpy(data->notify_data.data.string, temp, len);
1697 /*******************************************************************
1698 * fill a notify_info_data with the print processor options
1699 * jfm:xxxx send an empty string
1700 ********************************************************************/
1701 static void spoolss_notify_parameters(int snum,
1702 SPOOL_NOTIFY_INFO_DATA *data,
1703 print_queue_struct *queue,
1704 NT_PRINTER_INFO_LEVEL *printer,
1705 TALLOC_CTX *mem_ctx)
1710 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
1712 data->notify_data.data.length = len / 2;
1713 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1715 if (!data->notify_data.data.string) {
1716 data->notify_data.data.length = 0;
1720 memcpy(data->notify_data.data.string, temp, len);
1723 /*******************************************************************
1724 * fill a notify_info_data with the data type
1725 * jfm:xxxx always send RAW as data type
1726 ********************************************************************/
1727 static void spoolss_notify_datatype(int snum,
1728 SPOOL_NOTIFY_INFO_DATA *data,
1729 print_queue_struct *queue,
1730 NT_PRINTER_INFO_LEVEL *printer,
1731 TALLOC_CTX *mem_ctx)
1736 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
1738 data->notify_data.data.length = len / 2;
1739 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1741 if (!data->notify_data.data.string) {
1742 data->notify_data.data.length = 0;
1746 memcpy(data->notify_data.data.string, temp, len);
1749 /*******************************************************************
1750 * fill a notify_info_data with the security descriptor
1751 * jfm:xxxx send an null pointer to say no security desc
1752 * have to implement security before !
1753 ********************************************************************/
1754 static void spoolss_notify_security_desc(int snum,
1755 SPOOL_NOTIFY_INFO_DATA *data,
1756 print_queue_struct *queue,
1757 NT_PRINTER_INFO_LEVEL *printer,
1758 TALLOC_CTX *mem_ctx)
1760 data->notify_data.data.length=0;
1761 data->notify_data.data.string = NULL;
1764 /*******************************************************************
1765 * fill a notify_info_data with the attributes
1766 * jfm:xxxx a samba printer is always shared
1767 ********************************************************************/
1768 static void spoolss_notify_attributes(int snum,
1769 SPOOL_NOTIFY_INFO_DATA *data,
1770 print_queue_struct *queue,
1771 NT_PRINTER_INFO_LEVEL *printer,
1772 TALLOC_CTX *mem_ctx)
1774 data->notify_data.value[0] = printer->info_2->attributes;
1775 data->notify_data.value[1] = 0;
1778 /*******************************************************************
1779 * fill a notify_info_data with the priority
1780 ********************************************************************/
1781 static void spoolss_notify_priority(int snum,
1782 SPOOL_NOTIFY_INFO_DATA *data,
1783 print_queue_struct *queue,
1784 NT_PRINTER_INFO_LEVEL *printer,
1785 TALLOC_CTX *mem_ctx)
1787 data->notify_data.value[0] = printer->info_2->priority;
1788 data->notify_data.value[1] = 0;
1791 /*******************************************************************
1792 * fill a notify_info_data with the default priority
1793 ********************************************************************/
1794 static void spoolss_notify_default_priority(int snum,
1795 SPOOL_NOTIFY_INFO_DATA *data,
1796 print_queue_struct *queue,
1797 NT_PRINTER_INFO_LEVEL *printer,
1798 TALLOC_CTX *mem_ctx)
1800 data->notify_data.value[0] = printer->info_2->default_priority;
1801 data->notify_data.value[1] = 0;
1804 /*******************************************************************
1805 * fill a notify_info_data with the start time
1806 ********************************************************************/
1807 static void spoolss_notify_start_time(int snum,
1808 SPOOL_NOTIFY_INFO_DATA *data,
1809 print_queue_struct *queue,
1810 NT_PRINTER_INFO_LEVEL *printer,
1811 TALLOC_CTX *mem_ctx)
1813 data->notify_data.value[0] = printer->info_2->starttime;
1814 data->notify_data.value[1] = 0;
1817 /*******************************************************************
1818 * fill a notify_info_data with the until time
1819 ********************************************************************/
1820 static void spoolss_notify_until_time(int snum,
1821 SPOOL_NOTIFY_INFO_DATA *data,
1822 print_queue_struct *queue,
1823 NT_PRINTER_INFO_LEVEL *printer,
1824 TALLOC_CTX *mem_ctx)
1826 data->notify_data.value[0] = printer->info_2->untiltime;
1827 data->notify_data.value[1] = 0;
1830 /*******************************************************************
1831 * fill a notify_info_data with the status
1832 ********************************************************************/
1833 static void spoolss_notify_status(int snum,
1834 SPOOL_NOTIFY_INFO_DATA *data,
1835 print_queue_struct *queue,
1836 NT_PRINTER_INFO_LEVEL *printer,
1837 TALLOC_CTX *mem_ctx)
1839 print_status_struct status;
1841 print_queue_length(snum, &status);
1842 data->notify_data.value[0]=(uint32) status.status;
1843 data->notify_data.value[1] = 0;
1846 /*******************************************************************
1847 * fill a notify_info_data with the number of jobs queued
1848 ********************************************************************/
1849 static void spoolss_notify_cjobs(int snum,
1850 SPOOL_NOTIFY_INFO_DATA *data,
1851 print_queue_struct *queue,
1852 NT_PRINTER_INFO_LEVEL *printer,
1853 TALLOC_CTX *mem_ctx)
1855 data->notify_data.value[0] = print_queue_length(snum, NULL);
1856 data->notify_data.value[1] = 0;
1859 /*******************************************************************
1860 * fill a notify_info_data with the average ppm
1861 ********************************************************************/
1862 static void spoolss_notify_average_ppm(int snum,
1863 SPOOL_NOTIFY_INFO_DATA *data,
1864 print_queue_struct *queue,
1865 NT_PRINTER_INFO_LEVEL *printer,
1866 TALLOC_CTX *mem_ctx)
1868 /* always respond 8 pages per minutes */
1869 /* a little hard ! */
1870 data->notify_data.value[0] = printer->info_2->averageppm;
1871 data->notify_data.value[1] = 0;
1874 /*******************************************************************
1875 * fill a notify_info_data with username
1876 ********************************************************************/
1877 static void spoolss_notify_username(int snum,
1878 SPOOL_NOTIFY_INFO_DATA *data,
1879 print_queue_struct *queue,
1880 NT_PRINTER_INFO_LEVEL *printer,
1881 TALLOC_CTX *mem_ctx)
1886 len = rpcstr_push(temp, queue->user, sizeof(temp)-2, STR_TERMINATE);
1889 data->notify_data.data.length = len / 2;
1890 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1892 if (!data->notify_data.data.string) {
1893 data->notify_data.data.length = 0;
1897 memcpy(data->notify_data.data.string, temp, len);
1900 /*******************************************************************
1901 * fill a notify_info_data with job status
1902 ********************************************************************/
1903 static void spoolss_notify_job_status(int snum,
1904 SPOOL_NOTIFY_INFO_DATA *data,
1905 print_queue_struct *queue,
1906 NT_PRINTER_INFO_LEVEL *printer,
1907 TALLOC_CTX *mem_ctx)
1909 data->notify_data.value[0]=nt_printj_status(queue->status);
1910 data->notify_data.value[1] = 0;
1913 /*******************************************************************
1914 * fill a notify_info_data with job name
1915 ********************************************************************/
1916 static void spoolss_notify_job_name(int snum,
1917 SPOOL_NOTIFY_INFO_DATA *data,
1918 print_queue_struct *queue,
1919 NT_PRINTER_INFO_LEVEL *printer,
1920 TALLOC_CTX *mem_ctx)
1925 len = rpcstr_push(temp, queue->file, sizeof(temp)-2, STR_TERMINATE);
1927 data->notify_data.data.length = len / 2;
1928 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1930 if (!data->notify_data.data.string) {
1931 data->notify_data.data.length = 0;
1935 memcpy(data->notify_data.data.string, temp, len);
1938 /*******************************************************************
1939 * fill a notify_info_data with job status
1940 ********************************************************************/
1941 static void spoolss_notify_job_status_string(int snum,
1942 SPOOL_NOTIFY_INFO_DATA *data,
1943 print_queue_struct *queue,
1944 NT_PRINTER_INFO_LEVEL *printer,
1945 TALLOC_CTX *mem_ctx)
1948 * Now we're returning job status codes we just return a "" here. JRA.
1955 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1958 switch (queue->status) {
1963 p = ""; /* NT provides the paused string */
1972 #endif /* NO LONGER NEEDED. */
1974 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
1976 data->notify_data.data.length = len / 2;
1977 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1979 if (!data->notify_data.data.string) {
1980 data->notify_data.data.length = 0;
1984 memcpy(data->notify_data.data.string, temp, len);
1987 /*******************************************************************
1988 * fill a notify_info_data with job time
1989 ********************************************************************/
1990 static void spoolss_notify_job_time(int snum,
1991 SPOOL_NOTIFY_INFO_DATA *data,
1992 print_queue_struct *queue,
1993 NT_PRINTER_INFO_LEVEL *printer,
1994 TALLOC_CTX *mem_ctx)
1996 data->notify_data.value[0]=0x0;
1997 data->notify_data.value[1]=0;
2000 /*******************************************************************
2001 * fill a notify_info_data with job size
2002 ********************************************************************/
2003 static void spoolss_notify_job_size(int snum,
2004 SPOOL_NOTIFY_INFO_DATA *data,
2005 print_queue_struct *queue,
2006 NT_PRINTER_INFO_LEVEL *printer,
2007 TALLOC_CTX *mem_ctx)
2009 data->notify_data.value[0]=queue->size;
2010 data->notify_data.value[1]=0;
2013 /*******************************************************************
2014 * fill a notify_info_data with job position
2015 ********************************************************************/
2016 static void spoolss_notify_job_position(int snum,
2017 SPOOL_NOTIFY_INFO_DATA *data,
2018 print_queue_struct *queue,
2019 NT_PRINTER_INFO_LEVEL *printer,
2020 TALLOC_CTX *mem_ctx)
2022 data->notify_data.value[0]=queue->job;
2023 data->notify_data.value[1]=0;
2026 /*******************************************************************
2027 * fill a notify_info_data with submitted time
2028 ********************************************************************/
2029 static void spoolss_notify_submitted_time(int snum,
2030 SPOOL_NOTIFY_INFO_DATA *data,
2031 print_queue_struct *queue,
2032 NT_PRINTER_INFO_LEVEL *printer,
2033 TALLOC_CTX *mem_ctx)
2039 t=gmtime(&queue->time);
2041 len = sizeof(SYSTEMTIME);
2043 data->notify_data.data.length = len;
2044 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2046 if (!data->notify_data.data.string) {
2047 data->notify_data.data.length = 0;
2051 make_systemtime(&st, t);
2052 memcpy(data->notify_data.data.string,&st,len);
2057 struct s_notify_info_data_table
2063 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2064 print_queue_struct *queue,
2065 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2068 struct s_notify_info_data_table notify_info_data_table[] =
2070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2090 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2091 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2092 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2093 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2094 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2095 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2096 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2097 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2098 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2099 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2100 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2101 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2102 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2103 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2104 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2105 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2106 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2107 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2108 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2109 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2110 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2111 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2112 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2113 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2114 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2115 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2116 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2117 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2118 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2119 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2120 { END, END, "", END, NULL }
2123 /*******************************************************************
2124 return the size of info_data structure
2125 ********************************************************************/
2126 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2130 while (notify_info_data_table[i].type != END)
2132 if ( (notify_info_data_table[i].type == type ) &&
2133 (notify_info_data_table[i].field == field ) )
2135 return (notify_info_data_table[i].size);
2142 /*******************************************************************
2143 return the type of notify_info_data
2144 ********************************************************************/
2145 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2149 while (notify_info_data_table[i].type != END)
2151 if ( (notify_info_data_table[i].type == type ) &&
2152 (notify_info_data_table[i].field == field ) )
2154 if (notify_info_data_table[i].size == POINTER)
2168 /****************************************************************************
2169 ****************************************************************************/
2170 static int search_notify(uint16 type, uint16 field, int *value)
2175 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2177 if ( (notify_info_data_table[j].type == type ) &&
2178 (notify_info_data_table[j].field == field ) )
2183 if ( found && (notify_info_data_table[j].fn != NULL) )
2189 /****************************************************************************
2190 ****************************************************************************/
2191 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2193 info_data->type = type;
2194 info_data->field = field;
2195 info_data->reserved = 0;
2197 info_data->size = size_of_notify_info_data(type, field);
2198 info_data->enc_type = type_of_notify_info_data(type, field);
2202 /*******************************************************************
2204 * fill a notify_info struct with info asked
2206 ********************************************************************/
2207 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2208 snum, SPOOL_NOTIFY_OPTION_TYPE
2209 *option_type, uint32 id,
2210 TALLOC_CTX *mem_ctx)
2216 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2217 NT_PRINTER_INFO_LEVEL *printer = NULL;
2218 print_queue_struct *queue=NULL;
2220 type=option_type->type;
2222 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2223 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2224 option_type->count, lp_servicename(snum)));
2226 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2229 for(field_num=0; field_num<option_type->count; field_num++) {
2230 field = option_type->fields[field_num];
2231 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2233 if (!search_notify(type, field, &j) )
2236 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2237 DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2240 else info->data = tid;
2242 current_data=&info->data[info->count];
2244 construct_info_data(current_data, type, field, id);
2246 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2247 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2249 notify_info_data_table[j].fn(snum, current_data, queue,
2255 free_a_printer(&printer, 2);
2259 /*******************************************************************
2261 * fill a notify_info struct with info asked
2263 ********************************************************************/
2264 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2265 SPOOL_NOTIFY_INFO *info,
2266 NT_PRINTER_INFO_LEVEL *printer,
2267 int snum, SPOOL_NOTIFY_OPTION_TYPE
2268 *option_type, uint32 id,
2269 TALLOC_CTX *mem_ctx)
2275 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2277 DEBUG(4,("construct_notify_jobs_info\n"));
2279 type = option_type->type;
2281 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2282 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2283 option_type->count));
2285 for(field_num=0; field_num<option_type->count; field_num++) {
2286 field = option_type->fields[field_num];
2288 if (!search_notify(type, field, &j) )
2291 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2292 DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2295 else info->data = tid;
2297 current_data=&(info->data[info->count]);
2299 construct_info_data(current_data, type, field, id);
2300 notify_info_data_table[j].fn(snum, current_data, queue,
2309 * JFM: The enumeration is not that simple, it's even non obvious.
2311 * let's take an example: I want to monitor the PRINTER SERVER for
2312 * the printer's name and the number of jobs currently queued.
2313 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2314 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2316 * I have 3 printers on the back of my server.
2318 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2321 * 1 printer 1 name 1
2322 * 2 printer 1 cjob 1
2323 * 3 printer 2 name 2
2324 * 4 printer 2 cjob 2
2325 * 5 printer 3 name 3
2326 * 6 printer 3 name 3
2328 * that's the print server case, the printer case is even worse.
2331 /*******************************************************************
2333 * enumerate all printers on the printserver
2334 * fill a notify_info struct with info asked
2336 ********************************************************************/
2338 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2339 SPOOL_NOTIFY_INFO *info,
2340 TALLOC_CTX *mem_ctx)
2343 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2344 int n_services=lp_numservices();
2347 SPOOL_NOTIFY_OPTION *option;
2348 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2350 DEBUG(4,("printserver_notify_info\n"));
2352 option=Printer->notify.option;
2358 for (i=0; i<option->count; i++) {
2359 option_type=&(option->ctr.type[i]);
2361 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2364 for (snum=0; snum<n_services; snum++)
2365 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2366 if (construct_notify_printer_info
2367 (info, snum, option_type, id, mem_ctx))
2372 * Debugging information, don't delete.
2375 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2376 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2377 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2379 for (i=0; i<info->count; i++) {
2380 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2381 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2382 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2389 /*******************************************************************
2391 * fill a notify_info struct with info asked
2393 ********************************************************************/
2394 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2395 TALLOC_CTX *mem_ctx)
2398 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2401 SPOOL_NOTIFY_OPTION *option;
2402 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2404 print_queue_struct *queue=NULL;
2405 print_status_struct status;
2407 DEBUG(4,("printer_notify_info\n"));
2409 option=Printer->notify.option;
2415 get_printer_snum(p, hnd, &snum);
2417 for (i=0; i<option->count; i++) {
2418 option_type=&option->ctr.type[i];
2420 switch ( option_type->type ) {
2421 case PRINTER_NOTIFY_TYPE:
2422 if(construct_notify_printer_info(info, snum,
2428 case JOB_NOTIFY_TYPE: {
2429 NT_PRINTER_INFO_LEVEL *printer = NULL;
2431 count = print_queue_status(snum, &queue, &status);
2433 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
2434 lp_servicename(snum))))
2437 for (j=0; j<count; j++) {
2438 construct_notify_jobs_info(&queue[j], info,
2445 free_a_printer(&printer, 2);
2455 * Debugging information, don't delete.
2458 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2459 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2460 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2462 for (i=0; i<info->count; i++) {
2463 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2464 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2465 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2471 /********************************************************************
2473 ********************************************************************/
2475 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2477 POLICY_HND *handle = &q_u->handle;
2478 /* uint32 change = q_u->change; - notused. */
2479 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2480 SPOOL_NOTIFY_INFO *info = &r_u->info;
2482 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2483 WERROR result = WERR_BADFID;
2485 /* we always have a NOTIFY_INFO struct */
2489 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2490 OUR_HANDLE(handle)));
2494 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2496 /* jfm: the change value isn't used right now.
2497 * we will honour it when
2498 * a) we'll be able to send notification to the client
2499 * b) we'll have a way to communicate between the spoolss process.
2501 * same thing for option->flags
2502 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2503 * I don't have a global notification system, I'm sending back all the
2504 * informations even when _NOTHING_ has changed.
2507 /* just ignore the SPOOL_NOTIFY_OPTION */
2509 switch (Printer->printer_type) {
2510 case PRINTER_HANDLE_IS_PRINTSERVER:
2511 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2514 case PRINTER_HANDLE_IS_PRINTER:
2515 result = printer_notify_info(p, handle, info, p->mem_ctx);
2523 /********************************************************************
2524 * construct_printer_info_0
2525 * fill a printer_info_0 struct
2526 ********************************************************************/
2527 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2531 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2532 counter_printer_0 *session_counter;
2533 uint32 global_counter;
2536 print_status_struct status;
2538 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2541 count = print_queue_length(snum, &status);
2543 /* check if we already have a counter for this printer */
2544 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2546 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2547 if (session_counter->snum == snum)
2551 /* it's the first time, add it to the list */
2552 if (session_counter==NULL) {
2553 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2554 free_a_printer(&ntprinter, 2);
2557 ZERO_STRUCTP(session_counter);
2558 session_counter->snum=snum;
2559 session_counter->counter=0;
2560 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2564 session_counter->counter++;
2567 * the global_counter should be stored in a TDB as it's common to all the clients
2568 * and should be zeroed on samba startup
2570 global_counter=session_counter->counter;
2572 pstrcpy(chaine,ntprinter->info_2->printername);
2574 init_unistr(&printer->printername, chaine);
2576 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2577 init_unistr(&printer->servername, chaine);
2579 printer->cjobs = count;
2580 printer->total_jobs = 0;
2581 printer->total_bytes = 0;
2583 setuptime = (time_t)ntprinter->info_2->setuptime;
2584 t=gmtime(&setuptime);
2586 printer->year = t->tm_year+1900;
2587 printer->month = t->tm_mon+1;
2588 printer->dayofweek = t->tm_wday;
2589 printer->day = t->tm_mday;
2590 printer->hour = t->tm_hour;
2591 printer->minute = t->tm_min;
2592 printer->second = t->tm_sec;
2593 printer->milliseconds = 0;
2595 printer->global_counter = global_counter;
2596 printer->total_pages = 0;
2597 printer->major_version = 0x0004; /* NT 4 */
2598 printer->build_version = 0x0565; /* build 1381 */
2599 printer->unknown7 = 0x1;
2600 printer->unknown8 = 0x0;
2601 printer->unknown9 = 0x0;
2602 printer->session_counter = session_counter->counter;
2603 printer->unknown11 = 0x0;
2604 printer->printer_errors = 0x0; /* number of print failure */
2605 printer->unknown13 = 0x0;
2606 printer->unknown14 = 0x1;
2607 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2608 printer->unknown16 = 0x0;
2609 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2610 printer->unknown18 = 0x0;
2611 printer->status = nt_printq_status(status.status);
2612 printer->unknown20 = 0x0;
2613 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2614 printer->unknown22 = 0x0;
2615 printer->unknown23 = 0x6; /* 6 ???*/
2616 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2617 printer->unknown25 = 0;
2618 printer->unknown26 = 0;
2619 printer->unknown27 = 0;
2620 printer->unknown28 = 0;
2621 printer->unknown29 = 0;
2623 free_a_printer(&ntprinter,2);
2627 /********************************************************************
2628 * construct_printer_info_1
2629 * fill a printer_info_1 struct
2630 ********************************************************************/
2631 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2635 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2637 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2640 printer->flags=flags;
2642 if (*ntprinter->info_2->comment == '\0') {
2643 init_unistr(&printer->comment, lp_comment(snum));
2644 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2645 ntprinter->info_2->drivername, lp_comment(snum));
2648 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2649 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2650 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2653 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2655 init_unistr(&printer->description, chaine);
2656 init_unistr(&printer->name, chaine2);
2658 free_a_printer(&ntprinter,2);
2663 /****************************************************************************
2664 Free a DEVMODE struct.
2665 ****************************************************************************/
2667 static void free_dev_mode(DEVICEMODE *dev)
2672 SAFE_FREE(dev->private);
2676 /****************************************************************************
2677 Create a DEVMODE struct. Returns malloced memory.
2678 ****************************************************************************/
2680 static DEVICEMODE *construct_dev_mode(int snum)
2684 NT_PRINTER_INFO_LEVEL *printer = NULL;
2685 NT_DEVICEMODE *ntdevmode = NULL;
2686 DEVICEMODE *devmode = NULL;
2688 DEBUG(7,("construct_dev_mode\n"));
2690 DEBUGADD(8,("getting printer characteristics\n"));
2692 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2693 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2697 ZERO_STRUCTP(devmode);
2699 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2702 if (printer->info_2->devmode)
2703 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2705 if (ntdevmode == NULL)
2708 DEBUGADD(8,("loading DEVICEMODE\n"));
2710 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2711 init_unistr(&devmode->devicename, adevice);
2713 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2714 init_unistr(&devmode->formname, aform);
2716 devmode->specversion = ntdevmode->specversion;
2717 devmode->driverversion = ntdevmode->driverversion;
2718 devmode->size = ntdevmode->size;
2719 devmode->driverextra = ntdevmode->driverextra;
2720 devmode->fields = ntdevmode->fields;
2722 devmode->orientation = ntdevmode->orientation;
2723 devmode->papersize = ntdevmode->papersize;
2724 devmode->paperlength = ntdevmode->paperlength;
2725 devmode->paperwidth = ntdevmode->paperwidth;
2726 devmode->scale = ntdevmode->scale;
2727 devmode->copies = ntdevmode->copies;
2728 devmode->defaultsource = ntdevmode->defaultsource;
2729 devmode->printquality = ntdevmode->printquality;
2730 devmode->color = ntdevmode->color;
2731 devmode->duplex = ntdevmode->duplex;
2732 devmode->yresolution = ntdevmode->yresolution;
2733 devmode->ttoption = ntdevmode->ttoption;
2734 devmode->collate = ntdevmode->collate;
2735 devmode->icmmethod = ntdevmode->icmmethod;
2736 devmode->icmintent = ntdevmode->icmintent;
2737 devmode->mediatype = ntdevmode->mediatype;
2738 devmode->dithertype = ntdevmode->dithertype;
2740 if (ntdevmode->private != NULL) {
2741 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2745 free_nt_devicemode(&ntdevmode);
2746 free_a_printer(&printer,2);
2753 free_nt_devicemode(&ntdevmode);
2755 free_a_printer(&printer,2);
2756 free_dev_mode(devmode);
2761 /********************************************************************
2762 * construct_printer_info_2
2763 * fill a printer_info_2 struct
2764 ********************************************************************/
2766 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2769 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2771 print_status_struct status;
2773 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2776 count = print_queue_length(snum, &status);
2778 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2779 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2780 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2781 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2782 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2784 if (*ntprinter->info_2->comment == '\0')
2785 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2787 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2789 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2790 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2791 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2792 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2793 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2795 printer->attributes = ntprinter->info_2->attributes;
2797 printer->priority = ntprinter->info_2->priority; /* priority */
2798 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2799 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2800 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2801 printer->status = nt_printq_status(status.status); /* status */
2802 printer->cjobs = count; /* jobs */
2803 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2805 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2806 DEBUG(8, ("Returning NULL Devicemode!\n"));
2809 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2810 /* steal the printer info sec_desc structure. [badly done]. */
2811 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2812 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2813 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2814 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2817 printer->secdesc = NULL;
2820 free_a_printer(&ntprinter, 2);
2824 /********************************************************************
2825 * construct_printer_info_3
2826 * fill a printer_info_3 struct
2827 ********************************************************************/
2828 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2830 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2831 PRINTER_INFO_3 *printer = NULL;
2833 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2837 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2838 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2842 ZERO_STRUCTP(printer);
2844 printer->flags = 4; /* These are the components of the SD we are returning. */
2845 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2846 /* steal the printer info sec_desc structure. [badly done]. */
2847 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2851 * Set the flags for the components we are returning.
2854 if (printer->secdesc->owner_sid)
2855 printer->flags |= OWNER_SECURITY_INFORMATION;
2857 if (printer->secdesc->grp_sid)
2858 printer->flags |= GROUP_SECURITY_INFORMATION;
2860 if (printer->secdesc->dacl)
2861 printer->flags |= DACL_SECURITY_INFORMATION;
2863 if (printer->secdesc->sacl)
2864 printer->flags |= SACL_SECURITY_INFORMATION;
2867 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2868 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2869 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2872 free_a_printer(&ntprinter, 2);
2874 *pp_printer = printer;
2878 /********************************************************************
2879 Spoolss_enumprinters.
2880 ********************************************************************/
2881 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2885 int n_services=lp_numservices();
2886 PRINTER_INFO_1 *tp, *printers=NULL;
2887 PRINTER_INFO_1 current_prt;
2889 DEBUG(4,("enum_all_printers_info_1\n"));
2891 for (snum=0; snum<n_services; snum++) {
2892 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2893 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2895 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2896 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2897 DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2898 SAFE_FREE(printers);
2903 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2904 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
2910 /* check the required size. */
2911 for (i=0; i<*returned; i++)
2912 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2914 if (!alloc_buffer_size(buffer, *needed))
2915 return WERR_INSUFFICIENT_BUFFER;
2917 /* fill the buffer with the structures */
2918 for (i=0; i<*returned; i++)
2919 smb_io_printer_info_1("", buffer, &printers[i], 0);
2922 SAFE_FREE(printers);
2924 if (*needed > offered) {
2926 return WERR_INSUFFICIENT_BUFFER;
2932 /********************************************************************
2933 enum_all_printers_info_1_local.
2934 *********************************************************************/
2935 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2937 DEBUG(4,("enum_all_printers_info_1_local\n"));
2939 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2942 /********************************************************************
2943 enum_all_printers_info_1_name.
2944 *********************************************************************/
2945 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2949 DEBUG(4,("enum_all_printers_info_1_name\n"));
2951 if ((name[0] == '\\') && (name[1] == '\\'))
2954 if (is_myname_or_ipaddr(s)) {
2955 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2958 return WERR_INVALID_NAME;
2961 /********************************************************************
2962 enum_all_printers_info_1_remote.
2963 *********************************************************************/
2964 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2966 PRINTER_INFO_1 *printer;
2967 fstring printername;
2970 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2972 /* JFM: currently it's more a place holder than anything else.
2973 * In the spooler world there is a notion of server registration.
2974 * the print servers are registring (sp ?) on the PDC (in the same domain)
2976 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2979 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2984 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2985 slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2986 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2988 init_unistr(&printer->description, desc);
2989 init_unistr(&printer->name, printername);
2990 init_unistr(&printer->comment, comment);
2991 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2993 /* check the required size. */
2994 *needed += spoolss_size_printer_info_1(printer);
2996 if (!alloc_buffer_size(buffer, *needed)) {
2998 return WERR_INSUFFICIENT_BUFFER;
3001 /* fill the buffer with the structures */
3002 smb_io_printer_info_1("", buffer, printer, 0);
3007 if (*needed > offered) {
3009 return WERR_INSUFFICIENT_BUFFER;
3015 /********************************************************************
3016 enum_all_printers_info_1_network.
3017 *********************************************************************/
3019 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3021 DEBUG(4,("enum_all_printers_info_1_network\n"));
3023 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3026 /********************************************************************
3027 * api_spoolss_enumprinters
3029 * called from api_spoolss_enumprinters (see this to understand)
3030 ********************************************************************/
3032 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3036 int n_services=lp_numservices();
3037 PRINTER_INFO_2 *tp, *printers=NULL;
3038 PRINTER_INFO_2 current_prt;
3040 for (snum=0; snum<n_services; snum++) {
3041 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3042 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3044 if (construct_printer_info_2(¤t_prt, snum)) {
3045 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3046 DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3047 SAFE_FREE(printers);
3052 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3053 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
3059 /* check the required size. */
3060 for (i=0; i<*returned; i++)
3061 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3063 if (!alloc_buffer_size(buffer, *needed)) {
3064 for (i=0; i<*returned; i++) {
3065 free_devmode(printers[i].devmode);
3067 SAFE_FREE(printers);
3068 return WERR_INSUFFICIENT_BUFFER;
3071 /* fill the buffer with the structures */
3072 for (i=0; i<*returned; i++)
3073 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3076 for (i=0; i<*returned; i++) {
3077 free_devmode(printers[i].devmode);
3079 SAFE_FREE(printers);
3081 if (*needed > offered) {
3083 return WERR_INSUFFICIENT_BUFFER;
3089 /********************************************************************
3090 * handle enumeration of printers at level 1
3091 ********************************************************************/
3092 static WERROR enumprinters_level1( uint32 flags, fstring name,
3093 NEW_BUFFER *buffer, uint32 offered,
3094 uint32 *needed, uint32 *returned)
3096 /* Not all the flags are equals */
3098 if (flags & PRINTER_ENUM_LOCAL)
3099 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3101 if (flags & PRINTER_ENUM_NAME)
3102 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3104 if (flags & PRINTER_ENUM_REMOTE)
3105 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3107 if (flags & PRINTER_ENUM_NETWORK)
3108 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3110 return WERR_OK; /* NT4sp5 does that */
3113 /********************************************************************
3114 * handle enumeration of printers at level 2
3115 ********************************************************************/
3116 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3117 NEW_BUFFER *buffer, uint32 offered,
3118 uint32 *needed, uint32 *returned)
3120 char *s = servername;
3122 if (flags & PRINTER_ENUM_LOCAL) {
3123 return enum_all_printers_info_2(buffer, offered, needed, returned);
3126 if (flags & PRINTER_ENUM_NAME) {
3127 if ((servername[0] == '\\') && (servername[1] == '\\'))
3129 if (is_myname_or_ipaddr(s))
3130 return enum_all_printers_info_2(buffer, offered, needed, returned);
3132 return WERR_INVALID_NAME;
3135 if (flags & PRINTER_ENUM_REMOTE)
3136 return WERR_UNKNOWN_LEVEL;
3141 /********************************************************************
3142 * handle enumeration of printers at level 5
3143 ********************************************************************/
3144 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3145 NEW_BUFFER *buffer, uint32 offered,
3146 uint32 *needed, uint32 *returned)
3148 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3152 /********************************************************************
3153 * api_spoolss_enumprinters
3155 * called from api_spoolss_enumprinters (see this to understand)
3156 ********************************************************************/
3158 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3160 uint32 flags = q_u->flags;
3161 UNISTR2 *servername = &q_u->servername;
3162 uint32 level = q_u->level;
3163 NEW_BUFFER *buffer = NULL;
3164 uint32 offered = q_u->offered;
3165 uint32 *needed = &r_u->needed;
3166 uint32 *returned = &r_u->returned;
3170 /* that's an [in out] buffer */
3171 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3172 buffer = r_u->buffer;
3174 DEBUG(4,("_spoolss_enumprinters\n"));
3181 * flags==PRINTER_ENUM_NAME
3182 * if name=="" then enumerates all printers
3183 * if name!="" then enumerate the printer
3184 * flags==PRINTER_ENUM_REMOTE
3185 * name is NULL, enumerate printers
3186 * Level 2: name!="" enumerates printers, name can't be NULL
3187 * Level 3: doesn't exist
3188 * Level 4: does a local registry lookup
3189 * Level 5: same as Level 2
3192 unistr2_to_ascii(name, servername, sizeof(name)-1);
3197 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3199 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3201 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3206 return WERR_UNKNOWN_LEVEL;
3209 /****************************************************************************
3210 ****************************************************************************/
3211 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3213 PRINTER_INFO_0 *printer=NULL;
3215 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3218 construct_printer_info_0(printer, snum);
3220 /* check the required size. */
3221 *needed += spoolss_size_printer_info_0(printer);
3223 if (!alloc_buffer_size(buffer, *needed)) {
3225 return WERR_INSUFFICIENT_BUFFER;
3228 /* fill the buffer with the structures */
3229 smb_io_printer_info_0("", buffer, printer, 0);
3234 if (*needed > offered) {
3235 return WERR_INSUFFICIENT_BUFFER;
3241 /****************************************************************************
3242 ****************************************************************************/
3243 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3245 PRINTER_INFO_1 *printer=NULL;
3247 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3250 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3252 /* check the required size. */
3253 *needed += spoolss_size_printer_info_1(printer);
3255 if (!alloc_buffer_size(buffer, *needed)) {
3257 return WERR_INSUFFICIENT_BUFFER;
3260 /* fill the buffer with the structures */
3261 smb_io_printer_info_1("", buffer, printer, 0);
3266 if (*needed > offered) {
3267 return WERR_INSUFFICIENT_BUFFER;
3273 /****************************************************************************
3274 ****************************************************************************/
3275 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3277 PRINTER_INFO_2 *printer=NULL;
3279 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3282 construct_printer_info_2(printer, snum);
3284 /* check the required size. */
3285 *needed += spoolss_size_printer_info_2(printer);
3287 if (!alloc_buffer_size(buffer, *needed)) {
3288 free_printer_info_2(printer);
3289 return WERR_INSUFFICIENT_BUFFER;
3292 /* fill the buffer with the structures */
3293 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3294 free_printer_info_2(printer);
3299 free_printer_info_2(printer);
3301 if (*needed > offered) {
3302 return WERR_INSUFFICIENT_BUFFER;
3308 /****************************************************************************
3309 ****************************************************************************/
3310 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3312 PRINTER_INFO_3 *printer=NULL;
3314 if (!construct_printer_info_3(&printer, snum))
3317 /* check the required size. */
3318 *needed += spoolss_size_printer_info_3(printer);
3320 if (!alloc_buffer_size(buffer, *needed)) {
3321 free_printer_info_3(printer);
3322 return WERR_INSUFFICIENT_BUFFER;
3325 /* fill the buffer with the structures */
3326 smb_io_printer_info_3("", buffer, printer, 0);
3329 free_printer_info_3(printer);
3331 if (*needed > offered) {
3332 return WERR_INSUFFICIENT_BUFFER;
3338 /****************************************************************************
3339 ****************************************************************************/
3341 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3343 POLICY_HND *handle = &q_u->handle;
3344 uint32 level = q_u->level;
3345 NEW_BUFFER *buffer = NULL;
3346 uint32 offered = q_u->offered;
3347 uint32 *needed = &r_u->needed;
3351 /* that's an [in out] buffer */
3352 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3353 buffer = r_u->buffer;
3357 if (!get_printer_snum(p, handle, &snum))
3362 return getprinter_level_0(snum, buffer, offered, needed);
3364 return getprinter_level_1(snum, buffer, offered, needed);
3366 return getprinter_level_2(snum, buffer, offered, needed);
3368 return getprinter_level_3(snum, buffer, offered, needed);
3370 return WERR_UNKNOWN_LEVEL;
3373 /********************************************************************
3374 * fill a DRIVER_INFO_1 struct
3375 ********************************************************************/
3376 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3378 init_unistr( &info->name, driver.info_3->name);
3381 /********************************************************************
3382 * construct_printer_driver_info_1
3383 ********************************************************************/
3384 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3386 NT_PRINTER_INFO_LEVEL *printer = NULL;
3387 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3389 ZERO_STRUCT(driver);
3391 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3392 return WERR_INVALID_PRINTER_NAME;
3394 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3395 return WERR_UNKNOWN_PRINTER_DRIVER;
3397 fill_printer_driver_info_1(info, driver, servername, architecture);
3399 free_a_printer(&printer,2);
3404 /********************************************************************
3405 * construct_printer_driver_info_2
3406 * fill a printer_info_2 struct
3407 ********************************************************************/
3408 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3412 info->version=driver.info_3->cversion;
3414 init_unistr( &info->name, driver.info_3->name );
3415 init_unistr( &info->architecture, driver.info_3->environment );
3418 if (strlen(driver.info_3->driverpath)) {
3419 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3420 init_unistr( &info->driverpath, temp );
3422 init_unistr( &info->driverpath, "" );
3424 if (strlen(driver.info_3->datafile)) {
3425 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3426 init_unistr( &info->datafile, temp );
3428 init_unistr( &info->datafile, "" );
3430 if (strlen(driver.info_3->configfile)) {
3431 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3432 init_unistr( &info->configfile, temp );
3434 init_unistr( &info->configfile, "" );
3437 /********************************************************************
3438 * construct_printer_driver_info_2
3439 * fill a printer_info_2 struct
3440 ********************************************************************/
3441 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3443 NT_PRINTER_INFO_LEVEL *printer = NULL;
3444 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3446 ZERO_STRUCT(printer);
3447 ZERO_STRUCT(driver);
3449 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3450 return WERR_INVALID_PRINTER_NAME;
3452 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3453 return WERR_UNKNOWN_PRINTER_DRIVER;
3455 fill_printer_driver_info_2(info, driver, servername);
3457 free_a_printer(&printer,2);
3462 /********************************************************************
3463 * copy a strings array and convert to UNICODE
3465 * convert an array of ascii string to a UNICODE string
3466 ********************************************************************/
3467 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3475 DEBUG(6,("init_unistr_array\n"));
3479 if (char_array == NULL)
3483 if (!v) v = ""; /* hack to handle null lists */
3485 if (strlen(v) == 0) break;
3486 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3487 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3488 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3489 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3492 else *uni_array = tuary;
3493 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3498 (*uni_array)[j]=0x0000;
3501 DEBUGADD(6,("last one:done\n"));
3504 /********************************************************************
3505 * construct_printer_info_3
3506 * fill a printer_info_3 struct
3507 ********************************************************************/
3508 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3514 info->version=driver.info_3->cversion;
3516 init_unistr( &info->name, driver.info_3->name );
3517 init_unistr( &info->architecture, driver.info_3->environment );
3519 if (strlen(driver.info_3->driverpath)) {
3520 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3521 init_unistr( &info->driverpath, temp );
3523 init_unistr( &info->driverpath, "" );
3525 if (strlen(driver.info_3->datafile)) {
3526 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3527 init_unistr( &info->datafile, temp );
3529 init_unistr( &info->datafile, "" );
3531 if (strlen(driver.info_3->configfile)) {
3532 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3533 init_unistr( &info->configfile, temp );
3535 init_unistr( &info->configfile, "" );
3537 if (strlen(driver.info_3->helpfile)) {
3538 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3539 init_unistr( &info->helpfile, temp );
3541 init_unistr( &info->helpfile, "" );
3543 init_unistr( &info->monitorname, driver.info_3->monitorname );
3544 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3546 info->dependentfiles=NULL;
3547 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3550 /********************************************************************
3551 * construct_printer_info_3
3552 * fill a printer_info_3 struct
3553 ********************************************************************/
3554 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3556 NT_PRINTER_INFO_LEVEL *printer = NULL;
3557 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3559 ZERO_STRUCT(driver);
3561 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3562 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3563 if (!W_ERROR_IS_OK(status))
3564 return WERR_INVALID_PRINTER_NAME;
3566 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3567 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3568 if (!W_ERROR_IS_OK(status)) {
3569 free_a_printer(&printer,2);
3570 return WERR_UNKNOWN_PRINTER_DRIVER;
3573 fill_printer_driver_info_3(info, driver, servername);
3575 free_a_printer(&printer,2);
3580 /********************************************************************
3581 * construct_printer_info_6
3582 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3583 ********************************************************************/
3585 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3591 memset(&nullstr, '\0', sizeof(fstring));
3593 info->version=driver.info_3->cversion;
3595 init_unistr( &info->name, driver.info_3->name );
3596 init_unistr( &info->architecture, driver.info_3->environment );
3598 if (strlen(driver.info_3->driverpath)) {
3599 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3600 init_unistr( &info->driverpath, temp );
3602 init_unistr( &info->driverpath, "" );
3604 if (strlen(driver.info_3->datafile)) {
3605 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3606 init_unistr( &info->datafile, temp );
3608 init_unistr( &info->datafile, "" );
3610 if (strlen(driver.info_3->configfile)) {
3611 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3612 init_unistr( &info->configfile, temp );
3614 init_unistr( &info->configfile, "" );
3616 if (strlen(driver.info_3->helpfile)) {
3617 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3618 init_unistr( &info->helpfile, temp );
3620 init_unistr( &info->helpfile, "" );
3622 init_unistr( &info->monitorname, driver.info_3->monitorname );
3623 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3625 info->dependentfiles=NULL;
3626 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3628 info->previousdrivernames=NULL;
3629 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3631 info->driver_date.low=0;
3632 info->driver_date.high=0;
3635 info->driver_version_low=0;
3636 info->driver_version_high=0;
3638 init_unistr( &info->mfgname, "");
3639 init_unistr( &info->oem_url, "");
3640 init_unistr( &info->hardware_id, "");
3641 init_unistr( &info->provider, "");
3644 /********************************************************************
3645 * construct_printer_info_6
3646 * fill a printer_info_6 struct
3647 ********************************************************************/
3648 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3650 NT_PRINTER_INFO_LEVEL *printer = NULL;
3651 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3653 ZERO_STRUCT(driver);
3655 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3656 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3657 if (!W_ERROR_IS_OK(status))
3658 return WERR_INVALID_PRINTER_NAME;
3660 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3661 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3662 if (!W_ERROR_IS_OK(status)) {
3664 * Is this a W2k client ?
3668 free_a_printer(&printer,2);
3669 return WERR_UNKNOWN_PRINTER_DRIVER;
3672 /* Yes - try again with a WinNT driver. */
3674 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3675 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3676 if (!W_ERROR_IS_OK(status)) {
3677 free_a_printer(&printer,2);
3678 return WERR_UNKNOWN_PRINTER_DRIVER;
3682 fill_printer_driver_info_6(info, driver, servername);
3684 free_a_printer(&printer,2);
3689 /****************************************************************************
3690 ****************************************************************************/
3692 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3694 SAFE_FREE(info->dependentfiles);
3697 /****************************************************************************
3698 ****************************************************************************/
3700 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3702 SAFE_FREE(info->dependentfiles);
3706 /****************************************************************************
3707 ****************************************************************************/
3708 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3710 DRIVER_INFO_1 *info=NULL;
3713 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3716 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3717 if (!W_ERROR_IS_OK(status)) {
3722 /* check the required size. */
3723 *needed += spoolss_size_printer_driver_info_1(info);
3725 if (!alloc_buffer_size(buffer, *needed)) {
3727 return WERR_INSUFFICIENT_BUFFER;
3730 /* fill the buffer with the structures */
3731 smb_io_printer_driver_info_1("", buffer, info, 0);
3736 if (*needed > offered)
3737 return WERR_INSUFFICIENT_BUFFER;
3742 /****************************************************************************
3743 ****************************************************************************/
3744 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3746 DRIVER_INFO_2 *info=NULL;
3749 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3752 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3753 if (!W_ERROR_IS_OK(status)) {
3758 /* check the required size. */
3759 *needed += spoolss_size_printer_driver_info_2(info);
3761 if (!alloc_buffer_size(buffer, *needed)) {
3763 return WERR_INSUFFICIENT_BUFFER;
3766 /* fill the buffer with the structures */
3767 smb_io_printer_driver_info_2("", buffer, info, 0);
3772 if (*needed > offered)
3773 return WERR_INSUFFICIENT_BUFFER;
3778 /****************************************************************************
3779 ****************************************************************************/
3780 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3787 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3788 if (!W_ERROR_IS_OK(status)) {
3792 /* check the required size. */
3793 *needed += spoolss_size_printer_driver_info_3(&info);
3795 if (!alloc_buffer_size(buffer, *needed)) {
3796 free_printer_driver_info_3(&info);
3797 return WERR_INSUFFICIENT_BUFFER;
3800 /* fill the buffer with the structures */
3801 smb_io_printer_driver_info_3("", buffer, &info, 0);
3803 free_printer_driver_info_3(&info);
3805 if (*needed > offered)
3806 return WERR_INSUFFICIENT_BUFFER;
3811 /****************************************************************************
3812 ****************************************************************************/
3813 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3820 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3821 if (!W_ERROR_IS_OK(status)) {
3825 /* check the required size. */
3826 *needed += spoolss_size_printer_driver_info_6(&info);
3828 if (!alloc_buffer_size(buffer, *needed)) {
3829 free_printer_driver_info_6(&info);
3830 return WERR_INSUFFICIENT_BUFFER;
3833 /* fill the buffer with the structures */
3834 smb_io_printer_driver_info_6("", buffer, &info, 0);
3836 free_printer_driver_info_6(&info);
3838 if (*needed > offered)
3839 return WERR_INSUFFICIENT_BUFFER;
3844 /****************************************************************************
3845 ****************************************************************************/
3847 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3849 POLICY_HND *handle = &q_u->handle;
3850 UNISTR2 *uni_arch = &q_u->architecture;
3851 uint32 level = q_u->level;
3852 uint32 clientmajorversion = q_u->clientmajorversion;
3853 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3854 NEW_BUFFER *buffer = NULL;
3855 uint32 offered = q_u->offered;
3856 uint32 *needed = &r_u->needed;
3857 uint32 *servermajorversion = &r_u->servermajorversion;
3858 uint32 *serverminorversion = &r_u->serverminorversion;
3861 fstring architecture;
3864 /* that's an [in out] buffer */
3865 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3866 buffer = r_u->buffer;
3868 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3871 *servermajorversion=0;
3872 *serverminorversion=0;
3874 pstrcpy(servername, global_myname);
3875 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3877 if (!get_printer_snum(p, handle, &snum))
3882 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3884 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3886 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3888 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3891 return WERR_UNKNOWN_LEVEL;
3894 /****************************************************************************
3895 ****************************************************************************/
3897 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
3899 POLICY_HND *handle = &q_u->handle;
3901 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3904 Printer->page_started=True;
3908 DEBUG(3,("Error in startpageprinter printer handle\n"));
3912 /****************************************************************************
3913 ****************************************************************************/
3915 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
3917 POLICY_HND *handle = &q_u->handle;
3919 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3922 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3926 Printer->page_started=False;
3931 /********************************************************************
3932 * api_spoolss_getprinter
3933 * called from the spoolss dispatcher
3935 ********************************************************************/
3937 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
3939 POLICY_HND *handle = &q_u->handle;
3940 /* uint32 level = q_u->doc_info_container.level; - notused. */
3941 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
3942 uint32 *jobid = &r_u->jobid;
3944 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3948 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3949 struct current_user user;
3952 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3956 get_current_user(&user, p);
3959 * a nice thing with NT is it doesn't listen to what you tell it.
3960 * when asked to send _only_ RAW datas, it tries to send datas
3963 * So I add checks like in NT Server ...
3965 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3966 * there's a bug in NT client-side code, so we'll fix it in the
3967 * server-side code. *nnnnnggggh!*
3970 if (info_1->p_datatype != 0) {
3971 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3972 if (strcmp(datatype, "RAW") != 0) {
3974 return WERR_INVALID_DATATYPE;
3978 /* get the share number of the printer */
3979 if (!get_printer_snum(p, handle, &snum)) {
3983 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3985 Printer->jobid = print_job_start(&user, snum, jobname);
3987 /* An error occured in print_job_start() so return an appropriate
3990 if (Printer->jobid == -1) {
3991 return map_werror_from_unix(errno);
3994 Printer->document_started=True;
3995 (*jobid) = Printer->jobid;
4000 /********************************************************************
4001 * api_spoolss_getprinter
4002 * called from the spoolss dispatcher
4004 ********************************************************************/
4006 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4008 POLICY_HND *handle = &q_u->handle;
4010 return _spoolss_enddocprinter_internal(p, handle);
4013 /****************************************************************************
4014 ****************************************************************************/
4016 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4018 POLICY_HND *handle = &q_u->handle;
4019 uint32 buffer_size = q_u->buffer_size;
4020 uint8 *buffer = q_u->buffer;
4021 uint32 *buffer_written = &q_u->buffer_size2;
4023 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4026 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
4027 r_u->buffer_written = q_u->buffer_size2;
4031 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4034 r_u->buffer_written = q_u->buffer_size2;
4039 /********************************************************************
4040 * api_spoolss_getprinter
4041 * called from the spoolss dispatcher
4043 ********************************************************************/
4044 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4047 struct current_user user;
4049 WERROR errcode = WERR_BADFUNC;
4050 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4052 get_current_user(&user, p);
4055 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4059 if (!get_printer_snum(p, handle, &snum))
4063 case PRINTER_CONTROL_PAUSE:
4064 if (print_queue_pause(&user, snum, &errcode)) {
4068 case PRINTER_CONTROL_RESUME:
4069 case PRINTER_CONTROL_UNPAUSE:
4070 if (print_queue_resume(&user, snum, &errcode)) {
4074 case PRINTER_CONTROL_PURGE:
4075 if (print_queue_purge(&user, snum, &errcode)) {
4080 return WERR_UNKNOWN_LEVEL;
4086 /********************************************************************
4087 * api_spoolss_abortprinter
4088 ********************************************************************/
4090 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4092 POLICY_HND *handle = &q_u->handle;
4094 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4097 /********************************************************************
4098 * called by spoolss_api_setprinter
4099 * when updating a printer description
4100 ********************************************************************/
4101 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4102 const SPOOL_PRINTER_INFO_LEVEL *info,
4103 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4105 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4106 struct current_user user;
4110 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4112 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4113 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4114 OUR_HANDLE(handle)));
4116 result = WERR_BADFID;
4120 /* NT seems to like setting the security descriptor even though
4121 nothing may have actually changed. This causes annoying
4122 dialog boxes when the user doesn't have permission to change
4123 the security descriptor. */
4125 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4127 if (DEBUGLEVEL >= 10) {
4131 the_acl = old_secdesc_ctr->sec->dacl;
4132 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4133 PRINTERNAME(snum), the_acl->num_aces));
4135 for (i = 0; i < the_acl->num_aces; i++) {
4138 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4140 DEBUG(10, ("%s 0x%08x\n", sid_str,
4141 the_acl->ace[i].info.mask));
4144 the_acl = secdesc_ctr->sec->dacl;
4147 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4148 PRINTERNAME(snum), the_acl->num_aces));
4150 for (i = 0; i < the_acl->num_aces; i++) {
4153 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4155 DEBUG(10, ("%s 0x%08x\n", sid_str,
4156 the_acl->ace[i].info.mask));
4159 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4163 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4165 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4170 /* Work out which user is performing the operation */
4172 get_current_user(&user, p);
4174 /* Check the user has permissions to change the security
4175 descriptor. By experimentation with two NT machines, the user
4176 requires Full Access to the printer to change security
4179 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4180 result = WERR_ACCESS_DENIED;
4184 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4191 /********************************************************************
4192 Do Samba sanity checks on a printer info struct.
4193 this has changed purpose: it now "canonicalises" printer
4194 info from a client rather than just checking it is correct
4195 ********************************************************************/
4197 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4199 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4200 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4202 /* we force some elements to "correct" values */
4203 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4204 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4205 global_myname, lp_servicename(snum));
4206 fstrcpy(info->sharename, lp_servicename(snum));
4207 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4208 | PRINTER_ATTRIBUTE_LOCAL \
4209 | PRINTER_ATTRIBUTE_RAW_ONLY \
4210 | PRINTER_ATTRIBUTE_QUEUED ;
4215 /****************************************************************************
4216 ****************************************************************************/
4217 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4219 char *cmd = lp_addprinter_cmd();
4222 pstring driverlocation;
4227 /* build driver path... only 9X architecture is needed for legacy reasons */
4228 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4230 /* change \ to \\ for the shell */
4231 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4233 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4234 cmd, printer->info_2->printername, printer->info_2->sharename,
4235 printer->info_2->portname, printer->info_2->drivername,
4236 printer->info_2->location, driverlocation);
4238 DEBUG(10,("Running [%s]\n", command));
4239 ret = smbrun(command, &fd);
4240 DEBUGADD(10,("returned [%d]\n", ret));
4249 /* Get lines and convert them back to dos-codepage */
4250 qlines = fd_lines_load(fd, &numlines);
4251 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4255 /* Set the portname to what the script says the portname should be. */
4256 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4257 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4259 /* Send SIGHUP to process group... is there a better way? */
4264 file_lines_free(qlines);
4268 /* Return true if two devicemodes are equal */
4270 #define DEVMODE_CHECK_INT(field) \
4271 if (d1->field != d2->field) { \
4272 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4273 d1->field, d2->field)); \
4277 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4279 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4282 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4283 return False; /* if either is exclusively NULL are not equal */
4286 if (!strequal(d1->devicename, d2->devicename)) {
4287 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4291 if (!strequal(d1->formname, d2->formname)) {
4292 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4296 DEVMODE_CHECK_INT(specversion);
4297 DEVMODE_CHECK_INT(driverversion);
4298 DEVMODE_CHECK_INT(driverextra);
4299 DEVMODE_CHECK_INT(orientation);
4300 DEVMODE_CHECK_INT(papersize);
4301 DEVMODE_CHECK_INT(paperlength);
4302 DEVMODE_CHECK_INT(paperwidth);
4303 DEVMODE_CHECK_INT(scale);
4304 DEVMODE_CHECK_INT(copies);
4305 DEVMODE_CHECK_INT(defaultsource);
4306 DEVMODE_CHECK_INT(printquality);
4307 DEVMODE_CHECK_INT(color);
4308 DEVMODE_CHECK_INT(duplex);
4309 DEVMODE_CHECK_INT(yresolution);
4310 DEVMODE_CHECK_INT(ttoption);
4311 DEVMODE_CHECK_INT(collate);
4312 DEVMODE_CHECK_INT(logpixels);
4314 DEVMODE_CHECK_INT(fields);
4315 DEVMODE_CHECK_INT(bitsperpel);
4316 DEVMODE_CHECK_INT(pelswidth);
4317 DEVMODE_CHECK_INT(pelsheight);
4318 DEVMODE_CHECK_INT(displayflags);
4319 DEVMODE_CHECK_INT(displayfrequency);
4320 DEVMODE_CHECK_INT(icmmethod);
4321 DEVMODE_CHECK_INT(icmintent);
4322 DEVMODE_CHECK_INT(mediatype);
4323 DEVMODE_CHECK_INT(dithertype);
4324 DEVMODE_CHECK_INT(reserved1);
4325 DEVMODE_CHECK_INT(reserved2);
4326 DEVMODE_CHECK_INT(panningwidth);
4327 DEVMODE_CHECK_INT(panningheight);
4329 /* compare the private data if it exists */
4330 if (!d1->driverextra && !d2->driverextra) goto equal;
4333 DEVMODE_CHECK_INT(driverextra);
4335 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4336 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4341 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4345 /* Return true if two NT_PRINTER_PARAM structures are equal */
4347 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4348 NT_PRINTER_PARAM *p2)
4350 if (!p1 && !p2) goto equal;
4352 if ((!p1 && p2) || (p1 && !p2)) {
4353 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4357 /* Compare lists of printer parameters */
4361 NT_PRINTER_PARAM *q = p1;
4363 /* Find the parameter in the second structure */
4367 if (strequal(p1->value, q->value)) {
4369 if (p1->type != q->type) {
4370 DEBUG(10, ("nt_printer_param_equal():"
4371 "types for %s differ (%d != %d)\n",
4372 p1->value, p1->type,
4377 if (p1->data_len != q->data_len) {
4378 DEBUG(10, ("nt_printer_param_equal():"
4379 "len for %s differs (%d != %d)\n",
4380 p1->value, p1->data_len,
4385 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4388 DEBUG(10, ("nt_printer_param_equal():"
4389 "data for %s differs\n", p1->value));
4399 DEBUG(10, ("nt_printer_param_equal(): param %s "
4400 "does not exist\n", p1->value));
4409 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4413 /********************************************************************
4414 * Called by update_printer when trying to work out whether to
4415 * actually update printer info.
4416 ********************************************************************/
4418 #define PI_CHECK_INT(field) \
4419 if (pi1->field != pi2->field) { \
4420 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4421 pi1->field, pi2->field)); \
4425 #define PI_CHECK_STR(field) \
4426 if (!strequal(pi1->field, pi2->field)) { \
4427 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4428 pi1->field, pi2->field)); \
4432 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4433 NT_PRINTER_INFO_LEVEL *p2)
4435 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4437 /* Trivial conditions */
4439 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4443 if ((!p1 && p2) || (p1 && !p2) ||
4444 (!p1->info_2 && p2->info_2) ||
4445 (p1->info_2 && !p2->info_2)) {
4446 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4451 /* Compare two nt_printer_info_level structures. Don't compare
4452 status or cjobs as they seem to have something to do with the
4458 /* Don't check the attributes as we stomp on the value in
4459 check_printer_ok() anyway. */
4462 PI_CHECK_INT(attributes);
4465 PI_CHECK_INT(priority);
4466 PI_CHECK_INT(default_priority);
4467 PI_CHECK_INT(starttime);
4468 PI_CHECK_INT(untiltime);
4469 PI_CHECK_INT(averageppm);
4471 /* Yuck - don't check the printername or servername as the
4472 add_a_printer() code plays games with them. You can't
4473 change the printername or the sharename through this interface
4476 PI_CHECK_STR(sharename);
4477 PI_CHECK_STR(portname);
4478 PI_CHECK_STR(drivername);
4479 PI_CHECK_STR(comment);
4480 PI_CHECK_STR(location);
4482 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4486 PI_CHECK_STR(sepfile);
4487 PI_CHECK_STR(printprocessor);
4488 PI_CHECK_STR(datatype);
4489 PI_CHECK_STR(parameters);
4491 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4495 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4499 PI_CHECK_INT(changeid);
4500 PI_CHECK_INT(c_setprinter);
4501 PI_CHECK_INT(setuptime);
4504 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4508 /********************************************************************
4509 * called by spoolss_api_setprinter
4510 * when updating a printer description
4511 ********************************************************************/
4513 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4514 const SPOOL_PRINTER_INFO_LEVEL *info,
4515 DEVICEMODE *devmode)
4518 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4519 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4522 DEBUG(8,("update_printer\n"));
4527 DEBUG(0,("Send a mail to samba@samba.org\n"));
4528 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4529 result = WERR_UNKNOWN_LEVEL;
4534 result = WERR_BADFID;
4538 if (!get_printer_snum(p, handle, &snum)) {
4539 result = WERR_BADFID;
4543 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
4544 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
4545 result = WERR_BADFID;
4549 DEBUGADD(8,("Converting info_2 struct\n"));
4552 * convert_printer_info converts the incoming
4553 * info from the client and overwrites the info
4554 * just read from the tdb in the pointer 'printer'.
4557 if (!convert_printer_info(info, printer, level)) {
4558 result = WERR_NOMEM;
4562 if (info->info_2->devmode_ptr != 0) {
4563 /* we have a valid devmode
4564 convert it and link it*/
4566 DEBUGADD(8,("Converting the devicemode struct\n"));
4567 if (!convert_devicemode(printer->info_2->printername, devmode,
4568 &printer->info_2->devmode)) {
4569 result = WERR_NOMEM;
4574 /* Do sanity check on the requested changes for Samba */
4576 if (!check_printer_ok(printer->info_2, snum)) {
4577 result = WERR_INVALID_PARAM;
4581 /* NT likes to call this function even though nothing has actually
4582 changed. Check this so the user doesn't end up with an
4583 annoying permission denied dialog box. */
4585 if (nt_printer_info_level_equal(printer, old_printer)) {
4586 DEBUG(3, ("printer info has not changed\n"));
4591 /* Check calling user has permission to update printer description */
4593 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4594 DEBUG(3, ("printer property change denied by security "
4596 result = WERR_ACCESS_DENIED;
4600 /* Call addprinter hook */
4602 if (*lp_addprinter_cmd()) {
4603 if (!add_printer_hook(printer)) {
4604 result = WERR_ACCESS_DENIED;
4609 /* Update printer info */
4610 result = add_a_printer(*printer, 2);
4613 free_a_printer(&printer, 2);
4614 free_a_printer(&old_printer, 2);
4616 srv_spoolss_sendnotify(p, handle);
4621 /****************************************************************************
4622 ****************************************************************************/
4624 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4626 POLICY_HND *handle = &q_u->handle;
4627 uint32 level = q_u->level;
4628 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4629 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4630 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4631 uint32 command = q_u->command;
4633 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4636 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4640 /* check the level */
4643 return control_printer(handle, command, p);
4645 return update_printer(p, handle, level, info, devmode_ctr.devmode);
4647 return update_printer_sec(handle, level, info, p,
4650 return WERR_UNKNOWN_LEVEL;
4654 /****************************************************************************
4655 ****************************************************************************/
4657 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4659 POLICY_HND *handle = &q_u->handle;
4661 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4664 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4668 if (Printer->notify.client_connected==True)
4669 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4671 Printer->notify.flags=0;
4672 Printer->notify.options=0;
4673 Printer->notify.localmachine[0]='\0';
4674 Printer->notify.printerlocal=0;
4675 if (Printer->notify.option)
4676 free_spool_notify_option(&Printer->notify.option);
4677 Printer->notify.client_connected=False;
4682 /****************************************************************************
4683 ****************************************************************************/
4685 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4687 /* that's an [in out] buffer (despite appearences to the contrary) */
4688 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4691 return WERR_INVALID_PARAM; /* this is what a NT server
4692 returns for AddJob. AddJob
4693 must fail on non-local
4697 /****************************************************************************
4698 ****************************************************************************/
4699 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4700 int position, int snum)
4706 t=gmtime(&queue->time);
4707 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4709 job_info->jobid=queue->job;
4710 init_unistr(&job_info->printername, lp_servicename(snum));
4711 init_unistr(&job_info->machinename, temp_name);
4712 init_unistr(&job_info->username, queue->user);
4713 init_unistr(&job_info->document, queue->file);
4714 init_unistr(&job_info->datatype, "RAW");
4715 init_unistr(&job_info->text_status, "");
4716 job_info->status=nt_printj_status(queue->status);
4717 job_info->priority=queue->priority;
4718 job_info->position=position;
4719 job_info->totalpages=0;
4720 job_info->pagesprinted=0;
4722 make_systemtime(&job_info->submitted, t);
4725 /****************************************************************************
4726 ****************************************************************************/
4727 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4728 int position, int snum,
4729 NT_PRINTER_INFO_LEVEL *ntprinter)
4735 t=gmtime(&queue->time);
4736 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4738 job_info->jobid=queue->job;
4740 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4742 init_unistr(&job_info->printername, chaine);
4744 init_unistr(&job_info->machinename, temp_name);
4745 init_unistr(&job_info->username, queue->user);
4746 init_unistr(&job_info->document, queue->file);
4747 init_unistr(&job_info->notifyname, queue->user);
4748 init_unistr(&job_info->datatype, "RAW");
4749 init_unistr(&job_info->printprocessor, "winprint");
4750 init_unistr(&job_info->parameters, "");
4751 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4752 init_unistr(&job_info->text_status, "");
4754 /* and here the security descriptor */
4756 job_info->status=nt_printj_status(queue->status);
4757 job_info->priority=queue->priority;
4758 job_info->position=position;
4759 job_info->starttime=0;
4760 job_info->untiltime=0;
4761 job_info->totalpages=0;
4762 job_info->size=queue->size;
4763 make_systemtime(&(job_info->submitted), t);
4764 job_info->timeelapsed=0;
4765 job_info->pagesprinted=0;
4767 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4774 /****************************************************************************
4775 Enumjobs at level 1.
4776 ****************************************************************************/
4777 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
4778 NEW_BUFFER *buffer, uint32 offered,
4779 uint32 *needed, uint32 *returned)
4784 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4791 for (i=0; i<*returned; i++)
4792 fill_job_info_1(&info[i], &queue[i], i, snum);
4796 /* check the required size. */
4797 for (i=0; i<*returned; i++)
4798 (*needed) += spoolss_size_job_info_1(&info[i]);
4800 if (!alloc_buffer_size(buffer, *needed)) {
4802 return WERR_INSUFFICIENT_BUFFER;
4805 /* fill the buffer with the structures */
4806 for (i=0; i<*returned; i++)
4807 smb_io_job_info_1("", buffer, &info[i], 0);
4812 if (*needed > offered) {
4814 return WERR_INSUFFICIENT_BUFFER;
4820 /****************************************************************************
4821 Enumjobs at level 2.
4822 ****************************************************************************/
4823 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
4824 NEW_BUFFER *buffer, uint32 offered,
4825 uint32 *needed, uint32 *returned)
4827 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4832 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4838 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
4839 if (!W_ERROR_IS_OK(result)) {
4844 for (i=0; i<*returned; i++)
4845 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4847 free_a_printer(&ntprinter, 2);
4850 /* check the required size. */
4851 for (i=0; i<*returned; i++)
4852 (*needed) += spoolss_size_job_info_2(&info[i]);
4854 if (!alloc_buffer_size(buffer, *needed)) {
4856 return WERR_INSUFFICIENT_BUFFER;
4859 /* fill the buffer with the structures */
4860 for (i=0; i<*returned; i++)
4861 smb_io_job_info_2("", buffer, &info[i], 0);
4864 for (i = 0; i < *returned; i++)
4865 free_job_info_2(&info[i]);
4869 if (*needed > offered) {
4871 return WERR_INSUFFICIENT_BUFFER;
4877 /****************************************************************************
4879 ****************************************************************************/
4881 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4883 POLICY_HND *handle = &q_u->handle;
4884 /* uint32 firstjob = q_u->firstjob; - notused. */
4885 /* uint32 numofjobs = q_u->numofjobs; - notused. */
4886 uint32 level = q_u->level;
4887 NEW_BUFFER *buffer = NULL;
4888 uint32 offered = q_u->offered;
4889 uint32 *needed = &r_u->needed;
4890 uint32 *returned = &r_u->returned;
4893 print_status_struct prt_status;
4894 print_queue_struct *queue=NULL;
4896 /* that's an [in out] buffer */
4897 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4898 buffer = r_u->buffer;
4900 DEBUG(4,("_spoolss_enumjobs\n"));
4905 if (!get_printer_snum(p, handle, &snum))
4908 *returned = print_queue_status(snum, &queue, &prt_status);
4909 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4911 if (*returned == 0) {
4918 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4920 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4924 return WERR_UNKNOWN_LEVEL;
4928 /****************************************************************************
4929 ****************************************************************************/
4931 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
4936 /****************************************************************************
4937 ****************************************************************************/
4939 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
4941 POLICY_HND *handle = &q_u->handle;
4942 uint32 jobid = q_u->jobid;
4943 /* uint32 level = q_u->level; - notused. */
4944 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
4945 uint32 command = q_u->command;
4947 struct current_user user;
4949 WERROR errcode = WERR_BADFUNC;
4951 if (!get_printer_snum(p, handle, &snum)) {
4955 if (!print_job_exists(jobid)) {
4956 return WERR_INVALID_PRINTER_NAME;
4959 get_current_user(&user, p);
4962 case JOB_CONTROL_CANCEL:
4963 case JOB_CONTROL_DELETE:
4964 if (print_job_delete(&user, jobid, &errcode)) {
4968 case JOB_CONTROL_PAUSE:
4969 if (print_job_pause(&user, jobid, &errcode)) {
4973 case JOB_CONTROL_RESTART:
4974 case JOB_CONTROL_RESUME:
4975 if (print_job_resume(&user, jobid, &errcode)) {
4980 return WERR_UNKNOWN_LEVEL;
4986 /****************************************************************************
4987 Enumerates all printer drivers at level 1.
4988 ****************************************************************************/
4989 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4994 fstring *list = NULL;
4996 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4997 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5001 #define MAX_VERSION 4
5003 for (version=0; version<MAX_VERSION; version++) {
5005 ndrivers=get_ntdrivers(&list, architecture, version);
5006 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5012 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5013 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5014 SAFE_FREE(driver_info_1);
5018 else driver_info_1 = tdi1;
5021 for (i=0; i<ndrivers; i++) {
5023 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5024 ZERO_STRUCT(driver);
5025 status = get_a_printer_driver(&driver, 3, list[i],
5026 architecture, version);
5027 if (!W_ERROR_IS_OK(status)) {
5031 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5032 free_a_printer_driver(driver, 3);
5035 *returned+=ndrivers;
5039 /* check the required size. */
5040 for (i=0; i<*returned; i++) {
5041 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5042 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5045 if (!alloc_buffer_size(buffer, *needed)) {
5046 SAFE_FREE(driver_info_1);
5047 return WERR_INSUFFICIENT_BUFFER;
5050 /* fill the buffer with the driver structures */
5051 for (i=0; i<*returned; i++) {
5052 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5053 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5056 SAFE_FREE(driver_info_1);
5058 if (*needed > offered) {
5060 return WERR_INSUFFICIENT_BUFFER;
5066 /****************************************************************************
5067 Enumerates all printer drivers at level 2.
5068 ****************************************************************************/
5069 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5074 fstring *list = NULL;
5076 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5077 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5081 #define MAX_VERSION 4
5083 for (version=0; version<MAX_VERSION; version++) {
5085 ndrivers=get_ntdrivers(&list, architecture, version);
5086 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5092 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5093 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5094 SAFE_FREE(driver_info_2);
5098 else driver_info_2 = tdi2;
5101 for (i=0; i<ndrivers; i++) {
5104 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5105 ZERO_STRUCT(driver);
5106 status = get_a_printer_driver(&driver, 3, list[i],
5107 architecture, version);
5108 if (!W_ERROR_IS_OK(status)) {
5112 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5113 free_a_printer_driver(driver, 3);
5116 *returned+=ndrivers;
5120 /* check the required size. */
5121 for (i=0; i<*returned; i++) {
5122 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5123 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5126 if (!alloc_buffer_size(buffer, *needed)) {
5127 SAFE_FREE(driver_info_2);
5128 return WERR_INSUFFICIENT_BUFFER;
5131 /* fill the buffer with the form structures */
5132 for (i=0; i<*returned; i++) {
5133 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5134 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5137 SAFE_FREE(driver_info_2);
5139 if (*needed > offered) {
5141 return WERR_INSUFFICIENT_BUFFER;
5147 /****************************************************************************
5148 Enumerates all printer drivers at level 3.
5149 ****************************************************************************/
5150 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5155 fstring *list = NULL;
5157 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5158 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5162 #define MAX_VERSION 4
5164 for (version=0; version<MAX_VERSION; version++) {
5166 ndrivers=get_ntdrivers(&list, architecture, version);
5167 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5173 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5174 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5175 SAFE_FREE(driver_info_3);
5179 else driver_info_3 = tdi3;
5182 for (i=0; i<ndrivers; i++) {
5185 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5186 ZERO_STRUCT(driver);
5187 status = get_a_printer_driver(&driver, 3, list[i],
5188 architecture, version);
5189 if (!W_ERROR_IS_OK(status)) {
5193 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5194 free_a_printer_driver(driver, 3);
5197 *returned+=ndrivers;
5201 /* check the required size. */
5202 for (i=0; i<*returned; i++) {
5203 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5204 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5207 if (!alloc_buffer_size(buffer, *needed)) {
5208 SAFE_FREE(driver_info_3);
5209 return WERR_INSUFFICIENT_BUFFER;
5212 /* fill the buffer with the driver structures */
5213 for (i=0; i<*returned; i++) {
5214 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5215 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5218 for (i=0; i<*returned; i++)
5219 SAFE_FREE(driver_info_3[i].dependentfiles);
5221 SAFE_FREE(driver_info_3);
5223 if (*needed > offered) {
5225 return WERR_INSUFFICIENT_BUFFER;
5231 /****************************************************************************
5232 Enumerates all printer drivers.
5233 ****************************************************************************/
5235 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5237 /* UNISTR2 *name = &q_u->name; - notused. */
5238 UNISTR2 *environment = &q_u->environment;
5239 uint32 level = q_u->level;
5240 NEW_BUFFER *buffer = NULL;
5241 uint32 offered = q_u->offered;
5242 uint32 *needed = &r_u->needed;
5243 uint32 *returned = &r_u->returned;
5245 fstring *list = NULL;
5247 fstring architecture;
5249 /* that's an [in out] buffer */
5250 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5251 buffer = r_u->buffer;
5253 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5254 fstrcpy(servername, global_myname);
5258 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5262 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5264 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5266 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5270 return WERR_UNKNOWN_LEVEL;
5274 /****************************************************************************
5275 ****************************************************************************/
5277 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5279 form->flag=list->flag;
5280 init_unistr(&form->name, list->name);
5281 form->width=list->width;
5282 form->length=list->length;
5283 form->left=list->left;
5284 form->top=list->top;
5285 form->right=list->right;
5286 form->bottom=list->bottom;
5289 /****************************************************************************
5290 ****************************************************************************/
5292 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5294 /* POLICY_HND *handle = &q_u->handle; - notused. */
5295 uint32 level = q_u->level;
5296 NEW_BUFFER *buffer = NULL;
5297 uint32 offered = q_u->offered;
5298 uint32 *needed = &r_u->needed;
5299 uint32 *numofforms = &r_u->numofforms;
5300 uint32 numbuiltinforms;
5302 nt_forms_struct *list=NULL;
5303 nt_forms_struct *builtinlist=NULL;
5308 /* that's an [in out] buffer */
5309 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5310 buffer = r_u->buffer;
5312 DEBUG(4,("_spoolss_enumforms\n"));
5313 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5314 DEBUGADD(5,("Info level [%d]\n", level));
5316 numbuiltinforms = get_builtin_ntforms(&builtinlist);
5317 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
5318 *numofforms = get_ntforms(&list);
5319 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
5320 *numofforms += numbuiltinforms;
5322 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
5326 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5331 /* construct the list of form structures */
5332 for (i=0; i<numbuiltinforms; i++) {
5333 DEBUGADD(6,("Filling form number [%d]\n",i));
5334 fill_form_1(&forms_1[i], &builtinlist[i]);
5337 SAFE_FREE(builtinlist);
5339 for (; i<*numofforms; i++) {
5340 DEBUGADD(6,("Filling form number [%d]\n",i));
5341 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5346 /* check the required size. */
5347 for (i=0; i<numbuiltinforms; i++) {
5348 DEBUGADD(6,("adding form [%d]'s size\n",i));
5349 buffer_size += spoolss_size_form_1(&forms_1[i]);
5351 for (; i<*numofforms; i++) {
5352 DEBUGADD(6,("adding form [%d]'s size\n",i));
5353 buffer_size += spoolss_size_form_1(&forms_1[i]);
5356 *needed=buffer_size;
5358 if (!alloc_buffer_size(buffer, buffer_size)){
5360 return WERR_INSUFFICIENT_BUFFER;
5363 /* fill the buffer with the form structures */
5364 for (i=0; i<numbuiltinforms; i++) {
5365 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5366 smb_io_form_1("", buffer, &forms_1[i], 0);
5368 for (; i<*numofforms; i++) {
5369 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5370 smb_io_form_1("", buffer, &forms_1[i], 0);
5375 if (*needed > offered) {
5377 return WERR_INSUFFICIENT_BUFFER;
5384 SAFE_FREE(builtinlist);
5385 return WERR_UNKNOWN_LEVEL;
5390 /****************************************************************************
5391 ****************************************************************************/
5393 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5395 /* POLICY_HND *handle = &q_u->handle; - notused. */
5396 uint32 level = q_u->level;
5397 UNISTR2 *uni_formname = &q_u->formname;
5398 NEW_BUFFER *buffer = NULL;
5399 uint32 offered = q_u->offered;
5400 uint32 *needed = &r_u->needed;
5402 nt_forms_struct *list=NULL;
5403 nt_forms_struct builtin_form;
5408 int numofforms=0, i=0;
5410 /* that's an [in out] buffer */
5411 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5412 buffer = r_u->buffer;
5414 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5416 DEBUG(4,("_spoolss_getform\n"));
5417 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5418 DEBUGADD(5,("Info level [%d]\n", level));
5420 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5421 if (!foundBuiltin) {
5422 numofforms = get_ntforms(&list);
5423 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5425 if (numofforms == 0)
5432 fill_form_1(&form_1, &builtin_form);
5435 /* Check if the requested name is in the list of form structures */
5436 for (i=0; i<numofforms; i++) {
5438 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5440 if (strequal(form_name, list[i].name)) {
5441 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5442 fill_form_1(&form_1, &list[i]);
5448 if (i == numofforms) {
5452 /* check the required size. */
5454 *needed=spoolss_size_form_1(&form_1);
5456 if (!alloc_buffer_size(buffer, buffer_size)){
5457 return WERR_INSUFFICIENT_BUFFER;
5460 if (*needed > offered) {
5461 return WERR_INSUFFICIENT_BUFFER;
5464 /* fill the buffer with the form structures */
5465 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5466 smb_io_form_1("", buffer, &form_1, 0);
5472 return WERR_UNKNOWN_LEVEL;
5476 /****************************************************************************
5477 ****************************************************************************/
5478 static void fill_port_1(PORT_INFO_1 *port, char *name)
5480 init_unistr(&port->port_name, name);
5483 /****************************************************************************
5484 ****************************************************************************/
5485 static void fill_port_2(PORT_INFO_2 *port, char *name)
5487 init_unistr(&port->port_name, name);
5488 init_unistr(&port->monitor_name, "Local Monitor");
5489 init_unistr(&port->description, "Local Port");
5490 #define PORT_TYPE_WRITE 1
5491 port->port_type=PORT_TYPE_WRITE;
5495 /****************************************************************************
5497 ****************************************************************************/
5498 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5500 PORT_INFO_1 *ports=NULL;
5503 if (*lp_enumports_cmd()) {
5504 char *cmd = lp_enumports_cmd();
5511 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5513 DEBUG(10,("Running [%s]\n", command));
5514 ret = smbrun(command, &fd);
5515 DEBUG(10,("Returned [%d]\n", ret));
5519 /* Is this the best error to return here? */
5520 return WERR_ACCESS_DENIED;
5524 qlines = fd_lines_load(fd, &numlines);
5525 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5529 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5530 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
5531 werror_str(WERR_NOMEM)));
5532 file_lines_free(qlines);
5536 for (i=0; i<numlines; i++) {
5537 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5538 fill_port_1(&ports[i], qlines[i]);
5541 file_lines_free(qlines);
5544 *returned = numlines;
5547 *returned = 1; /* Sole Samba port returned. */
5549 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5552 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5554 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5557 /* check the required size. */
5558 for (i=0; i<*returned; i++) {
5559 DEBUGADD(6,("adding port [%d]'s size\n", i));
5560 *needed += spoolss_size_port_info_1(&ports[i]);
5563 if (!alloc_buffer_size(buffer, *needed)) {
5565 return WERR_INSUFFICIENT_BUFFER;
5568 /* fill the buffer with the ports structures */
5569 for (i=0; i<*returned; i++) {
5570 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5571 smb_io_port_1("", buffer, &ports[i], 0);
5576 if (*needed > offered) {
5578 return WERR_INSUFFICIENT_BUFFER;
5584 /****************************************************************************
5586 ****************************************************************************/
5588 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5590 PORT_INFO_2 *ports=NULL;
5593 if (*lp_enumports_cmd()) {
5594 char *cmd = lp_enumports_cmd();
5603 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5604 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5606 path = lp_lockdir();
5608 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
5609 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5612 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5613 ret = smbrun(command, &fd);
5614 DEBUGADD(10,("returned [%d]\n", ret));
5618 /* Is this the best error to return here? */
5619 return WERR_ACCESS_DENIED;
5623 qlines = fd_lines_load(fd, &numlines);
5624 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5628 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5629 file_lines_free(qlines);
5633 for (i=0; i<numlines; i++) {
5634 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5635 fill_port_2(&(ports[i]), qlines[i]);
5638 file_lines_free(qlines);
5641 *returned = numlines;
5647 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5650 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5652 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5655 /* check the required size. */
5656 for (i=0; i<*returned; i++) {
5657 DEBUGADD(6,("adding port [%d]'s size\n", i));
5658 *needed += spoolss_size_port_info_2(&ports[i]);
5661 if (!alloc_buffer_size(buffer, *needed)) {
5663 return WERR_INSUFFICIENT_BUFFER;
5666 /* fill the buffer with the ports structures */
5667 for (i=0; i<*returned; i++) {
5668 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5669 smb_io_port_2("", buffer, &ports[i], 0);
5674 if (*needed > offered) {
5676 return WERR_INSUFFICIENT_BUFFER;
5682 /****************************************************************************
5684 ****************************************************************************/
5686 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5688 /* UNISTR2 *name = &q_u->name; - notused. */
5689 uint32 level = q_u->level;
5690 NEW_BUFFER *buffer = NULL;
5691 uint32 offered = q_u->offered;
5692 uint32 *needed = &r_u->needed;
5693 uint32 *returned = &r_u->returned;
5695 /* that's an [in out] buffer */
5696 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5697 buffer = r_u->buffer;
5699 DEBUG(4,("_spoolss_enumports\n"));
5706 return enumports_level_1(buffer, offered, needed, returned);
5708 return enumports_level_2(buffer, offered, needed, returned);
5710 return WERR_UNKNOWN_LEVEL;
5714 /****************************************************************************
5715 ****************************************************************************/
5716 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5717 const SPOOL_PRINTER_INFO_LEVEL *info,
5718 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5719 uint32 user_switch, const SPOOL_USER_CTR *user,
5722 NT_PRINTER_INFO_LEVEL *printer = NULL;
5725 WERROR err = WERR_OK;
5727 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5728 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5732 ZERO_STRUCTP(printer);
5734 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5735 if (!convert_printer_info(info, printer, 2)) {
5736 free_a_printer(&printer, 2);
5740 /* check to see if the printer already exists */
5742 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
5743 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
5744 printer->info_2->sharename));
5745 free_a_printer(&printer, 2);
5746 return WERR_PRINTER_ALREADY_EXISTS;
5749 if (*lp_addprinter_cmd() )
5750 if ( !add_printer_hook(printer) ) {
5751 free_a_printer(&printer,2);
5752 return WERR_ACCESS_DENIED;
5755 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5756 printer->info_2->sharename);
5758 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5759 free_a_printer(&printer,2);
5760 return WERR_ACCESS_DENIED;
5763 /* you must be a printer admin to add a new printer */
5764 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5765 free_a_printer(&printer,2);
5766 return WERR_ACCESS_DENIED;
5770 * Do sanity check on the requested changes for Samba.
5773 if (!check_printer_ok(printer->info_2, snum)) {
5774 free_a_printer(&printer,2);
5775 return WERR_INVALID_PARAM;
5779 * When a printer is created, the drivername bound to the printer is used
5780 * to lookup previously saved driver initialization info, which is then
5781 * bound to the new printer, simulating what happens in the Windows arch.
5783 set_driver_init(printer, 2);
5785 /* write the ASCII on disk */
5786 err = add_a_printer(*printer, 2);
5787 if (!W_ERROR_IS_OK(err)) {
5788 free_a_printer(&printer,2);
5792 if (!open_printer_hnd(p, handle, name)) {
5793 /* Handle open failed - remove addition. */
5794 del_a_printer(printer->info_2->sharename);
5795 free_a_printer(&printer,2);
5796 return WERR_ACCESS_DENIED;
5799 free_a_printer(&printer,2);
5801 srv_spoolss_sendnotify(p, handle);
5806 /****************************************************************************
5807 ****************************************************************************/
5809 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5811 UNISTR2 *uni_srv_name = &q_u->server_name;
5812 uint32 level = q_u->level;
5813 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5814 uint32 unk0 = q_u->unk0;
5815 uint32 unk1 = q_u->unk1;
5816 uint32 unk2 = q_u->unk2;
5817 uint32 unk3 = q_u->unk3;
5818 uint32 user_switch = q_u->user_switch;
5819 SPOOL_USER_CTR *user = &q_u->user_ctr;
5820 POLICY_HND *handle = &r_u->handle;
5824 /* we don't handle yet */
5825 /* but I know what to do ... */
5826 return WERR_UNKNOWN_LEVEL;
5828 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5829 unk0, unk1, unk2, unk3,
5830 user_switch, user, handle);
5832 return WERR_UNKNOWN_LEVEL;
5836 /****************************************************************************
5837 ****************************************************************************/
5839 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5841 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5842 uint32 level = q_u->level;
5843 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5844 WERROR err = WERR_OK;
5845 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5846 struct current_user user;
5848 ZERO_STRUCT(driver);
5850 get_current_user(&user, p);
5852 if (!convert_printer_driver_info(info, &driver, level)) {
5857 DEBUG(5,("Cleaning driver's information\n"));
5858 err = clean_up_driver_struct(driver, level, &user);
5859 if (!W_ERROR_IS_OK(err))
5862 DEBUG(5,("Moving driver to final destination\n"));
5863 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5864 if (W_ERROR_IS_OK(err))
5865 err = WERR_ACCESS_DENIED;
5869 if (add_a_printer_driver(driver, level)!=0) {
5870 err = WERR_ACCESS_DENIED;
5875 free_a_printer_driver(driver, level);
5879 /****************************************************************************
5880 ****************************************************************************/
5881 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5883 init_unistr(&info->name, name);
5886 /****************************************************************************
5887 ****************************************************************************/
5888 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5892 pstring short_archi;
5893 DRIVER_DIRECTORY_1 *info=NULL;
5895 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5897 if (get_short_archi(short_archi, long_archi)==False)
5898 return WERR_INVALID_ENVIRONMENT;
5900 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5903 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5905 DEBUG(4,("printer driver directory: [%s]\n", path));
5907 fill_driverdir_1(info, path);
5909 *needed += spoolss_size_driverdir_info_1(info);
5911 if (!alloc_buffer_size(buffer, *needed)) {
5913 return WERR_INSUFFICIENT_BUFFER;
5916 smb_io_driverdir_1("", buffer, info, 0);
5920 if (*needed > offered)
5921 return WERR_INSUFFICIENT_BUFFER;
5926 /****************************************************************************
5927 ****************************************************************************/
5929 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
5931 UNISTR2 *name = &q_u->name;
5932 UNISTR2 *uni_environment = &q_u->environment;
5933 uint32 level = q_u->level;
5934 NEW_BUFFER *buffer = NULL;
5935 uint32 offered = q_u->offered;
5936 uint32 *needed = &r_u->needed;
5938 /* that's an [in out] buffer */
5939 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5940 buffer = r_u->buffer;
5942 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5948 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5950 return WERR_UNKNOWN_LEVEL;
5954 /****************************************************************************
5955 ****************************************************************************/
5957 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
5959 POLICY_HND *handle = &q_u->handle;
5960 uint32 idx = q_u->index;
5961 uint32 in_value_len = q_u->valuesize;
5962 uint32 in_data_len = q_u->datasize;
5963 uint32 *out_max_value_len = &r_u->valuesize;
5964 uint16 **out_value = &r_u->value;
5965 uint32 *out_value_len = &r_u->realvaluesize;
5966 uint32 *out_type = &r_u->type;
5967 uint32 *out_max_data_len = &r_u->datasize;
5968 uint8 **data_out = &r_u->data;
5969 uint32 *out_data_len = &r_u->realdatasize;
5971 NT_PRINTER_INFO_LEVEL *printer = NULL;
5976 uint32 biggest_valuesize;
5977 uint32 biggest_datasize;
5979 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5985 ZERO_STRUCT(printer);
5989 *out_max_data_len=0;
5993 DEBUG(5,("spoolss_enumprinterdata\n"));
5996 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6000 if (!get_printer_snum(p,handle, &snum))
6003 result = get_a_printer(&printer, 2, lp_servicename(snum));
6004 if (!W_ERROR_IS_OK(result))
6008 * The NT machine wants to know the biggest size of value and data
6010 * cf: MSDN EnumPrinterData remark section
6012 if ( (in_value_len==0) && (in_data_len==0) ) {
6013 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6017 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6018 * if this parameter size doesn't exist.
6019 * Ok - my opinion here is that the client is not asking for the greatest
6020 * possible size of all the parameters, but is asking specifically for the size needed
6021 * for this specific parameter. In that case we can remove the loop below and
6022 * simplify this lookup code considerably. JF - comments welcome. JRA.
6025 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6027 free_a_printer(&printer, 2);
6028 return WERR_NO_MORE_ITEMS;
6035 biggest_valuesize=0;
6038 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6039 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6040 if (data_len > biggest_datasize) biggest_datasize=data_len;
6042 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6048 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6049 *out_value_len=2*(1+biggest_valuesize);
6050 *out_data_len=biggest_datasize;
6052 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6054 free_a_printer(&printer, 2);
6059 * the value len is wrong in NT sp3
6060 * that's the number of bytes not the number of unicode chars
6063 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6066 free_a_printer(&printer, 2);
6068 /* out_value should default to "" or else NT4 has
6069 problems unmarshalling the response */
6071 *out_max_value_len=(in_value_len/sizeof(uint16));
6072 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL)
6075 ZERO_STRUCTP(*out_value);
6076 *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
6078 /* the data is counted in bytes */
6079 *out_max_data_len = in_data_len;
6080 *out_data_len = in_data_len;
6081 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL)
6084 memset(*data_out,'\0',in_data_len);
6086 return WERR_NO_MORE_ITEMS;
6089 free_a_printer(&printer, 2);
6093 * - counted in bytes in the request
6094 * - counted in UNICODE chars in the max reply
6095 * - counted in bytes in the real size
6097 * take a pause *before* coding not *during* coding
6100 *out_max_value_len=(in_value_len/sizeof(uint16));
6101 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6106 *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6110 /* the data is counted in bytes */
6111 *out_max_data_len=in_data_len;
6112 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6117 memcpy(*data_out, data, (size_t)data_len);
6118 *out_data_len=data_len;
6125 /****************************************************************************
6126 ****************************************************************************/
6128 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6130 POLICY_HND *handle = &q_u->handle;
6131 UNISTR2 *value = &q_u->value;
6132 uint32 type = q_u->type;
6133 /* uint32 max_len = q_u->max_len; - notused. */
6134 uint8 *data = q_u->data;
6135 uint32 real_len = q_u->real_len;
6136 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6138 NT_PRINTER_INFO_LEVEL *printer = NULL;
6139 NT_PRINTER_PARAM *param = NULL, old_param;
6141 WERROR status = WERR_OK;
6142 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6144 DEBUG(5,("spoolss_setprinterdata\n"));
6147 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6151 if (!get_printer_snum(p,handle, &snum))
6154 ZERO_STRUCT(old_param);
6157 * Access check : NT returns "access denied" if you make a
6158 * SetPrinterData call without the necessary privildge.
6159 * we were originally returning OK if nothing changed
6160 * which made Win2k issue **a lot** of SetPrinterData
6161 * when connecting to a printer --jerry
6164 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6165 DEBUG(3, ("security descriptor change denied by existing "
6166 "security descriptor\n"));
6167 status = WERR_ACCESS_DENIED;
6171 /* Check if we are making any changes or not. Return true if
6172 nothing is actually changing. This is not needed anymore but
6173 has been left in as an optimization to keep from from
6174 writing to disk as often --jerry */
6176 status = get_a_printer(&printer, 2, lp_servicename(snum));
6177 if (!W_ERROR_IS_OK(status))
6180 convert_specific_param(¶m, value , type, data, real_len);
6183 if (get_specific_param(*printer, 2, param->value, &old_param.data,
6184 &old_param.type, (uint32 *)&old_param.data_len)) {
6186 if (param->type == old_param.type &&
6187 param->data_len == old_param.data_len &&
6188 memcmp(param->data, old_param.data,
6189 old_param.data_len) == 0) {
6191 DEBUG(3, ("setprinterdata hasn't changed\n"));
6197 unlink_specific_param_if_exist(printer->info_2, param);
6200 * When client side code sets a magic printer data key, detect it and save
6201 * the current printer data and the magic key's data (its the DEVMODE) for
6202 * future printer/driver initializations.
6204 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6206 * Set devmode and printer initialization info
6208 status = save_driver_init(printer, 2, param);
6211 add_a_specific_param(printer->info_2, ¶m);
6212 status = mod_a_printer(*printer, 2);
6216 free_a_printer(&printer, 2);
6218 free_nt_printer_param(¶m);
6219 SAFE_FREE(old_param.data);
6224 /****************************************************************************
6225 ****************************************************************************/
6227 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6229 POLICY_HND *handle = &q_u->handle;
6230 UNISTR2 *value = &q_u->valuename;
6232 NT_PRINTER_INFO_LEVEL *printer = NULL;
6233 NT_PRINTER_PARAM param;
6235 WERROR status = WERR_OK;
6236 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6238 DEBUG(5,("spoolss_deleteprinterdata\n"));
6241 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6245 if (!get_printer_snum(p, handle, &snum))
6248 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6249 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6250 "change denied by existing security descriptor\n"));
6251 return WERR_ACCESS_DENIED;
6254 status = get_a_printer(&printer, 2, lp_servicename(snum));
6255 if (!W_ERROR_IS_OK(status))
6258 ZERO_STRUCTP(¶m);
6259 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6261 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
6262 status = WERR_INVALID_PARAM;
6264 status = mod_a_printer(*printer, 2);
6266 free_a_printer(&printer, 2);
6270 /****************************************************************************
6271 ****************************************************************************/
6273 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6275 POLICY_HND *handle = &q_u->handle;
6276 /* uint32 level = q_u->level; - notused. */
6277 FORM *form = &q_u->form;
6278 nt_forms_struct tmpForm;
6281 nt_forms_struct *list=NULL;
6282 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6284 DEBUG(5,("spoolss_addform\n"));
6287 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6291 /* can't add if builtin */
6292 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6293 return WERR_INVALID_PARAM;
6296 count=get_ntforms(&list);
6297 if(!add_a_form(&list, form, &count))
6299 write_ntforms(&list, count);
6306 /****************************************************************************
6307 ****************************************************************************/
6309 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6311 POLICY_HND *handle = &q_u->handle;
6312 UNISTR2 *form_name = &q_u->name;
6313 nt_forms_struct tmpForm;
6315 WERROR ret = WERR_OK;
6316 nt_forms_struct *list=NULL;
6317 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6319 DEBUG(5,("spoolss_deleteform\n"));
6322 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6326 /* can't delete if builtin */
6327 if (get_a_builtin_ntform(form_name,&tmpForm)) {
6328 return WERR_INVALID_PARAM;
6331 count = get_ntforms(&list);
6332 if(!delete_a_form(&list, form_name, &count, &ret))
6333 return WERR_INVALID_PARAM;
6340 /****************************************************************************
6341 ****************************************************************************/
6343 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6345 POLICY_HND *handle = &q_u->handle;
6346 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6347 /* uint32 level = q_u->level; - notused. */
6348 FORM *form = &q_u->form;
6349 nt_forms_struct tmpForm;
6352 nt_forms_struct *list=NULL;
6353 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6355 DEBUG(5,("spoolss_setform\n"));
6358 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6361 /* can't set if builtin */
6362 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6363 return WERR_INVALID_PARAM;
6366 count=get_ntforms(&list);
6367 update_a_form(&list, form, count);
6368 write_ntforms(&list, count);
6375 /****************************************************************************
6376 enumprintprocessors level 1.
6377 ****************************************************************************/
6378 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6380 PRINTPROCESSOR_1 *info_1=NULL;
6382 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6387 init_unistr(&info_1->name, "winprint");
6389 *needed += spoolss_size_printprocessor_info_1(info_1);
6391 if (!alloc_buffer_size(buffer, *needed))
6392 return WERR_INSUFFICIENT_BUFFER;
6394 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6398 if (*needed > offered) {
6400 return WERR_INSUFFICIENT_BUFFER;
6406 /****************************************************************************
6407 ****************************************************************************/
6409 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6411 /* UNISTR2 *name = &q_u->name; - notused. */
6412 /* UNISTR2 *environment = &q_u->environment; - notused. */
6413 uint32 level = q_u->level;
6414 NEW_BUFFER *buffer = NULL;
6415 uint32 offered = q_u->offered;
6416 uint32 *needed = &r_u->needed;
6417 uint32 *returned = &r_u->returned;
6419 /* that's an [in out] buffer */
6420 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6421 buffer = r_u->buffer;
6423 DEBUG(5,("spoolss_enumprintprocessors\n"));
6426 * Enumerate the print processors ...
6428 * Just reply with "winprint", to keep NT happy
6429 * and I can use my nice printer checker.
6437 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6439 return WERR_UNKNOWN_LEVEL;
6443 /****************************************************************************
6444 enumprintprocdatatypes level 1.
6445 ****************************************************************************/
6446 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6448 PRINTPROCDATATYPE_1 *info_1=NULL;
6450 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6455 init_unistr(&info_1->name, "RAW");
6457 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6459 if (!alloc_buffer_size(buffer, *needed))
6460 return WERR_INSUFFICIENT_BUFFER;
6462 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6466 if (*needed > offered) {
6468 return WERR_INSUFFICIENT_BUFFER;
6474 /****************************************************************************
6475 ****************************************************************************/
6477 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6479 /* UNISTR2 *name = &q_u->name; - notused. */
6480 /* UNISTR2 *processor = &q_u->processor; - notused. */
6481 uint32 level = q_u->level;
6482 NEW_BUFFER *buffer = NULL;
6483 uint32 offered = q_u->offered;
6484 uint32 *needed = &r_u->needed;
6485 uint32 *returned = &r_u->returned;
6487 /* that's an [in out] buffer */
6488 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6489 buffer = r_u->buffer;
6491 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6498 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6500 return WERR_UNKNOWN_LEVEL;
6504 /****************************************************************************
6505 enumprintmonitors level 1.
6506 ****************************************************************************/
6508 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6510 PRINTMONITOR_1 *info_1=NULL;
6512 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6517 init_unistr(&info_1->name, "Local Port");
6519 *needed += spoolss_size_printmonitor_info_1(info_1);
6521 if (!alloc_buffer_size(buffer, *needed))
6522 return WERR_INSUFFICIENT_BUFFER;
6524 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6528 if (*needed > offered) {
6530 return WERR_INSUFFICIENT_BUFFER;
6536 /****************************************************************************
6537 enumprintmonitors level 2.
6538 ****************************************************************************/
6539 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6541 PRINTMONITOR_2 *info_2=NULL;
6543 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6548 init_unistr(&info_2->name, "Local Port");
6549 init_unistr(&info_2->environment, "Windows NT X86");
6550 init_unistr(&info_2->dll_name, "localmon.dll");
6552 *needed += spoolss_size_printmonitor_info_2(info_2);
6554 if (!alloc_buffer_size(buffer, *needed))
6555 return WERR_INSUFFICIENT_BUFFER;
6557 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6561 if (*needed > offered) {
6563 return WERR_INSUFFICIENT_BUFFER;
6569 /****************************************************************************
6570 ****************************************************************************/
6572 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6574 /* UNISTR2 *name = &q_u->name; - notused. */
6575 uint32 level = q_u->level;
6576 NEW_BUFFER *buffer = NULL;
6577 uint32 offered = q_u->offered;
6578 uint32 *needed = &r_u->needed;
6579 uint32 *returned = &r_u->returned;
6581 /* that's an [in out] buffer */
6582 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6583 buffer = r_u->buffer;
6585 DEBUG(5,("spoolss_enumprintmonitors\n"));
6588 * Enumerate the print monitors ...
6590 * Just reply with "Local Port", to keep NT happy
6591 * and I can use my nice printer checker.
6599 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6601 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6603 return WERR_UNKNOWN_LEVEL;
6607 /****************************************************************************
6608 ****************************************************************************/
6609 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6613 JOB_INFO_1 *info_1=NULL;
6615 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6617 if (info_1 == NULL) {
6622 for (i=0; i<count && found==False; i++) {
6623 if (queue[i].job==(int)jobid)
6630 /* NT treats not found as bad param... yet another bad choice */
6631 return WERR_INVALID_PARAM;
6634 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6638 *needed += spoolss_size_job_info_1(info_1);
6640 if (!alloc_buffer_size(buffer, *needed)) {
6642 return WERR_INSUFFICIENT_BUFFER;
6645 smb_io_job_info_1("", buffer, info_1, 0);
6649 if (*needed > offered)
6650 return WERR_INSUFFICIENT_BUFFER;
6656 /****************************************************************************
6657 ****************************************************************************/
6658 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6663 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6666 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6668 ZERO_STRUCTP(info_2);
6670 if (info_2 == NULL) {
6675 for (i=0; i<count && found==False; i++) {
6676 if (queue[i].job==(int)jobid)
6683 /* NT treats not found as bad param... yet another bad choice */
6684 return WERR_INVALID_PARAM;
6687 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6688 if (!W_ERROR_IS_OK(ret)) {
6693 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6695 free_a_printer(&ntprinter, 2);
6698 *needed += spoolss_size_job_info_2(info_2);
6700 if (!alloc_buffer_size(buffer, *needed)) {
6702 return WERR_INSUFFICIENT_BUFFER;
6705 smb_io_job_info_2("", buffer, info_2, 0);
6707 free_job_info_2(info_2);
6710 if (*needed > offered)
6711 return WERR_INSUFFICIENT_BUFFER;
6716 /****************************************************************************
6717 ****************************************************************************/
6719 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6721 POLICY_HND *handle = &q_u->handle;
6722 uint32 jobid = q_u->jobid;
6723 uint32 level = q_u->level;
6724 NEW_BUFFER *buffer = NULL;
6725 uint32 offered = q_u->offered;
6726 uint32 *needed = &r_u->needed;
6730 print_queue_struct *queue=NULL;
6731 print_status_struct prt_status;
6733 /* that's an [in out] buffer */
6734 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6735 buffer = r_u->buffer;
6737 DEBUG(5,("spoolss_getjob\n"));
6741 if (!get_printer_snum(p, handle, &snum))
6744 count = print_queue_status(snum, &queue, &prt_status);
6746 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6747 count, prt_status.status, prt_status.message));
6751 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6753 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6756 return WERR_UNKNOWN_LEVEL;
6760 /********************************************************************
6761 * spoolss_getprinterdataex
6762 ********************************************************************/
6764 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
6766 POLICY_HND *handle = &q_u->handle;
6767 uint32 in_size = q_u->size;
6768 uint32 *type = &r_u->type;
6769 uint32 *out_size = &r_u->size;
6770 uint8 **data = &r_u->data;
6771 uint32 *needed = &r_u->needed;
6774 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6777 DEBUG(4,("_spoolss_getprinterdataex\n"));
6779 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
6780 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
6782 /* in case of problem, return some default values */
6789 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
6791 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6796 /* Is the handle to a printer or to the server? */
6798 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6800 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
6801 return WERR_INVALID_PARAM;
6806 * From MSDN documentation of GetPrinterDataEx: pass request
6807 * to GetPrinterData if key is "PrinterDriverData". This is
6808 * the only key we really support. Other keys to implement:
6814 if (strcmp(key, "PrinterDriverData") != 0)
6815 return WERR_INVALID_PARAM;
6817 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
6818 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
6819 type, data, needed, in_size);
6824 DEBUG(5, ("value not found, allocating %d\n", *out_size));
6826 /* reply this param doesn't exist */
6828 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
6834 return WERR_INVALID_PARAM;
6837 if (*needed > *out_size)
6838 return WERR_MORE_DATA;
6843 /********************************************************************
6844 * spoolss_setprinterdata
6845 ********************************************************************/
6847 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
6849 SPOOL_Q_SETPRINTERDATA q_u_local;
6850 SPOOL_R_SETPRINTERDATA r_u_local;
6853 DEBUG(4,("_spoolss_setprinterdataex\n"));
6855 /* From MSDN documentation of SetPrinterDataEx: pass request to
6856 SetPrinterData if key is "PrinterDriverData" */
6858 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6860 if (strcmp(key, "PrinterDriverData") == 0)
6861 return WERR_INVALID_PARAM;
6863 ZERO_STRUCT(q_u_local);
6864 ZERO_STRUCT(r_u_local);
6866 /* make a copy to call _spoolss_setprinterdata() */
6868 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
6869 copy_unistr2(&q_u_local.value, &q_u->value);
6870 q_u_local.type = q_u->type;
6871 q_u_local.max_len = q_u->max_len;
6872 q_u_local.data = q_u->data;
6873 q_u_local.real_len = q_u->real_len;
6874 q_u_local.numeric_data = q_u->numeric_data;
6876 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
6879 /********************************************************************
6880 * spoolss_enumprinterkey
6881 ********************************************************************/
6883 /* constants for EnumPrinterKey() */
6884 #define ENUMERATED_KEY_SIZE 19
6886 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
6889 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
6892 char *PrinterKey = "PrinterDriverData";
6894 DEBUG(4,("_spoolss_enumprinterkey\n"));
6896 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6899 * we only support enumating all keys (key == "")
6900 * Of course, the only key we support is the "PrinterDriverData"
6903 if (strlen(key) == 0)
6905 r_u->needed = ENUMERATED_KEY_SIZE *2;
6906 if (q_u->size < r_u->needed)
6907 return WERR_MORE_DATA;
6910 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
6912 enumkeys[i] = (uint16)(*ptr);
6916 /* tag of with 2 '\0's */
6917 enumkeys[i++] = '\0';
6920 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
6921 return WERR_BADFILE;
6926 /* The "PrinterDriverData" key should have no subkeys */
6927 if (strcmp(key, PrinterKey) == 0)
6930 if (q_u->size < r_u->needed)
6931 return WERR_MORE_DATA;
6933 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
6934 return WERR_BADFILE;
6940 /* The return value for an unknown key is documented in MSDN
6941 EnumPrinterKey description */
6942 return WERR_BADFILE;
6945 /********************************************************************
6946 * spoolss_enumprinterdataex
6947 ********************************************************************/
6949 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
6951 POLICY_HND *handle = &q_u->handle;
6952 uint32 in_size = q_u->size;
6955 NT_PRINTER_INFO_LEVEL *printer = NULL;
6956 PRINTER_ENUM_VALUES *enum_values = NULL;
6958 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6967 DEBUG(4,("_spoolss_enumprinterdataex\n"));
6970 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6976 * The only key we support is "PrinterDriverData". This should return
6977 > an array of all the key/value pairs returned by EnumPrinterDataSee
6978 * _spoolss_getprinterdataex() for details --jerry
6981 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6982 if (strcmp(key, "PrinterDriverData") != 0)
6984 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
6985 return WERR_INVALID_PARAM;
6989 if (!get_printer_snum(p,handle, &snum))
6992 ZERO_STRUCT(printer);
6993 result = get_a_printer(&printer, 2, lp_servicename(snum));
6994 if (!W_ERROR_IS_OK(result))
6999 * loop through all params and build the array to pass
7000 * back to the client
7007 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
7009 PRINTER_ENUM_VALUES *ptr;
7012 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7014 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7016 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7017 result = WERR_NOMEM;
7023 init_unistr(&enum_values[num_entries].valuename, value);
7024 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7025 enum_values[num_entries].type = type;
7028 * NULL terminate REG_SZ
7029 * FIXME!!! We should not be correctly problems in the way
7030 * we store PrinterData here. Need to investogate
7031 * SetPrinterData[Ex] --jerry
7034 if (type == REG_SZ) {
7035 /* fix alignment if the string was stored
7036 in a bizarre fashion */
7037 if ((data_len % 2) == 0)
7040 add_len = data_len % 2;
7043 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7044 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7045 result = WERR_NOMEM;
7048 memcpy(enum_values[num_entries].data, data, data_len);
7049 enum_values[num_entries].data_len = data_len + add_len;
7051 /* keep track of the size of the array in bytes */
7053 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7059 r_u->needed = needed;
7060 r_u->returned = num_entries;
7062 if (needed > in_size) {
7063 result = WERR_MORE_DATA;
7067 /* copy data into the reply */
7069 r_u->ctr.size = r_u->needed;
7070 r_u->ctr.size_of_array = r_u->returned;
7071 r_u->ctr.values = enum_values;
7076 free_a_printer(&printer, 2);
7081 /****************************************************************************
7082 ****************************************************************************/
7084 /* Disabled because it doesn't fix the bug I am looking at but it would be
7085 a shame to throw away the code. -tpot */
7089 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
7091 init_unistr(&info->name, name);
7094 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
7095 UNISTR2 *environment,
7102 pstring short_archi;
7103 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
7105 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
7107 if (get_short_archi(short_archi, long_archi)==FALSE)
7108 return WERR_INVALID_ENVIRONMENT;
7110 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
7113 /* Not sure what to return here - are UNC names valid here?.
7114 Windows returns the string: C:\WINNT\System32\spool\PRTPROCS\W32X86
7115 which is pretty bogus for a RPC. */
7117 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
7119 DEBUG(4,("print processor directory: [%s]\n", path));
7121 fill_printprocessordirectory_1(info, path);
7123 *needed += spoolss_size_printprocessordirectory_info_1(info);
7125 if (!alloc_buffer_size(buffer, *needed)) {
7127 return WERR_INSUFFICIENT_BUFFER;
7130 smb_io_printprocessordirectory_1("", buffer, info, 0);
7134 if (*needed > offered)
7135 return WERR_INSUFFICIENT_BUFFER;
7140 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
7142 uint32 level = q_u->level;
7143 NEW_BUFFER *buffer = NULL;
7144 uint32 offered = q_u->offered;
7145 uint32 *needed = &r_u->needed;
7147 /* that's an [in out] buffer */
7148 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7149 buffer = r_u->buffer;
7151 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7157 return getprintprocessordirectory_level_1
7158 (&q_u->name, &q_u->environment, buffer, offered, needed);
7160 return WERR_UNKNOWN_LEVEL;
7163 return WERR_ACCESS_DENIED;