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.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 #ifndef MAX_OPEN_PRINTER_EXS
32 #define MAX_OPEN_PRINTER_EXS 50
35 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
36 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
37 #define PRINTER_HANDLE_IS_PRINTER 0
38 #define PRINTER_HANDLE_IS_PRINTSERVER 1
47 /* structure to store the printer handles */
48 /* and a reference to what it's pointing to */
49 /* and the notify info asked about */
50 /* that's the central struct */
51 typedef struct _Printer{
52 struct _Printer *prev, *next;
53 BOOL document_started;
55 int jobid; /* jobid in printing backend */
59 fstring printerservername;
68 SPOOL_NOTIFY_OPTION *option;
69 POLICY_HND client_hnd;
70 uint32 client_connected;
78 static Printer_entry *printers_list;
80 typedef struct _counter_printer_0 {
88 static ubi_dlList counter_list;
90 static struct cli_state cli;
91 static uint32 smb_connections=0;
93 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
94 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
96 /* translate between internal status numbers and NT status numbers */
97 static int nt_printj_status(int v)
103 return JOB_STATUS_PAUSED;
105 return JOB_STATUS_SPOOLING;
107 return JOB_STATUS_PRINTING;
109 return JOB_STATUS_ERROR;
111 return JOB_STATUS_DELETING;
113 return JOB_STATUS_OFFLINE;
115 return JOB_STATUS_PAPEROUT;
117 return JOB_STATUS_PRINTED;
119 return JOB_STATUS_DELETED;
121 return JOB_STATUS_BLOCKED;
122 case LPQ_USER_INTERVENTION:
123 return JOB_STATUS_USER_INTERVENTION;
128 static int nt_printq_status(int v)
132 return PRINTER_STATUS_PAUSED;
141 /****************************************************************************
142 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
143 ****************************************************************************/
145 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
150 SAFE_FREE((*pp)->ctr.type);
154 /***************************************************************************
155 Disconnect from the client
156 ****************************************************************************/
158 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
162 /* weird if the test succeds !!! */
163 if (smb_connections==0) {
164 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
168 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
169 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
171 /* if it's the last connection, deconnect the IPC$ share */
172 if (smb_connections==1) {
173 if(!spoolss_disconnect_from_client(&cli))
176 message_deregister(MSG_PRINTER_NOTIFY);
182 /****************************************************************************
183 Functions to free a printer entry datastruct.
184 ****************************************************************************/
186 static void free_printer_entry(void *ptr)
188 Printer_entry *Printer = (Printer_entry *)ptr;
190 if (Printer->notify.client_connected==True)
191 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
193 Printer->notify.flags=0;
194 Printer->notify.options=0;
195 Printer->notify.localmachine[0]='\0';
196 Printer->notify.printerlocal=0;
197 free_spool_notify_option(&Printer->notify.option);
198 Printer->notify.option=NULL;
199 Printer->notify.client_connected=False;
201 /* Remove from the internal list. */
202 DLIST_REMOVE(printers_list, Printer);
207 /****************************************************************************
208 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
209 ****************************************************************************/
211 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
213 SPOOL_NOTIFY_OPTION *new_sp = NULL;
218 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
225 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
227 if (!new_sp->ctr.type) {
236 /****************************************************************************
237 find printer index by handle
238 ****************************************************************************/
240 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
242 Printer_entry *find_printer = NULL;
244 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
245 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
252 /****************************************************************************
253 Close printer index by handle.
254 ****************************************************************************/
256 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
258 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
261 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
265 close_policy_hnd(p, hnd);
270 /****************************************************************************
271 Delete a printer given a handle.
272 ****************************************************************************/
274 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
276 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
279 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
283 if (del_a_printer(Printer->dev.handlename) != 0) {
284 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
288 /* Check calling user has permission to delete printer. Note that
289 since we set the snum parameter to -1 only administrators can
290 delete the printer. This stops people with the Full Control
291 permission from deleting the printer. */
293 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
294 DEBUG(3, ("printer delete denied by security descriptor\n"));
295 return WERR_ACCESS_DENIED;
298 if (*lp_deleteprinter_cmd()) {
300 char *cmd = lp_deleteprinter_cmd();
305 /* Printer->dev.handlename equals portname equals sharename */
306 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
307 Printer->dev.handlename);
309 DEBUG(10,("Running [%s]\n", command));
310 ret = smbrun(command, NULL);
312 return WERR_BADFID; /* What to return here? */
314 DEBUGADD(10,("returned [%d]\n", ret));
316 /* Send SIGHUP to process group... is there a better way? */
319 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
323 return WERR_ACCESS_DENIED;
329 /****************************************************************************
330 return the snum of a printer corresponding to an handle
331 ****************************************************************************/
332 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
334 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
337 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
341 switch (Printer->printer_type) {
342 case PRINTER_HANDLE_IS_PRINTER:
343 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
344 *number = print_queue_snum(Printer->dev.handlename);
345 return (*number != -1);
346 case PRINTER_HANDLE_IS_PRINTSERVER:
353 /****************************************************************************
354 set printer handle type.
355 ****************************************************************************/
356 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
358 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
361 DEBUG(2,("set_printer_hnd_accesstype: Invalid handle (%s:%u:%u)", OUR_HANDLE(hnd)));
365 DEBUG(4,("Setting printer access=%x\n", access_required));
366 Printer->access = access_required;
370 /****************************************************************************
371 Set printer handle type.
372 Check if it's \\server or \\server\printer
373 ****************************************************************************/
375 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
377 DEBUG(3,("Setting printer type=%s\n", handlename));
379 if ( strlen(handlename) < 3 ) {
380 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
384 /* it's a print server */
385 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
386 DEBUGADD(4,("Printer is a print server\n"));
387 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
391 DEBUGADD(4,("Printer is a printer\n"));
392 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
398 /****************************************************************************
399 Set printer handle name.
400 ****************************************************************************/
402 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
404 NT_PRINTER_INFO_LEVEL *printer = NULL;
406 int n_services=lp_numservices();
410 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
412 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
413 ZERO_STRUCT(Printer->dev.printerservername);
414 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
418 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
421 if (*handlename=='\\') {
422 aprinter=strchr_m(handlename+2, '\\');
429 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
432 * store the Samba share name in it
433 * in back we have the long printer name
434 * need to iterate all the snum and do a
435 * get_a_printer each time to find the printer
436 * faster to do it here than later.
439 for (snum=0;snum<n_services && found==False;snum++) {
442 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
445 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
447 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
450 printername=strchr_m(printer->info_2->printername+2, '\\');
453 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
454 printer->info_2->printername, aprinter ));
456 if ( strlen(printername) != strlen(aprinter) ) {
457 free_a_printer(&printer, 2);
461 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
462 free_a_printer(&printer, 2);
470 * if we haven't found a printer with the given handlename
471 * then it can be a share name as you can open both \\server\printer and
476 * we still check if the printer description file exists as NT won't be happy
477 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
481 DEBUGADD(5,("Printer not found, checking for share now\n"));
483 for (snum=0;snum<n_services && found==False;snum++) {
485 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
488 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
490 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
493 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
494 printer->info_2->printername, aprinter ));
496 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
497 free_a_printer(&printer, 2);
501 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
502 free_a_printer(&printer, 2);
511 DEBUGADD(4,("Printer not found\n"));
516 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
517 printer->info_2->printername, lp_servicename(snum),snum));
519 ZERO_STRUCT(Printer->dev.handlename);
520 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
522 free_a_printer(&printer, 2);
527 /****************************************************************************
528 find first available printer slot. creates a printer handle for you.
529 ****************************************************************************/
531 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
533 Printer_entry *new_printer;
535 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
537 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
540 ZERO_STRUCTP(new_printer);
542 new_printer->notify.option=NULL;
544 /* Add to the internal list. */
545 DLIST_ADD(printers_list, new_printer);
547 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
548 SAFE_FREE(new_printer);
552 if (!set_printer_hnd_printertype(new_printer, name)) {
553 close_printer_handle(p, hnd);
557 if (!set_printer_hnd_name(new_printer, name)) {
558 close_printer_handle(p, hnd);
562 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
567 /********************************************************************
568 Return True if the handle is a print server.
569 ********************************************************************/
571 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
573 Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
578 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
584 /****************************************************************************
585 allocate more memory for a BUFFER.
586 ****************************************************************************/
587 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
595 /* damn, I'm doing the reverse operation of prs_grow() :) */
596 if (buffer_size < prs_data_size(ps))
599 extra_space = buffer_size - prs_data_size(ps);
602 * save the offset and move to the end of the buffer
603 * prs_grow() checks the extra_space against the offset
605 old_offset=prs_offset(ps);
606 prs_set_offset(ps, prs_data_size(ps));
608 if (!prs_grow(ps, extra_space))
611 prs_set_offset(ps, old_offset);
613 buffer->string_at_end=prs_data_size(ps);
618 /***************************************************************************
619 Receive the notify message.
620 ****************************************************************************/
622 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
624 Printer_entry *find_printer;
629 if (len != sizeof(msg)) {
630 DEBUG(2,("srv_spoolss_receive_message: got incorrect message size (%u)!\n", (unsigned int)len));
634 memcpy(msg, buf, len);
638 DEBUG(10,("srv_spoolss_receive_message: Got message printer change low=0x%x high=0x%x\n", (unsigned int)low,
639 (unsigned int)high ));
641 find_printer = printers_list;
643 /* Iterate the printer list */
644 for(; find_printer; find_printer = find_printer->next) {
647 * If the entry has a connected client we send the message.
651 if (find_printer->notify.client_connected==True) {
652 DEBUG(10,("srv_spoolss_receive_message: printerserver [%s]\n", find_printer->dev.printerservername ));
653 if (cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, low, high, &status))
654 DEBUG(10,("srv_spoolss_receive_message: cli_spoolss_reply_rrpcn status = 0x%x\n",
655 (unsigned int)W_ERROR_V(status)));
657 DEBUG(10,("srv_spoolss_receive_message: cli_spoolss_reply_rrpcn failed\n"));
662 /***************************************************************************
664 ****************************************************************************/
666 static BOOL srv_spoolss_sendnotify(uint32 high, uint32 low)
672 DEBUG(10,("srv_spoolss_sendnotify: printer change low=0x%x high=0x%x\n", low, high));
674 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, msg, sizeof(msg), False, NULL);
678 /********************************************************************
679 * spoolss_open_printer
681 * called from the spoolss dispatcher
682 ********************************************************************/
684 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
687 WERROR result = WERR_OK;
690 UNISTR2 *printername = NULL;
691 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
692 /* uint32 user_switch = q_u->user_switch; - notused */
693 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
694 POLICY_HND *handle = &r_u->handle;
698 struct current_user user;
700 if (q_u->printername_ptr != 0)
701 printername = &q_u->printername;
703 if (printername == NULL)
704 return WERR_INVALID_PRINTER_NAME;
706 /* some sanity check because you can open a printer or a print server */
707 /* aka: \\server\printer or \\server */
708 unistr2_to_ascii(name, printername, sizeof(name)-1);
710 DEBUGADD(3,("checking name: %s\n",name));
712 if (!open_printer_hnd(p, handle, name))
713 return WERR_INVALID_PRINTER_NAME;
716 if (printer_default->datatype_ptr != NULL)
718 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
719 set_printer_hnd_datatype(handle, datatype);
722 set_printer_hnd_datatype(handle, "");
725 if (!set_printer_hnd_accesstype(p, handle, printer_default->access_required)) {
726 close_printer_handle(p, handle);
727 return WERR_ACCESS_DENIED;
731 First case: the user is opening the print server:
733 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
734 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
736 Then both Win2k and WinNT clients try an OpenPrinterEx with
737 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
738 or if the user is listed in the smb.conf printer admin parameter.
740 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
741 client view printer folder, but does not show the MSAPW.
743 Note: this test needs code to check access rights here too. Jeremy
744 could you look at this?
747 Second case: the user is opening a printer:
748 NT doesn't let us connect to a printer if the connecting user
749 doesn't have print permission.
753 get_current_user(&user, p);
755 if (handle_is_printserver(p, handle)) {
756 if (printer_default->access_required == 0) {
759 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
761 /* Printserver handles use global struct... */
764 if (!lp_ms_add_printer_wizard()) {
765 close_printer_handle(p, handle);
766 return WERR_ACCESS_DENIED;
768 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
772 close_printer_handle(p, handle);
773 return WERR_ACCESS_DENIED;
779 /* NT doesn't let us connect to a printer if the connecting user
780 doesn't have print permission. */
782 if (!get_printer_snum(p, handle, &snum))
785 /* map an empty access mask to the minimum access mask */
786 if (printer_default->access_required == 0x0)
787 printer_default->access_required = PRINTER_ACCESS_USE;
791 * If we are not serving the printer driver for this printer,
792 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
793 * will keep NT clients happy --jerry
796 if (lp_use_client_driver(snum)
797 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
799 printer_default->access_required = PRINTER_ACCESS_USE;
802 if (!print_access_check(&user, snum, printer_default->access_required)) {
803 DEBUG(3, ("access DENIED for printer open\n"));
804 close_printer_handle(p, handle);
805 return WERR_ACCESS_DENIED;
809 * If we have a default device pointer in the
810 * printer_default struct, then we need to get
811 * the printer info from the tdb and if there is
812 * no default devicemode there then we do a *SET*
813 * here ! This is insanity.... JRA.
817 * If the openprinterex rpc call contains a devmode,
818 * it's a per-user one. This per-user devmode is derivated
819 * from the global devmode. Openprinterex() contains a per-user
820 * devmode for when you do EMF printing and spooling.
821 * In the EMF case, the NT workstation is only doing half the job
822 * of rendering the page. The other half is done by running the printer
823 * driver on the server.
824 * The EMF file doesn't contain the page description (paper size, orientation, ...).
825 * The EMF file only contains what is to be printed on the page.
826 * So in order for the server to know how to print, the NT client sends
827 * a devicemode attached to the openprinterex call.
828 * But this devicemode is short lived, it's only valid for the current print job.
830 * If Samba would have supported EMF spooling, this devicemode would
831 * have been attached to the handle, to sent it to the driver to correctly
832 * rasterize the EMF file.
834 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
835 * we just act as a pass-thru between windows and the printer.
837 * In order to know that Samba supports only RAW spooling, NT has to call
838 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
839 * and until NT sends a RAW job, we refuse it.
841 * But to call getprinter() or startdoc(), you first need a valid handle,
842 * and to get an handle you have to call openprintex(). Hence why you have
843 * a devicemode in the openprinterex() call.
846 * Differences between NT4 and NT 2000.
849 * On NT4, you only have a global devicemode. This global devicemode can be changed
850 * by the administrator (or by a user with enough privs). Everytime a user
851 * wants to print, the devicemode is resetted to the default. In Word, everytime
852 * you print, the printer's characteristics are always reset to the global devicemode.
856 * In W2K, there is the notion of per-user devicemode. The first time you use
857 * a printer, a per-user devicemode is build from the global devicemode.
858 * If you change your per-user devicemode, it is saved in the registry, under the
859 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
860 * printer preferences available.
862 * To change the per-user devicemode: it's the "Printing Preferences ..." button
863 * on the General Tab of the printer properties windows.
865 * To change the global devicemode: it's the "Printing Defaults..." button
866 * on the Advanced Tab of the printer properties window.
874 if (printer_default->devmode_cont.devmode != NULL) {
875 result = printer_write_default_dev( snum, printer_default);
877 close_printer_handle(p, handle);
887 /****************************************************************************
888 ****************************************************************************/
889 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
890 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
896 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
905 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
906 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
912 printer->info_3=NULL;
913 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
917 printer->info_6=NULL;
918 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
928 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
929 NT_DEVICEMODE **pp_nt_devmode)
931 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
934 * Ensure nt_devmode is a valid pointer
935 * as we will be overwriting it.
938 if (nt_devmode == NULL) {
939 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
940 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
944 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
945 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
947 nt_devmode->specversion=devmode->specversion;
948 nt_devmode->driverversion=devmode->driverversion;
949 nt_devmode->size=devmode->size;
950 nt_devmode->fields=devmode->fields;
951 nt_devmode->orientation=devmode->orientation;
952 nt_devmode->papersize=devmode->papersize;
953 nt_devmode->paperlength=devmode->paperlength;
954 nt_devmode->paperwidth=devmode->paperwidth;
955 nt_devmode->scale=devmode->scale;
956 nt_devmode->copies=devmode->copies;
957 nt_devmode->defaultsource=devmode->defaultsource;
958 nt_devmode->printquality=devmode->printquality;
959 nt_devmode->color=devmode->color;
960 nt_devmode->duplex=devmode->duplex;
961 nt_devmode->yresolution=devmode->yresolution;
962 nt_devmode->ttoption=devmode->ttoption;
963 nt_devmode->collate=devmode->collate;
965 nt_devmode->logpixels=devmode->logpixels;
966 nt_devmode->bitsperpel=devmode->bitsperpel;
967 nt_devmode->pelswidth=devmode->pelswidth;
968 nt_devmode->pelsheight=devmode->pelsheight;
969 nt_devmode->displayflags=devmode->displayflags;
970 nt_devmode->displayfrequency=devmode->displayfrequency;
971 nt_devmode->icmmethod=devmode->icmmethod;
972 nt_devmode->icmintent=devmode->icmintent;
973 nt_devmode->mediatype=devmode->mediatype;
974 nt_devmode->dithertype=devmode->dithertype;
975 nt_devmode->reserved1=devmode->reserved1;
976 nt_devmode->reserved2=devmode->reserved2;
977 nt_devmode->panningwidth=devmode->panningwidth;
978 nt_devmode->panningheight=devmode->panningheight;
981 * Only change private and driverextra if the incoming devmode
982 * has a new one. JRA.
985 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
986 SAFE_FREE(nt_devmode->private);
987 nt_devmode->driverextra=devmode->driverextra;
988 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
990 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
993 *pp_nt_devmode = nt_devmode;
998 /********************************************************************
999 * _spoolss_enddocprinter_internal.
1000 ********************************************************************/
1002 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1004 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1007 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1011 Printer->document_started=False;
1012 print_job_end(Printer->jobid,True);
1013 /* error codes unhandled so far ... */
1018 /********************************************************************
1019 * api_spoolss_closeprinter
1020 ********************************************************************/
1022 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1024 POLICY_HND *handle = &q_u->handle;
1026 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1028 if (Printer && Printer->document_started)
1029 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1031 if (!close_printer_handle(p, handle))
1034 /* clear the returned printer handle. Observed behavior
1035 from Win2k server. Don't think this really matters.
1036 Previous code just copied the value of the closed
1039 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1044 /********************************************************************
1045 * api_spoolss_deleteprinter
1047 ********************************************************************/
1049 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1051 POLICY_HND *handle = &q_u->handle;
1052 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1055 if (Printer && Printer->document_started)
1056 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1058 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1060 result = delete_printer_handle(p, handle);
1062 update_c_setprinter(FALSE);
1064 if (W_ERROR_IS_OK(result)) {
1065 srv_spoolss_sendnotify(0, PRINTER_CHANGE_DELETE_PRINTER);
1071 /*******************************************************************
1072 * static function to lookup the version id corresponding to an
1073 * long architecture string
1074 ******************************************************************/
1075 static int get_version_id (char * arch)
1078 struct table_node archi_table[]= {
1080 {"Windows 4.0", "WIN40", 0 },
1081 {"Windows NT x86", "W32X86", 2 },
1082 {"Windows NT R4000", "W32MIPS", 2 },
1083 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1084 {"Windows NT PowerPC", "W32PPC", 2 },
1088 for (i=0; archi_table[i].long_archi != NULL; i++)
1090 if (strcmp(arch, archi_table[i].long_archi) == 0)
1091 return (archi_table[i].version);
1097 /********************************************************************
1098 * _spoolss_deleteprinterdriver
1100 * We currently delete the driver for the architecture only.
1101 * This can leave the driver for other archtectures. However,
1102 * since every printer associates a "Windows NT x86" driver name
1103 * and we cannot delete that one while it is in use, **and** since
1104 * it is impossible to assign a driver to a Samba printer without
1105 * having the "Windows NT x86" driver installed,...
1107 * ....we should not get into trouble here.
1110 ********************************************************************/
1112 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
1113 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1117 NT_PRINTER_DRIVER_INFO_LEVEL info;
1120 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1121 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1123 /* check that we have a valid driver name first */
1124 if ((version=get_version_id(arch)) == -1) {
1125 /* this is what NT returns */
1126 return WERR_INVALID_ENVIRONMENT;
1130 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1131 return WERR_UNKNOWN_PRINTER_DRIVER;
1135 if (printer_driver_in_use(arch, driver))
1137 return WERR_PRINTER_DRIVER_IN_USE;
1140 return delete_printer_driver(info.info_3);
1144 /********************************************************************
1145 GetPrinterData on a printer server Handle.
1146 ********************************************************************/
1147 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1151 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1153 if (!strcmp(value, "W3SvcInstalled")) {
1155 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
1161 if (!strcmp(value, "BeepEnabled")) {
1163 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1165 SIVAL(*data, 0, 0x01);
1170 if (!strcmp(value, "EventLog")) {
1172 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1174 SIVAL(*data, 0, 0x1B);
1179 if (!strcmp(value, "NetPopup")) {
1181 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1183 SIVAL(*data, 0, 0x01);
1188 if (!strcmp(value, "MajorVersion")) {
1190 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1192 SIVAL(*data, 0, 0x02);
1197 if (!strcmp(value, "DefaultSpoolDirectory")) {
1198 pstring string="You are using a Samba server";
1200 *needed = 2*(strlen(string)+1);
1201 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1203 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1205 /* it's done by hand ready to go on the wire */
1206 for (i=0; i<strlen(string); i++) {
1207 (*data)[2*i]=string[i];
1208 (*data)[2*i+1]='\0';
1213 if (!strcmp(value, "Architecture")) {
1214 pstring string="Windows NT x86";
1216 *needed = 2*(strlen(string)+1);
1217 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1219 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1220 for (i=0; i<strlen(string); i++) {
1221 (*data)[2*i]=string[i];
1222 (*data)[2*i+1]='\0';
1230 /********************************************************************
1231 GetPrinterData on a printer Handle.
1232 ********************************************************************/
1233 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1234 fstring value, uint32 *type,
1235 uint8 **data, uint32 *needed, uint32 in_size )
1237 NT_PRINTER_INFO_LEVEL *printer = NULL;
1241 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1243 DEBUG(5,("getprinterdata_printer\n"));
1246 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1250 if(!get_printer_snum(p, handle, &snum))
1253 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1256 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1257 free_a_printer(&printer, 2);
1261 free_a_printer(&printer, 2);
1263 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1266 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1270 memset(*data, 0, in_size *sizeof(uint8));
1271 /* copy the min(in_size, len) */
1272 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1279 DEBUG(5,("getprinterdata_printer:copy done\n"));
1286 /********************************************************************
1287 * spoolss_getprinterdata
1288 ********************************************************************/
1290 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1292 POLICY_HND *handle = &q_u->handle;
1293 UNISTR2 *valuename = &q_u->valuename;
1294 uint32 in_size = q_u->size;
1295 uint32 *type = &r_u->type;
1296 uint32 *out_size = &r_u->size;
1297 uint8 **data = &r_u->data;
1298 uint32 *needed = &r_u->needed;
1302 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1305 * Reminder: when it's a string, the length is in BYTES
1306 * even if UNICODE is negociated.
1313 /* in case of problem, return some default values */
1317 DEBUG(4,("_spoolss_getprinterdata\n"));
1320 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1322 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1326 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1328 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1329 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1331 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1334 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1335 /* reply this param doesn't exist */
1337 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1343 return WERR_INVALID_PARAM;
1346 if (*needed > *out_size)
1347 return WERR_STATUS_MORE_ENTRIES;
1352 /***************************************************************************
1353 connect to the client
1354 ****************************************************************************/
1355 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1360 * If it's the first connection, contact the client
1361 * and connect to the IPC$ share anonumously
1363 if (smb_connections==0) {
1364 fstring unix_printer;
1366 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1368 if(!spoolss_connect_to_client(&cli, unix_printer))
1370 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1376 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1382 /********************************************************************
1384 * ReplyFindFirstPrinterChangeNotifyEx
1386 * jfmxxxx: before replying OK: status=0
1387 * should do a rpc call to the workstation asking ReplyOpenPrinter
1388 * have to code it, later.
1390 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1391 * called from api_spoolss_rffpcnex
1392 ********************************************************************/
1394 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1396 POLICY_HND *handle = &q_u->handle;
1397 uint32 flags = q_u->flags;
1398 uint32 options = q_u->options;
1399 UNISTR2 *localmachine = &q_u->localmachine;
1400 uint32 printerlocal = q_u->printerlocal;
1401 SPOOL_NOTIFY_OPTION *option = q_u->option;
1403 /* store the notify value in the printer struct */
1405 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1408 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
1412 Printer->notify.flags=flags;
1413 Printer->notify.options=options;
1414 Printer->notify.printerlocal=printerlocal;
1416 if (Printer->notify.option)
1417 free_spool_notify_option(&Printer->notify.option);
1419 Printer->notify.option=dup_spool_notify_option(option);
1421 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1423 /* connect to the client machine and send a ReplyOpenPrinter */
1424 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1425 Printer->notify.printerlocal, 1,
1426 &Printer->notify.client_hnd))
1427 Printer->notify.client_connected=True;
1432 /*******************************************************************
1433 * fill a notify_info_data with the servername
1434 ********************************************************************/
1436 static void spoolss_notify_server_name(int snum,
1437 SPOOL_NOTIFY_INFO_DATA *data,
1438 print_queue_struct *queue,
1439 NT_PRINTER_INFO_LEVEL *printer,
1440 TALLOC_CTX *mem_ctx)
1442 pstring temp_name, temp;
1445 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
1447 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
1449 data->notify_data.data.length = len / 2 - 1;
1450 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1452 if (!data->notify_data.data.string) {
1453 data->notify_data.data.length = 0;
1457 memcpy(data->notify_data.data.string, temp, len);
1460 /*******************************************************************
1461 * fill a notify_info_data with the printername (not including the servername).
1462 ********************************************************************/
1463 static void spoolss_notify_printer_name(int snum,
1464 SPOOL_NOTIFY_INFO_DATA *data,
1465 print_queue_struct *queue,
1466 NT_PRINTER_INFO_LEVEL *printer,
1467 TALLOC_CTX *mem_ctx)
1472 /* the notify name should not contain the \\server\ part */
1473 char *p = strrchr(printer->info_2->printername, '\\');
1476 p = printer->info_2->printername;
1481 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
1483 data->notify_data.data.length = len / 2 - 1;
1484 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1486 if (!data->notify_data.data.string) {
1487 data->notify_data.data.length = 0;
1491 memcpy(data->notify_data.data.string, temp, len);
1494 /*******************************************************************
1495 * fill a notify_info_data with the servicename
1496 ********************************************************************/
1497 static void spoolss_notify_share_name(int snum,
1498 SPOOL_NOTIFY_INFO_DATA *data,
1499 print_queue_struct *queue,
1500 NT_PRINTER_INFO_LEVEL *printer,
1501 TALLOC_CTX *mem_ctx)
1506 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
1508 data->notify_data.data.length = len / 2 - 1;
1509 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1511 if (!data->notify_data.data.string) {
1512 data->notify_data.data.length = 0;
1516 memcpy(data->notify_data.data.string, temp, len);
1519 /*******************************************************************
1520 * fill a notify_info_data with the port name
1521 ********************************************************************/
1522 static void spoolss_notify_port_name(int snum,
1523 SPOOL_NOTIFY_INFO_DATA *data,
1524 print_queue_struct *queue,
1525 NT_PRINTER_INFO_LEVEL *printer,
1526 TALLOC_CTX *mem_ctx)
1531 /* even if it's strange, that's consistant in all the code */
1533 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
1535 data->notify_data.data.length = len / 2 - 1;
1536 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1538 if (!data->notify_data.data.string) {
1539 data->notify_data.data.length = 0;
1543 memcpy(data->notify_data.data.string, temp, len);
1546 /*******************************************************************
1547 * fill a notify_info_data with the printername
1548 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1549 * but it doesn't exist, have to see what to do
1550 ********************************************************************/
1551 static void spoolss_notify_driver_name(int snum,
1552 SPOOL_NOTIFY_INFO_DATA *data,
1553 print_queue_struct *queue,
1554 NT_PRINTER_INFO_LEVEL *printer,
1555 TALLOC_CTX *mem_ctx)
1560 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
1561 data->notify_data.data.length = len / 2 - 1;
1562 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1564 if (!data->notify_data.data.string) {
1565 data->notify_data.data.length = 0;
1569 memcpy(data->notify_data.data.string, temp, len);
1572 /*******************************************************************
1573 * fill a notify_info_data with the comment
1574 ********************************************************************/
1575 static void spoolss_notify_comment(int snum,
1576 SPOOL_NOTIFY_INFO_DATA *data,
1577 print_queue_struct *queue,
1578 NT_PRINTER_INFO_LEVEL *printer,
1579 TALLOC_CTX *mem_ctx)
1584 if (*printer->info_2->comment == '\0')
1585 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
1587 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
1589 data->notify_data.data.length = len / 2 - 1;
1590 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1592 if (!data->notify_data.data.string) {
1593 data->notify_data.data.length = 0;
1597 memcpy(data->notify_data.data.string, temp, len);
1600 /*******************************************************************
1601 * fill a notify_info_data with the comment
1602 * jfm:xxxx incorrect, have to create a new smb.conf option
1603 * location = "Room 1, floor 2, building 3"
1604 ********************************************************************/
1605 static void spoolss_notify_location(int snum,
1606 SPOOL_NOTIFY_INFO_DATA *data,
1607 print_queue_struct *queue,
1608 NT_PRINTER_INFO_LEVEL *printer,
1609 TALLOC_CTX *mem_ctx)
1614 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
1616 data->notify_data.data.length = len / 2 - 1;
1617 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1619 if (!data->notify_data.data.string) {
1620 data->notify_data.data.length = 0;
1624 memcpy(data->notify_data.data.string, temp, len);
1627 /*******************************************************************
1628 * fill a notify_info_data with the device mode
1629 * jfm:xxxx don't to it for know but that's a real problem !!!
1630 ********************************************************************/
1631 static void spoolss_notify_devmode(int snum,
1632 SPOOL_NOTIFY_INFO_DATA *data,
1633 print_queue_struct *queue,
1634 NT_PRINTER_INFO_LEVEL *printer,
1635 TALLOC_CTX *mem_ctx)
1639 /*******************************************************************
1640 * fill a notify_info_data with the separator file name
1641 * jfm:xxxx just return no file could add an option to smb.conf
1642 * separator file = "separator.txt"
1643 ********************************************************************/
1644 static void spoolss_notify_sepfile(int snum,
1645 SPOOL_NOTIFY_INFO_DATA *data,
1646 print_queue_struct *queue,
1647 NT_PRINTER_INFO_LEVEL *printer,
1648 TALLOC_CTX *mem_ctx)
1653 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
1655 data->notify_data.data.length = len / 2 - 1;
1656 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1658 if (!data->notify_data.data.string) {
1659 data->notify_data.data.length = 0;
1663 memcpy(data->notify_data.data.string, temp, len);
1666 /*******************************************************************
1667 * fill a notify_info_data with the print processor
1668 * jfm:xxxx return always winprint to indicate we don't do anything to it
1669 ********************************************************************/
1670 static void spoolss_notify_print_processor(int snum,
1671 SPOOL_NOTIFY_INFO_DATA *data,
1672 print_queue_struct *queue,
1673 NT_PRINTER_INFO_LEVEL *printer,
1674 TALLOC_CTX *mem_ctx)
1679 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
1681 data->notify_data.data.length = len / 2 - 1;
1682 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1684 if (!data->notify_data.data.string) {
1685 data->notify_data.data.length = 0;
1689 memcpy(data->notify_data.data.string, temp, len);
1692 /*******************************************************************
1693 * fill a notify_info_data with the print processor options
1694 * jfm:xxxx send an empty string
1695 ********************************************************************/
1696 static void spoolss_notify_parameters(int snum,
1697 SPOOL_NOTIFY_INFO_DATA *data,
1698 print_queue_struct *queue,
1699 NT_PRINTER_INFO_LEVEL *printer,
1700 TALLOC_CTX *mem_ctx)
1705 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
1707 data->notify_data.data.length = len / 2 - 1;
1708 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1710 if (!data->notify_data.data.string) {
1711 data->notify_data.data.length = 0;
1715 memcpy(data->notify_data.data.string, temp, len);
1718 /*******************************************************************
1719 * fill a notify_info_data with the data type
1720 * jfm:xxxx always send RAW as data type
1721 ********************************************************************/
1722 static void spoolss_notify_datatype(int snum,
1723 SPOOL_NOTIFY_INFO_DATA *data,
1724 print_queue_struct *queue,
1725 NT_PRINTER_INFO_LEVEL *printer,
1726 TALLOC_CTX *mem_ctx)
1731 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
1733 data->notify_data.data.length = len / 2 - 1;
1734 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1736 if (!data->notify_data.data.string) {
1737 data->notify_data.data.length = 0;
1741 memcpy(data->notify_data.data.string, temp, len);
1744 /*******************************************************************
1745 * fill a notify_info_data with the security descriptor
1746 * jfm:xxxx send an null pointer to say no security desc
1747 * have to implement security before !
1748 ********************************************************************/
1749 static void spoolss_notify_security_desc(int snum,
1750 SPOOL_NOTIFY_INFO_DATA *data,
1751 print_queue_struct *queue,
1752 NT_PRINTER_INFO_LEVEL *printer,
1753 TALLOC_CTX *mem_ctx)
1755 data->notify_data.data.length=0;
1756 data->notify_data.data.string = NULL;
1759 /*******************************************************************
1760 * fill a notify_info_data with the attributes
1761 * jfm:xxxx a samba printer is always shared
1762 ********************************************************************/
1763 static void spoolss_notify_attributes(int snum,
1764 SPOOL_NOTIFY_INFO_DATA *data,
1765 print_queue_struct *queue,
1766 NT_PRINTER_INFO_LEVEL *printer,
1767 TALLOC_CTX *mem_ctx)
1769 data->notify_data.value[0] = printer->info_2->attributes;
1770 data->notify_data.value[1] = 0;
1773 /*******************************************************************
1774 * fill a notify_info_data with the priority
1775 ********************************************************************/
1776 static void spoolss_notify_priority(int snum,
1777 SPOOL_NOTIFY_INFO_DATA *data,
1778 print_queue_struct *queue,
1779 NT_PRINTER_INFO_LEVEL *printer,
1780 TALLOC_CTX *mem_ctx)
1782 data->notify_data.value[0] = printer->info_2->priority;
1783 data->notify_data.value[1] = 0;
1786 /*******************************************************************
1787 * fill a notify_info_data with the default priority
1788 ********************************************************************/
1789 static void spoolss_notify_default_priority(int snum,
1790 SPOOL_NOTIFY_INFO_DATA *data,
1791 print_queue_struct *queue,
1792 NT_PRINTER_INFO_LEVEL *printer,
1793 TALLOC_CTX *mem_ctx)
1795 data->notify_data.value[0] = printer->info_2->default_priority;
1796 data->notify_data.value[1] = 0;
1799 /*******************************************************************
1800 * fill a notify_info_data with the start time
1801 ********************************************************************/
1802 static void spoolss_notify_start_time(int snum,
1803 SPOOL_NOTIFY_INFO_DATA *data,
1804 print_queue_struct *queue,
1805 NT_PRINTER_INFO_LEVEL *printer,
1806 TALLOC_CTX *mem_ctx)
1808 data->notify_data.value[0] = printer->info_2->starttime;
1809 data->notify_data.value[1] = 0;
1812 /*******************************************************************
1813 * fill a notify_info_data with the until time
1814 ********************************************************************/
1815 static void spoolss_notify_until_time(int snum,
1816 SPOOL_NOTIFY_INFO_DATA *data,
1817 print_queue_struct *queue,
1818 NT_PRINTER_INFO_LEVEL *printer,
1819 TALLOC_CTX *mem_ctx)
1821 data->notify_data.value[0] = printer->info_2->untiltime;
1822 data->notify_data.value[1] = 0;
1825 /*******************************************************************
1826 * fill a notify_info_data with the status
1827 ********************************************************************/
1828 static void spoolss_notify_status(int snum,
1829 SPOOL_NOTIFY_INFO_DATA *data,
1830 print_queue_struct *queue,
1831 NT_PRINTER_INFO_LEVEL *printer,
1832 TALLOC_CTX *mem_ctx)
1834 print_status_struct status;
1836 print_queue_length(snum, &status);
1837 data->notify_data.value[0]=(uint32) status.status;
1838 data->notify_data.value[1] = 0;
1841 /*******************************************************************
1842 * fill a notify_info_data with the number of jobs queued
1843 ********************************************************************/
1844 static void spoolss_notify_cjobs(int snum,
1845 SPOOL_NOTIFY_INFO_DATA *data,
1846 print_queue_struct *queue,
1847 NT_PRINTER_INFO_LEVEL *printer,
1848 TALLOC_CTX *mem_ctx)
1850 data->notify_data.value[0] = print_queue_length(snum, NULL);
1851 data->notify_data.value[1] = 0;
1854 /*******************************************************************
1855 * fill a notify_info_data with the average ppm
1856 ********************************************************************/
1857 static void spoolss_notify_average_ppm(int snum,
1858 SPOOL_NOTIFY_INFO_DATA *data,
1859 print_queue_struct *queue,
1860 NT_PRINTER_INFO_LEVEL *printer,
1861 TALLOC_CTX *mem_ctx)
1863 /* always respond 8 pages per minutes */
1864 /* a little hard ! */
1865 data->notify_data.value[0] = printer->info_2->averageppm;
1866 data->notify_data.value[1] = 0;
1869 /*******************************************************************
1870 * fill a notify_info_data with username
1871 ********************************************************************/
1872 static void spoolss_notify_username(int snum,
1873 SPOOL_NOTIFY_INFO_DATA *data,
1874 print_queue_struct *queue,
1875 NT_PRINTER_INFO_LEVEL *printer,
1876 TALLOC_CTX *mem_ctx)
1881 len = rpcstr_push(temp, queue->user, sizeof(temp)-2, STR_TERMINATE);
1883 data->notify_data.data.length = len / 2 - 1;
1884 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1886 if (!data->notify_data.data.string) {
1887 data->notify_data.data.length = 0;
1891 memcpy(data->notify_data.data.string, temp, len);
1894 /*******************************************************************
1895 * fill a notify_info_data with job status
1896 ********************************************************************/
1897 static void spoolss_notify_job_status(int snum,
1898 SPOOL_NOTIFY_INFO_DATA *data,
1899 print_queue_struct *queue,
1900 NT_PRINTER_INFO_LEVEL *printer,
1901 TALLOC_CTX *mem_ctx)
1903 data->notify_data.value[0]=nt_printj_status(queue->status);
1904 data->notify_data.value[1] = 0;
1907 /*******************************************************************
1908 * fill a notify_info_data with job name
1909 ********************************************************************/
1910 static void spoolss_notify_job_name(int snum,
1911 SPOOL_NOTIFY_INFO_DATA *data,
1912 print_queue_struct *queue,
1913 NT_PRINTER_INFO_LEVEL *printer,
1914 TALLOC_CTX *mem_ctx)
1919 len = rpcstr_push(temp, queue->file, sizeof(temp)-2, STR_TERMINATE);
1921 data->notify_data.data.length = len / 2 - 1;
1922 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1924 if (!data->notify_data.data.string) {
1925 data->notify_data.data.length = 0;
1929 memcpy(data->notify_data.data.string, temp, len);
1932 /*******************************************************************
1933 * fill a notify_info_data with job status
1934 ********************************************************************/
1935 static void spoolss_notify_job_status_string(int snum,
1936 SPOOL_NOTIFY_INFO_DATA *data,
1937 print_queue_struct *queue,
1938 NT_PRINTER_INFO_LEVEL *printer,
1939 TALLOC_CTX *mem_ctx)
1942 * Now we're returning job status codes we just return a "" here. JRA.
1949 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1952 switch (queue->status) {
1957 p = ""; /* NT provides the paused string */
1966 #endif /* NO LONGER NEEDED. */
1968 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
1970 data->notify_data.data.length = len / 2 - 1;
1971 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1973 if (!data->notify_data.data.string) {
1974 data->notify_data.data.length = 0;
1978 memcpy(data->notify_data.data.string, temp, len);
1981 /*******************************************************************
1982 * fill a notify_info_data with job time
1983 ********************************************************************/
1984 static void spoolss_notify_job_time(int snum,
1985 SPOOL_NOTIFY_INFO_DATA *data,
1986 print_queue_struct *queue,
1987 NT_PRINTER_INFO_LEVEL *printer,
1988 TALLOC_CTX *mem_ctx)
1990 data->notify_data.value[0]=0x0;
1991 data->notify_data.value[1]=0;
1994 /*******************************************************************
1995 * fill a notify_info_data with job size
1996 ********************************************************************/
1997 static void spoolss_notify_job_size(int snum,
1998 SPOOL_NOTIFY_INFO_DATA *data,
1999 print_queue_struct *queue,
2000 NT_PRINTER_INFO_LEVEL *printer,
2001 TALLOC_CTX *mem_ctx)
2003 data->notify_data.value[0]=queue->size;
2004 data->notify_data.value[1]=0;
2007 /*******************************************************************
2008 Fill a notify_info_data with job position.
2009 ********************************************************************/
2011 static void spoolss_notify_job_position(int snum,
2012 SPOOL_NOTIFY_INFO_DATA *data,
2013 print_queue_struct *queue,
2014 NT_PRINTER_INFO_LEVEL *printer,
2015 TALLOC_CTX *mem_ctx)
2017 data->notify_data.value[0]=queue->job;
2018 data->notify_data.value[1]=0;
2021 /*******************************************************************
2022 Fill a notify_info_data with submitted time.
2023 ********************************************************************/
2025 static void spoolss_notify_submitted_time(int snum,
2026 SPOOL_NOTIFY_INFO_DATA *data,
2027 print_queue_struct *queue,
2028 NT_PRINTER_INFO_LEVEL *printer,
2029 TALLOC_CTX *mem_ctx)
2036 t=gmtime(&queue->time);
2038 len = sizeof(SYSTEMTIME);
2040 data->notify_data.data.length = len;
2041 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2043 if (!data->notify_data.data.string) {
2044 data->notify_data.data.length = 0;
2048 make_systemtime(&st, t);
2051 * Systemtime must be linearized as a set of UINT16's.
2052 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2055 p = (char *)data->notify_data.data.string;
2056 SSVAL(p, 0, st.year);
2057 SSVAL(p, 2, st.month);
2058 SSVAL(p, 4, st.dayofweek);
2059 SSVAL(p, 6, st.day);
2060 SSVAL(p, 8, st.hour);
2061 SSVAL(p, 10, st.minute);
2062 SSVAL(p, 12, st.second);
2063 SSVAL(p, 14, st.milliseconds);
2068 struct s_notify_info_data_table
2074 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2075 print_queue_struct *queue,
2076 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2079 struct s_notify_info_data_table notify_info_data_table[] =
2081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2090 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2091 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2092 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2093 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2094 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2095 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2096 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2097 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2098 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2099 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2100 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2101 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2102 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2103 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2104 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2105 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2106 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2107 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2108 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2109 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2110 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2111 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2112 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2113 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2114 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2115 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2116 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2117 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2118 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2119 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2120 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2121 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2122 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2123 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2124 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2125 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2126 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2127 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2128 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2129 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2130 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2131 { END, END, "", END, NULL }
2134 /*******************************************************************
2135 return the size of info_data structure
2136 ********************************************************************/
2137 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2141 while (notify_info_data_table[i].type != END)
2143 if ( (notify_info_data_table[i].type == type ) &&
2144 (notify_info_data_table[i].field == field ) )
2146 return (notify_info_data_table[i].size);
2153 /*******************************************************************
2154 return the type of notify_info_data
2155 ********************************************************************/
2156 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2160 while (notify_info_data_table[i].type != END)
2162 if ( (notify_info_data_table[i].type == type ) &&
2163 (notify_info_data_table[i].field == field ) )
2165 if (notify_info_data_table[i].size == POINTER)
2179 /****************************************************************************
2180 ****************************************************************************/
2181 static int search_notify(uint16 type, uint16 field, int *value)
2186 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2188 if ( (notify_info_data_table[j].type == type ) &&
2189 (notify_info_data_table[j].field == field ) )
2194 if ( found && (notify_info_data_table[j].fn != NULL) )
2200 /****************************************************************************
2201 ****************************************************************************/
2202 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2204 info_data->type = type;
2205 info_data->field = field;
2206 info_data->reserved = 0;
2208 info_data->size = size_of_notify_info_data(type, field);
2209 info_data->enc_type = type_of_notify_info_data(type, field);
2213 /*******************************************************************
2215 * fill a notify_info struct with info asked
2217 ********************************************************************/
2218 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2219 snum, SPOOL_NOTIFY_OPTION_TYPE
2220 *option_type, uint32 id,
2221 TALLOC_CTX *mem_ctx)
2227 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2228 NT_PRINTER_INFO_LEVEL *printer = NULL;
2229 print_queue_struct *queue=NULL;
2231 type=option_type->type;
2233 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2234 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2235 option_type->count, lp_servicename(snum)));
2237 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2240 for(field_num=0; field_num<option_type->count; field_num++) {
2241 field = option_type->fields[field_num];
2242 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2244 if (!search_notify(type, field, &j) )
2247 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2248 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2251 else info->data = tid;
2253 current_data=&info->data[info->count];
2255 construct_info_data(current_data, type, field, id);
2257 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2258 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2260 notify_info_data_table[j].fn(snum, current_data, queue,
2266 free_a_printer(&printer, 2);
2270 /*******************************************************************
2272 * fill a notify_info struct with info asked
2274 ********************************************************************/
2275 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2276 SPOOL_NOTIFY_INFO *info,
2277 NT_PRINTER_INFO_LEVEL *printer,
2278 int snum, SPOOL_NOTIFY_OPTION_TYPE
2279 *option_type, uint32 id,
2280 TALLOC_CTX *mem_ctx)
2286 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2288 DEBUG(4,("construct_notify_jobs_info\n"));
2290 type = option_type->type;
2292 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2293 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2294 option_type->count));
2296 for(field_num=0; field_num<option_type->count; field_num++) {
2297 field = option_type->fields[field_num];
2299 if (!search_notify(type, field, &j) )
2302 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2303 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2306 else info->data = tid;
2308 current_data=&(info->data[info->count]);
2310 construct_info_data(current_data, type, field, id);
2311 notify_info_data_table[j].fn(snum, current_data, queue,
2320 * JFM: The enumeration is not that simple, it's even non obvious.
2322 * let's take an example: I want to monitor the PRINTER SERVER for
2323 * the printer's name and the number of jobs currently queued.
2324 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2325 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2327 * I have 3 printers on the back of my server.
2329 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2332 * 1 printer 1 name 1
2333 * 2 printer 1 cjob 1
2334 * 3 printer 2 name 2
2335 * 4 printer 2 cjob 2
2336 * 5 printer 3 name 3
2337 * 6 printer 3 name 3
2339 * that's the print server case, the printer case is even worse.
2342 /*******************************************************************
2344 * enumerate all printers on the printserver
2345 * fill a notify_info struct with info asked
2347 ********************************************************************/
2349 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2350 SPOOL_NOTIFY_INFO *info,
2351 TALLOC_CTX *mem_ctx)
2354 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2355 int n_services=lp_numservices();
2358 SPOOL_NOTIFY_OPTION *option;
2359 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2361 DEBUG(4,("printserver_notify_info\n"));
2366 option=Printer->notify.option;
2372 for (i=0; i<option->count; i++) {
2373 option_type=&(option->ctr.type[i]);
2375 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2378 for (snum=0; snum<n_services; snum++)
2379 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2380 if (construct_notify_printer_info
2381 (info, snum, option_type, id, mem_ctx))
2386 * Debugging information, don't delete.
2389 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2390 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2391 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2393 for (i=0; i<info->count; i++) {
2394 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2395 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2396 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2403 /*******************************************************************
2405 * fill a notify_info struct with info asked
2407 ********************************************************************/
2408 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2409 TALLOC_CTX *mem_ctx)
2412 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2415 SPOOL_NOTIFY_OPTION *option;
2416 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2418 print_queue_struct *queue=NULL;
2419 print_status_struct status;
2421 DEBUG(4,("printer_notify_info\n"));
2426 option=Printer->notify.option;
2432 get_printer_snum(p, hnd, &snum);
2434 for (i=0; i<option->count; i++) {
2435 option_type=&option->ctr.type[i];
2437 switch ( option_type->type ) {
2438 case PRINTER_NOTIFY_TYPE:
2439 if(construct_notify_printer_info(info, snum,
2445 case JOB_NOTIFY_TYPE: {
2446 NT_PRINTER_INFO_LEVEL *printer = NULL;
2448 count = print_queue_status(snum, &queue, &status);
2450 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
2451 lp_servicename(snum))))
2454 for (j=0; j<count; j++) {
2455 construct_notify_jobs_info(&queue[j], info,
2462 free_a_printer(&printer, 2);
2472 * Debugging information, don't delete.
2475 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2476 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2477 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2479 for (i=0; i<info->count; i++) {
2480 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2481 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2482 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2488 /********************************************************************
2490 ********************************************************************/
2492 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2494 POLICY_HND *handle = &q_u->handle;
2495 /* uint32 change = q_u->change; - notused. */
2496 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2497 SPOOL_NOTIFY_INFO *info = &r_u->info;
2499 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2500 WERROR result = WERR_BADFID;
2502 /* we always have a NOTIFY_INFO struct */
2506 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
2507 OUR_HANDLE(handle)));
2511 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2513 /* jfm: the change value isn't used right now.
2514 * we will honour it when
2515 * a) we'll be able to send notification to the client
2516 * b) we'll have a way to communicate between the spoolss process.
2518 * same thing for option->flags
2519 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2520 * I don't have a global notification system, I'm sending back all the
2521 * informations even when _NOTHING_ has changed.
2524 /* just ignore the SPOOL_NOTIFY_OPTION */
2526 switch (Printer->printer_type) {
2527 case PRINTER_HANDLE_IS_PRINTSERVER:
2528 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2531 case PRINTER_HANDLE_IS_PRINTER:
2532 result = printer_notify_info(p, handle, info, p->mem_ctx);
2540 /********************************************************************
2541 * construct_printer_info_0
2542 * fill a printer_info_0 struct
2543 ********************************************************************/
2544 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2548 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2549 counter_printer_0 *session_counter;
2550 uint32 global_counter;
2553 print_status_struct status;
2555 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2558 count = print_queue_length(snum, &status);
2560 /* check if we already have a counter for this printer */
2561 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2563 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2564 if (session_counter->snum == snum)
2568 /* it's the first time, add it to the list */
2569 if (session_counter==NULL) {
2570 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2571 free_a_printer(&ntprinter, 2);
2574 ZERO_STRUCTP(session_counter);
2575 session_counter->snum=snum;
2576 session_counter->counter=0;
2577 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2581 session_counter->counter++;
2584 * the global_counter should be stored in a TDB as it's common to all the clients
2585 * and should be zeroed on samba startup
2587 global_counter=session_counter->counter;
2589 pstrcpy(chaine,ntprinter->info_2->printername);
2591 init_unistr(&printer->printername, chaine);
2593 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
2594 init_unistr(&printer->servername, chaine);
2596 printer->cjobs = count;
2597 printer->total_jobs = 0;
2598 printer->total_bytes = 0;
2600 setuptime = (time_t)ntprinter->info_2->setuptime;
2601 t=gmtime(&setuptime);
2603 printer->year = t->tm_year+1900;
2604 printer->month = t->tm_mon+1;
2605 printer->dayofweek = t->tm_wday;
2606 printer->day = t->tm_mday;
2607 printer->hour = t->tm_hour;
2608 printer->minute = t->tm_min;
2609 printer->second = t->tm_sec;
2610 printer->milliseconds = 0;
2612 printer->global_counter = global_counter;
2613 printer->total_pages = 0;
2614 printer->major_version = 0x0004; /* NT 4 */
2615 printer->build_version = 0x0565; /* build 1381 */
2616 printer->unknown7 = 0x1;
2617 printer->unknown8 = 0x0;
2618 printer->unknown9 = 0x0;
2619 printer->session_counter = session_counter->counter;
2620 printer->unknown11 = 0x0;
2621 printer->printer_errors = 0x0; /* number of print failure */
2622 printer->unknown13 = 0x0;
2623 printer->unknown14 = 0x1;
2624 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2625 printer->unknown16 = 0x0;
2626 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2627 printer->unknown18 = 0x0;
2628 printer->status = nt_printq_status(status.status);
2629 printer->unknown20 = 0x0;
2630 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
2631 printer->unknown22 = 0x0;
2632 printer->unknown23 = 0x6; /* 6 ???*/
2633 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2634 printer->unknown25 = 0;
2635 printer->unknown26 = 0;
2636 printer->unknown27 = 0;
2637 printer->unknown28 = 0;
2638 printer->unknown29 = 0;
2640 free_a_printer(&ntprinter,2);
2644 /********************************************************************
2645 * construct_printer_info_1
2646 * fill a printer_info_1 struct
2647 ********************************************************************/
2648 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2652 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2654 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2657 printer->flags=flags;
2659 if (*ntprinter->info_2->comment == '\0') {
2660 init_unistr(&printer->comment, lp_comment(snum));
2661 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
2662 ntprinter->info_2->drivername, lp_comment(snum));
2665 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2666 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
2667 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2670 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2672 init_unistr(&printer->description, chaine);
2673 init_unistr(&printer->name, chaine2);
2675 free_a_printer(&ntprinter,2);
2680 /****************************************************************************
2681 Free a DEVMODE struct.
2682 ****************************************************************************/
2684 static void free_dev_mode(DEVICEMODE *dev)
2689 SAFE_FREE(dev->private);
2693 /****************************************************************************
2694 Create a DEVMODE struct. Returns malloced memory.
2695 ****************************************************************************/
2697 static DEVICEMODE *construct_dev_mode(int snum)
2701 NT_PRINTER_INFO_LEVEL *printer = NULL;
2702 NT_DEVICEMODE *ntdevmode = NULL;
2703 DEVICEMODE *devmode = NULL;
2705 DEBUG(7,("construct_dev_mode\n"));
2707 DEBUGADD(8,("getting printer characteristics\n"));
2709 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2710 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
2714 ZERO_STRUCTP(devmode);
2716 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2719 if (printer->info_2->devmode)
2720 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2722 if (ntdevmode == NULL)
2725 DEBUGADD(8,("loading DEVICEMODE\n"));
2727 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2728 init_unistr(&devmode->devicename, adevice);
2730 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2731 init_unistr(&devmode->formname, aform);
2733 devmode->specversion = ntdevmode->specversion;
2734 devmode->driverversion = ntdevmode->driverversion;
2735 devmode->size = ntdevmode->size;
2736 devmode->driverextra = ntdevmode->driverextra;
2737 devmode->fields = ntdevmode->fields;
2739 devmode->orientation = ntdevmode->orientation;
2740 devmode->papersize = ntdevmode->papersize;
2741 devmode->paperlength = ntdevmode->paperlength;
2742 devmode->paperwidth = ntdevmode->paperwidth;
2743 devmode->scale = ntdevmode->scale;
2744 devmode->copies = ntdevmode->copies;
2745 devmode->defaultsource = ntdevmode->defaultsource;
2746 devmode->printquality = ntdevmode->printquality;
2747 devmode->color = ntdevmode->color;
2748 devmode->duplex = ntdevmode->duplex;
2749 devmode->yresolution = ntdevmode->yresolution;
2750 devmode->ttoption = ntdevmode->ttoption;
2751 devmode->collate = ntdevmode->collate;
2752 devmode->icmmethod = ntdevmode->icmmethod;
2753 devmode->icmintent = ntdevmode->icmintent;
2754 devmode->mediatype = ntdevmode->mediatype;
2755 devmode->dithertype = ntdevmode->dithertype;
2757 if (ntdevmode->private != NULL) {
2758 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2762 free_nt_devicemode(&ntdevmode);
2763 free_a_printer(&printer,2);
2770 free_nt_devicemode(&ntdevmode);
2772 free_a_printer(&printer,2);
2773 free_dev_mode(devmode);
2778 /********************************************************************
2779 * construct_printer_info_2
2780 * fill a printer_info_2 struct
2781 ********************************************************************/
2783 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2786 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2788 print_status_struct status;
2790 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2793 count = print_queue_length(snum, &status);
2795 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2796 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2797 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2798 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2799 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2801 if (*ntprinter->info_2->comment == '\0')
2802 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2804 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2806 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2807 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2808 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2809 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2810 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2812 printer->attributes = ntprinter->info_2->attributes;
2814 printer->priority = ntprinter->info_2->priority; /* priority */
2815 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2816 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2817 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2818 printer->status = nt_printq_status(status.status); /* status */
2819 printer->cjobs = count; /* jobs */
2820 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2822 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2823 DEBUG(8, ("Returning NULL Devicemode!\n"));
2826 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2827 /* steal the printer info sec_desc structure. [badly done]. */
2828 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2829 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2830 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2831 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2834 printer->secdesc = NULL;
2837 free_a_printer(&ntprinter, 2);
2841 /********************************************************************
2842 * construct_printer_info_3
2843 * fill a printer_info_3 struct
2844 ********************************************************************/
2845 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2847 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2848 PRINTER_INFO_3 *printer = NULL;
2850 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2854 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2855 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
2859 ZERO_STRUCTP(printer);
2861 printer->flags = 4; /* These are the components of the SD we are returning. */
2862 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2863 /* steal the printer info sec_desc structure. [badly done]. */
2864 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2868 * Set the flags for the components we are returning.
2871 if (printer->secdesc->owner_sid)
2872 printer->flags |= OWNER_SECURITY_INFORMATION;
2874 if (printer->secdesc->grp_sid)
2875 printer->flags |= GROUP_SECURITY_INFORMATION;
2877 if (printer->secdesc->dacl)
2878 printer->flags |= DACL_SECURITY_INFORMATION;
2880 if (printer->secdesc->sacl)
2881 printer->flags |= SACL_SECURITY_INFORMATION;
2884 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2885 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2886 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2889 free_a_printer(&ntprinter, 2);
2891 *pp_printer = printer;
2895 /********************************************************************
2896 * construct_printer_info_4
2897 * fill a printer_info_4 struct
2898 ********************************************************************/
2900 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
2902 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2904 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2907 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2908 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2909 printer->attributes = ntprinter->info_2->attributes;
2911 free_a_printer(&ntprinter, 2);
2915 /********************************************************************
2916 * construct_printer_info_5
2917 * fill a printer_info_5 struct
2918 ********************************************************************/
2920 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
2922 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2924 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2927 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2928 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
2929 printer->attributes = ntprinter->info_2->attributes;
2930 printer->device_not_selected_timeout = 0x3a98;
2931 printer->transmission_retry_timeout = 0xafc8;
2933 free_a_printer(&ntprinter, 2);
2938 /********************************************************************
2939 Spoolss_enumprinters.
2940 ********************************************************************/
2941 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2945 int n_services=lp_numservices();
2946 PRINTER_INFO_1 *tp, *printers=NULL;
2947 PRINTER_INFO_1 current_prt;
2949 DEBUG(4,("enum_all_printers_info_1\n"));
2951 for (snum=0; snum<n_services; snum++) {
2952 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2953 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2955 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2956 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2957 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2958 SAFE_FREE(printers);
2963 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2964 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
2970 /* check the required size. */
2971 for (i=0; i<*returned; i++)
2972 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2974 if (!alloc_buffer_size(buffer, *needed))
2975 return WERR_INSUFFICIENT_BUFFER;
2977 /* fill the buffer with the structures */
2978 for (i=0; i<*returned; i++)
2979 smb_io_printer_info_1("", buffer, &printers[i], 0);
2982 SAFE_FREE(printers);
2984 if (*needed > offered) {
2986 return WERR_INSUFFICIENT_BUFFER;
2992 /********************************************************************
2993 enum_all_printers_info_1_local.
2994 *********************************************************************/
2995 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2997 DEBUG(4,("enum_all_printers_info_1_local\n"));
2999 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3002 /********************************************************************
3003 enum_all_printers_info_1_name.
3004 *********************************************************************/
3005 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3009 DEBUG(4,("enum_all_printers_info_1_name\n"));
3011 if ((name[0] == '\\') && (name[1] == '\\'))
3014 if (is_myname_or_ipaddr(s)) {
3015 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3018 return WERR_INVALID_NAME;
3021 /********************************************************************
3022 enum_all_printers_info_1_remote.
3023 *********************************************************************/
3024 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3026 PRINTER_INFO_1 *printer;
3027 fstring printername;
3030 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3032 /* JFM: currently it's more a place holder than anything else.
3033 * In the spooler world there is a notion of server registration.
3034 * the print servers are registring (sp ?) on the PDC (in the same domain)
3036 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3039 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3044 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3045 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3046 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3048 init_unistr(&printer->description, desc);
3049 init_unistr(&printer->name, printername);
3050 init_unistr(&printer->comment, comment);
3051 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3053 /* check the required size. */
3054 *needed += spoolss_size_printer_info_1(printer);
3056 if (!alloc_buffer_size(buffer, *needed)) {
3058 return WERR_INSUFFICIENT_BUFFER;
3061 /* fill the buffer with the structures */
3062 smb_io_printer_info_1("", buffer, printer, 0);
3067 if (*needed > offered) {
3069 return WERR_INSUFFICIENT_BUFFER;
3075 /********************************************************************
3076 enum_all_printers_info_1_network.
3077 *********************************************************************/
3079 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3081 DEBUG(4,("enum_all_printers_info_1_network\n"));
3083 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3086 /********************************************************************
3087 * api_spoolss_enumprinters
3089 * called from api_spoolss_enumprinters (see this to understand)
3090 ********************************************************************/
3092 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3096 int n_services=lp_numservices();
3097 PRINTER_INFO_2 *tp, *printers=NULL;
3098 PRINTER_INFO_2 current_prt;
3100 for (snum=0; snum<n_services; snum++) {
3101 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3102 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3104 if (construct_printer_info_2(¤t_prt, snum)) {
3105 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3106 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3107 SAFE_FREE(printers);
3112 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3113 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
3119 /* check the required size. */
3120 for (i=0; i<*returned; i++)
3121 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3123 if (!alloc_buffer_size(buffer, *needed)) {
3124 for (i=0; i<*returned; i++) {
3125 free_devmode(printers[i].devmode);
3127 SAFE_FREE(printers);
3128 return WERR_INSUFFICIENT_BUFFER;
3131 /* fill the buffer with the structures */
3132 for (i=0; i<*returned; i++)
3133 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3136 for (i=0; i<*returned; i++) {
3137 free_devmode(printers[i].devmode);
3139 SAFE_FREE(printers);
3141 if (*needed > offered) {
3143 return WERR_INSUFFICIENT_BUFFER;
3149 /********************************************************************
3150 * handle enumeration of printers at level 1
3151 ********************************************************************/
3152 static WERROR enumprinters_level1( uint32 flags, fstring name,
3153 NEW_BUFFER *buffer, uint32 offered,
3154 uint32 *needed, uint32 *returned)
3156 /* Not all the flags are equals */
3158 if (flags & PRINTER_ENUM_LOCAL)
3159 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3161 if (flags & PRINTER_ENUM_NAME)
3162 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3164 if (flags & PRINTER_ENUM_REMOTE)
3165 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3167 if (flags & PRINTER_ENUM_NETWORK)
3168 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3170 return WERR_OK; /* NT4sp5 does that */
3173 /********************************************************************
3174 * handle enumeration of printers at level 2
3175 ********************************************************************/
3176 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3177 NEW_BUFFER *buffer, uint32 offered,
3178 uint32 *needed, uint32 *returned)
3180 char *s = servername;
3182 if (flags & PRINTER_ENUM_LOCAL) {
3183 return enum_all_printers_info_2(buffer, offered, needed, returned);
3186 if (flags & PRINTER_ENUM_NAME) {
3187 if ((servername[0] == '\\') && (servername[1] == '\\'))
3189 if (is_myname_or_ipaddr(s))
3190 return enum_all_printers_info_2(buffer, offered, needed, returned);
3192 return WERR_INVALID_NAME;
3195 if (flags & PRINTER_ENUM_REMOTE)
3196 return WERR_UNKNOWN_LEVEL;
3201 /********************************************************************
3202 * handle enumeration of printers at level 5
3203 ********************************************************************/
3204 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3205 NEW_BUFFER *buffer, uint32 offered,
3206 uint32 *needed, uint32 *returned)
3208 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3212 /********************************************************************
3213 * api_spoolss_enumprinters
3215 * called from api_spoolss_enumprinters (see this to understand)
3216 ********************************************************************/
3218 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3220 uint32 flags = q_u->flags;
3221 UNISTR2 *servername = &q_u->servername;
3222 uint32 level = q_u->level;
3223 NEW_BUFFER *buffer = NULL;
3224 uint32 offered = q_u->offered;
3225 uint32 *needed = &r_u->needed;
3226 uint32 *returned = &r_u->returned;
3230 /* that's an [in out] buffer */
3231 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3232 buffer = r_u->buffer;
3234 DEBUG(4,("_spoolss_enumprinters\n"));
3241 * flags==PRINTER_ENUM_NAME
3242 * if name=="" then enumerates all printers
3243 * if name!="" then enumerate the printer
3244 * flags==PRINTER_ENUM_REMOTE
3245 * name is NULL, enumerate printers
3246 * Level 2: name!="" enumerates printers, name can't be NULL
3247 * Level 3: doesn't exist
3248 * Level 4: does a local registry lookup
3249 * Level 5: same as Level 2
3252 unistr2_to_ascii(name, servername, sizeof(name)-1);
3257 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3259 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3261 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3266 return WERR_UNKNOWN_LEVEL;
3269 /****************************************************************************
3270 ****************************************************************************/
3271 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3273 PRINTER_INFO_0 *printer=NULL;
3275 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3278 construct_printer_info_0(printer, snum);
3280 /* check the required size. */
3281 *needed += spoolss_size_printer_info_0(printer);
3283 if (!alloc_buffer_size(buffer, *needed)) {
3285 return WERR_INSUFFICIENT_BUFFER;
3288 /* fill the buffer with the structures */
3289 smb_io_printer_info_0("", buffer, printer, 0);
3294 if (*needed > offered) {
3295 return WERR_INSUFFICIENT_BUFFER;
3301 /****************************************************************************
3302 ****************************************************************************/
3303 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3305 PRINTER_INFO_1 *printer=NULL;
3307 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3310 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3312 /* check the required size. */
3313 *needed += spoolss_size_printer_info_1(printer);
3315 if (!alloc_buffer_size(buffer, *needed)) {
3317 return WERR_INSUFFICIENT_BUFFER;
3320 /* fill the buffer with the structures */
3321 smb_io_printer_info_1("", buffer, printer, 0);
3326 if (*needed > offered) {
3327 return WERR_INSUFFICIENT_BUFFER;
3333 /****************************************************************************
3334 ****************************************************************************/
3335 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3337 PRINTER_INFO_2 *printer=NULL;
3339 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3342 construct_printer_info_2(printer, snum);
3344 /* check the required size. */
3345 *needed += spoolss_size_printer_info_2(printer);
3347 if (!alloc_buffer_size(buffer, *needed)) {
3348 free_printer_info_2(printer);
3349 return WERR_INSUFFICIENT_BUFFER;
3352 /* fill the buffer with the structures */
3353 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3354 free_printer_info_2(printer);
3359 free_printer_info_2(printer);
3361 if (*needed > offered) {
3362 return WERR_INSUFFICIENT_BUFFER;
3368 /****************************************************************************
3369 ****************************************************************************/
3370 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3372 PRINTER_INFO_3 *printer=NULL;
3374 if (!construct_printer_info_3(&printer, snum))
3377 /* check the required size. */
3378 *needed += spoolss_size_printer_info_3(printer);
3380 if (!alloc_buffer_size(buffer, *needed)) {
3381 free_printer_info_3(printer);
3382 return WERR_INSUFFICIENT_BUFFER;
3385 /* fill the buffer with the structures */
3386 smb_io_printer_info_3("", buffer, printer, 0);
3389 free_printer_info_3(printer);
3391 if (*needed > offered) {
3392 return WERR_INSUFFICIENT_BUFFER;
3398 /****************************************************************************
3399 ****************************************************************************/
3400 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3402 PRINTER_INFO_4 *printer=NULL;
3404 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
3407 if (!construct_printer_info_4(printer, snum))
3410 /* check the required size. */
3411 *needed += spoolss_size_printer_info_4(printer);
3413 if (!alloc_buffer_size(buffer, *needed)) {
3414 free_printer_info_4(printer);
3415 return WERR_INSUFFICIENT_BUFFER;
3418 /* fill the buffer with the structures */
3419 smb_io_printer_info_4("", buffer, printer, 0);
3422 free_printer_info_4(printer);
3424 if (*needed > offered) {
3425 return WERR_INSUFFICIENT_BUFFER;
3431 /****************************************************************************
3432 ****************************************************************************/
3433 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3435 PRINTER_INFO_5 *printer=NULL;
3437 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
3440 if (!construct_printer_info_5(printer, snum))
3443 /* check the required size. */
3444 *needed += spoolss_size_printer_info_5(printer);
3446 if (!alloc_buffer_size(buffer, *needed)) {
3447 free_printer_info_5(printer);
3448 return WERR_INSUFFICIENT_BUFFER;
3451 /* fill the buffer with the structures */
3452 smb_io_printer_info_5("", buffer, printer, 0);
3455 free_printer_info_5(printer);
3457 if (*needed > offered) {
3458 return WERR_INSUFFICIENT_BUFFER;
3464 /****************************************************************************
3465 ****************************************************************************/
3467 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3469 POLICY_HND *handle = &q_u->handle;
3470 uint32 level = q_u->level;
3471 NEW_BUFFER *buffer = NULL;
3472 uint32 offered = q_u->offered;
3473 uint32 *needed = &r_u->needed;
3477 /* that's an [in out] buffer */
3478 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3479 buffer = r_u->buffer;
3483 if (!get_printer_snum(p, handle, &snum))
3488 return getprinter_level_0(snum, buffer, offered, needed);
3490 return getprinter_level_1(snum, buffer, offered, needed);
3492 return getprinter_level_2(snum, buffer, offered, needed);
3494 return getprinter_level_3(snum, buffer, offered, needed);
3496 return getprinter_level_4(snum, buffer, offered, needed);
3498 return getprinter_level_5(snum, buffer, offered, needed);
3500 return WERR_UNKNOWN_LEVEL;
3503 /********************************************************************
3504 * fill a DRIVER_INFO_1 struct
3505 ********************************************************************/
3506 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3508 init_unistr( &info->name, driver.info_3->name);
3511 /********************************************************************
3512 * construct_printer_driver_info_1
3513 ********************************************************************/
3514 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3516 NT_PRINTER_INFO_LEVEL *printer = NULL;
3517 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3519 ZERO_STRUCT(driver);
3521 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3522 return WERR_INVALID_PRINTER_NAME;
3524 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3525 return WERR_UNKNOWN_PRINTER_DRIVER;
3527 fill_printer_driver_info_1(info, driver, servername, architecture);
3529 free_a_printer(&printer,2);
3534 /********************************************************************
3535 * construct_printer_driver_info_2
3536 * fill a printer_info_2 struct
3537 ********************************************************************/
3538 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3542 info->version=driver.info_3->cversion;
3544 init_unistr( &info->name, driver.info_3->name );
3545 init_unistr( &info->architecture, driver.info_3->environment );
3548 if (strlen(driver.info_3->driverpath)) {
3549 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3550 init_unistr( &info->driverpath, temp );
3552 init_unistr( &info->driverpath, "" );
3554 if (strlen(driver.info_3->datafile)) {
3555 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3556 init_unistr( &info->datafile, temp );
3558 init_unistr( &info->datafile, "" );
3560 if (strlen(driver.info_3->configfile)) {
3561 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3562 init_unistr( &info->configfile, temp );
3564 init_unistr( &info->configfile, "" );
3567 /********************************************************************
3568 * construct_printer_driver_info_2
3569 * fill a printer_info_2 struct
3570 ********************************************************************/
3571 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3573 NT_PRINTER_INFO_LEVEL *printer = NULL;
3574 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3576 ZERO_STRUCT(printer);
3577 ZERO_STRUCT(driver);
3579 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3580 return WERR_INVALID_PRINTER_NAME;
3582 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3583 return WERR_UNKNOWN_PRINTER_DRIVER;
3585 fill_printer_driver_info_2(info, driver, servername);
3587 free_a_printer(&printer,2);
3592 /********************************************************************
3593 * copy a strings array and convert to UNICODE
3595 * convert an array of ascii string to a UNICODE string
3596 ********************************************************************/
3597 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3605 DEBUG(6,("init_unistr_array\n"));
3609 if (char_array == NULL)
3613 if (!v) v = ""; /* hack to handle null lists */
3615 if (strlen(v) == 0) break;
3616 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3617 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3618 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3619 DEBUG(2,("init_unistr_array: Realloc error\n" ));
3623 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3628 (*uni_array)[j]=0x0000;
3631 DEBUGADD(6,("last one:done\n"));
3634 /********************************************************************
3635 * construct_printer_info_3
3636 * fill a printer_info_3 struct
3637 ********************************************************************/
3638 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3644 info->version=driver.info_3->cversion;
3646 init_unistr( &info->name, driver.info_3->name );
3647 init_unistr( &info->architecture, driver.info_3->environment );
3649 if (strlen(driver.info_3->driverpath)) {
3650 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3651 init_unistr( &info->driverpath, temp );
3653 init_unistr( &info->driverpath, "" );
3655 if (strlen(driver.info_3->datafile)) {
3656 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3657 init_unistr( &info->datafile, temp );
3659 init_unistr( &info->datafile, "" );
3661 if (strlen(driver.info_3->configfile)) {
3662 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3663 init_unistr( &info->configfile, temp );
3665 init_unistr( &info->configfile, "" );
3667 if (strlen(driver.info_3->helpfile)) {
3668 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3669 init_unistr( &info->helpfile, temp );
3671 init_unistr( &info->helpfile, "" );
3673 init_unistr( &info->monitorname, driver.info_3->monitorname );
3674 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3676 info->dependentfiles=NULL;
3677 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3680 /********************************************************************
3681 * construct_printer_info_3
3682 * fill a printer_info_3 struct
3683 ********************************************************************/
3684 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3686 NT_PRINTER_INFO_LEVEL *printer = NULL;
3687 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3689 ZERO_STRUCT(driver);
3691 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3692 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3693 if (!W_ERROR_IS_OK(status))
3694 return WERR_INVALID_PRINTER_NAME;
3696 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3697 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3702 * I put this code in during testing. Helpful when commenting out the
3703 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
3704 * as win2k always queries the driver using an infor level of 6.
3705 * I've left it in (but ifdef'd out) because I'll probably
3706 * use it in experimentation again in the future. --jerry 22/01/2002
3709 if (!W_ERROR_IS_OK(status)) {
3711 * Is this a W2k client ?
3714 /* Yes - try again with a WinNT driver. */
3716 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3717 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3721 if (!W_ERROR_IS_OK(status)) {
3722 free_a_printer(&printer,2);
3723 return WERR_UNKNOWN_PRINTER_DRIVER;
3731 fill_printer_driver_info_3(info, driver, servername);
3733 free_a_printer(&printer,2);
3738 /********************************************************************
3739 * construct_printer_info_6
3740 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3741 ********************************************************************/
3743 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3749 memset(&nullstr, '\0', sizeof(fstring));
3751 info->version=driver.info_3->cversion;
3753 init_unistr( &info->name, driver.info_3->name );
3754 init_unistr( &info->architecture, driver.info_3->environment );
3756 if (strlen(driver.info_3->driverpath)) {
3757 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3758 init_unistr( &info->driverpath, temp );
3760 init_unistr( &info->driverpath, "" );
3762 if (strlen(driver.info_3->datafile)) {
3763 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3764 init_unistr( &info->datafile, temp );
3766 init_unistr( &info->datafile, "" );
3768 if (strlen(driver.info_3->configfile)) {
3769 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3770 init_unistr( &info->configfile, temp );
3772 init_unistr( &info->configfile, "" );
3774 if (strlen(driver.info_3->helpfile)) {
3775 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3776 init_unistr( &info->helpfile, temp );
3778 init_unistr( &info->helpfile, "" );
3780 init_unistr( &info->monitorname, driver.info_3->monitorname );
3781 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3783 info->dependentfiles=NULL;
3784 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3786 info->previousdrivernames=NULL;
3787 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3789 info->driver_date.low=0;
3790 info->driver_date.high=0;
3793 info->driver_version_low=0;
3794 info->driver_version_high=0;
3796 init_unistr( &info->mfgname, "");
3797 init_unistr( &info->oem_url, "");
3798 init_unistr( &info->hardware_id, "");
3799 init_unistr( &info->provider, "");
3802 /********************************************************************
3803 * construct_printer_info_6
3804 * fill a printer_info_6 struct
3805 ********************************************************************/
3806 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3808 NT_PRINTER_INFO_LEVEL *printer = NULL;
3809 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3811 ZERO_STRUCT(driver);
3813 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3814 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3815 if (!W_ERROR_IS_OK(status))
3816 return WERR_INVALID_PRINTER_NAME;
3818 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3819 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3820 if (!W_ERROR_IS_OK(status)) {
3822 * Is this a W2k client ?
3826 free_a_printer(&printer,2);
3827 return WERR_UNKNOWN_PRINTER_DRIVER;
3830 /* Yes - try again with a WinNT driver. */
3832 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3833 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3834 if (!W_ERROR_IS_OK(status)) {
3835 free_a_printer(&printer,2);
3836 return WERR_UNKNOWN_PRINTER_DRIVER;
3840 fill_printer_driver_info_6(info, driver, servername);
3842 free_a_printer(&printer,2);
3847 /****************************************************************************
3848 ****************************************************************************/
3850 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3852 SAFE_FREE(info->dependentfiles);
3855 /****************************************************************************
3856 ****************************************************************************/
3858 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3860 SAFE_FREE(info->dependentfiles);
3864 /****************************************************************************
3865 ****************************************************************************/
3866 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3868 DRIVER_INFO_1 *info=NULL;
3871 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3874 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3875 if (!W_ERROR_IS_OK(status)) {
3880 /* check the required size. */
3881 *needed += spoolss_size_printer_driver_info_1(info);
3883 if (!alloc_buffer_size(buffer, *needed)) {
3885 return WERR_INSUFFICIENT_BUFFER;
3888 /* fill the buffer with the structures */
3889 smb_io_printer_driver_info_1("", buffer, info, 0);
3894 if (*needed > offered)
3895 return WERR_INSUFFICIENT_BUFFER;
3900 /****************************************************************************
3901 ****************************************************************************/
3902 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3904 DRIVER_INFO_2 *info=NULL;
3907 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3910 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3911 if (!W_ERROR_IS_OK(status)) {
3916 /* check the required size. */
3917 *needed += spoolss_size_printer_driver_info_2(info);
3919 if (!alloc_buffer_size(buffer, *needed)) {
3921 return WERR_INSUFFICIENT_BUFFER;
3924 /* fill the buffer with the structures */
3925 smb_io_printer_driver_info_2("", buffer, info, 0);
3930 if (*needed > offered)
3931 return WERR_INSUFFICIENT_BUFFER;
3936 /****************************************************************************
3937 ****************************************************************************/
3938 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3945 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3946 if (!W_ERROR_IS_OK(status)) {
3950 /* check the required size. */
3951 *needed += spoolss_size_printer_driver_info_3(&info);
3953 if (!alloc_buffer_size(buffer, *needed)) {
3954 free_printer_driver_info_3(&info);
3955 return WERR_INSUFFICIENT_BUFFER;
3958 /* fill the buffer with the structures */
3959 smb_io_printer_driver_info_3("", buffer, &info, 0);
3961 free_printer_driver_info_3(&info);
3963 if (*needed > offered)
3964 return WERR_INSUFFICIENT_BUFFER;
3969 /****************************************************************************
3970 ****************************************************************************/
3971 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3978 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3979 if (!W_ERROR_IS_OK(status)) {
3983 /* check the required size. */
3984 *needed += spoolss_size_printer_driver_info_6(&info);
3986 if (!alloc_buffer_size(buffer, *needed)) {
3987 free_printer_driver_info_6(&info);
3988 return WERR_INSUFFICIENT_BUFFER;
3991 /* fill the buffer with the structures */
3992 smb_io_printer_driver_info_6("", buffer, &info, 0);
3994 free_printer_driver_info_6(&info);
3996 if (*needed > offered)
3997 return WERR_INSUFFICIENT_BUFFER;
4002 /****************************************************************************
4003 ****************************************************************************/
4005 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
4007 POLICY_HND *handle = &q_u->handle;
4008 UNISTR2 *uni_arch = &q_u->architecture;
4009 uint32 level = q_u->level;
4010 uint32 clientmajorversion = q_u->clientmajorversion;
4011 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
4012 NEW_BUFFER *buffer = NULL;
4013 uint32 offered = q_u->offered;
4014 uint32 *needed = &r_u->needed;
4015 uint32 *servermajorversion = &r_u->servermajorversion;
4016 uint32 *serverminorversion = &r_u->serverminorversion;
4019 fstring architecture;
4022 /* that's an [in out] buffer */
4023 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4024 buffer = r_u->buffer;
4026 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4029 *servermajorversion=0;
4030 *serverminorversion=0;
4032 pstrcpy(servername, get_called_name());
4033 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4035 if (!get_printer_snum(p, handle, &snum))
4040 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4042 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4044 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4046 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4049 return WERR_UNKNOWN_LEVEL;
4052 /****************************************************************************
4053 ****************************************************************************/
4055 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4057 POLICY_HND *handle = &q_u->handle;
4059 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4062 DEBUG(3,("Error in startpageprinter printer handle\n"));
4066 Printer->page_started=True;
4070 /****************************************************************************
4071 ****************************************************************************/
4073 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4075 POLICY_HND *handle = &q_u->handle;
4077 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4080 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
4084 Printer->page_started=False;
4089 /********************************************************************
4090 * api_spoolss_getprinter
4091 * called from the spoolss dispatcher
4093 ********************************************************************/
4095 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4097 POLICY_HND *handle = &q_u->handle;
4098 /* uint32 level = q_u->doc_info_container.level; - notused. */
4099 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4100 uint32 *jobid = &r_u->jobid;
4102 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4106 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4107 struct current_user user;
4110 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4114 get_current_user(&user, p);
4117 * a nice thing with NT is it doesn't listen to what you tell it.
4118 * when asked to send _only_ RAW datas, it tries to send datas
4121 * So I add checks like in NT Server ...
4123 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4124 * there's a bug in NT client-side code, so we'll fix it in the
4125 * server-side code. *nnnnnggggh!*
4128 if (info_1->p_datatype != 0) {
4129 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4130 if (strcmp(datatype, "RAW") != 0) {
4132 return WERR_INVALID_DATATYPE;
4136 /* get the share number of the printer */
4137 if (!get_printer_snum(p, handle, &snum)) {
4141 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4143 Printer->jobid = print_job_start(&user, snum, jobname);
4145 /* An error occured in print_job_start() so return an appropriate
4148 if (Printer->jobid == -1) {
4149 return map_werror_from_unix(errno);
4152 Printer->document_started=True;
4153 (*jobid) = Printer->jobid;
4158 /********************************************************************
4159 * api_spoolss_getprinter
4160 * called from the spoolss dispatcher
4162 ********************************************************************/
4164 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4166 POLICY_HND *handle = &q_u->handle;
4168 return _spoolss_enddocprinter_internal(p, handle);
4171 /****************************************************************************
4172 ****************************************************************************/
4174 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4176 POLICY_HND *handle = &q_u->handle;
4177 uint32 buffer_size = q_u->buffer_size;
4178 uint8 *buffer = q_u->buffer;
4179 uint32 *buffer_written = &q_u->buffer_size2;
4181 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4184 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
4185 r_u->buffer_written = q_u->buffer_size2;
4189 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4192 r_u->buffer_written = q_u->buffer_size2;
4197 /********************************************************************
4198 * api_spoolss_getprinter
4199 * called from the spoolss dispatcher
4201 ********************************************************************/
4202 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4205 struct current_user user;
4207 WERROR errcode = WERR_BADFUNC;
4208 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4210 get_current_user(&user, p);
4213 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4217 if (!get_printer_snum(p, handle, &snum))
4221 case PRINTER_CONTROL_PAUSE:
4222 if (print_queue_pause(&user, snum, &errcode)) {
4226 case PRINTER_CONTROL_RESUME:
4227 case PRINTER_CONTROL_UNPAUSE:
4228 if (print_queue_resume(&user, snum, &errcode)) {
4232 case PRINTER_CONTROL_PURGE:
4233 if (print_queue_purge(&user, snum, &errcode)) {
4238 return WERR_UNKNOWN_LEVEL;
4244 /********************************************************************
4245 * api_spoolss_abortprinter
4246 ********************************************************************/
4248 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4250 POLICY_HND *handle = &q_u->handle;
4252 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4255 /********************************************************************
4256 * called by spoolss_api_setprinter
4257 * when updating a printer description
4258 ********************************************************************/
4259 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4260 const SPOOL_PRINTER_INFO_LEVEL *info,
4261 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4263 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4264 struct current_user user;
4268 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4270 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4271 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
4272 OUR_HANDLE(handle)));
4274 result = WERR_BADFID;
4278 /* NT seems to like setting the security descriptor even though
4279 nothing may have actually changed. This causes annoying
4280 dialog boxes when the user doesn't have permission to change
4281 the security descriptor. */
4283 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4285 if (DEBUGLEVEL >= 10) {
4289 the_acl = old_secdesc_ctr->sec->dacl;
4290 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4291 PRINTERNAME(snum), the_acl->num_aces));
4293 for (i = 0; i < the_acl->num_aces; i++) {
4296 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4298 DEBUG(10, ("%s 0x%08x\n", sid_str,
4299 the_acl->ace[i].info.mask));
4302 the_acl = secdesc_ctr->sec->dacl;
4305 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4306 PRINTERNAME(snum), the_acl->num_aces));
4308 for (i = 0; i < the_acl->num_aces; i++) {
4311 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4313 DEBUG(10, ("%s 0x%08x\n", sid_str,
4314 the_acl->ace[i].info.mask));
4317 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4321 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4323 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4328 /* Work out which user is performing the operation */
4330 get_current_user(&user, p);
4332 /* Check the user has permissions to change the security
4333 descriptor. By experimentation with two NT machines, the user
4334 requires Full Access to the printer to change security
4337 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4338 result = WERR_ACCESS_DENIED;
4342 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4349 /********************************************************************
4350 Do Samba sanity checks on a printer info struct.
4351 this has changed purpose: it now "canonicalises" printer
4352 info from a client rather than just checking it is correct
4353 ********************************************************************/
4355 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4357 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4358 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4360 /* we force some elements to "correct" values */
4361 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
4362 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4363 get_called_name(), lp_servicename(snum));
4364 fstrcpy(info->sharename, lp_servicename(snum));
4365 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
4370 /****************************************************************************
4371 ****************************************************************************/
4372 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4374 char *cmd = lp_addprinter_cmd();
4377 pstring driverlocation;
4381 fstring remote_machine = "%m";
4383 /* build driver path... only 9X architecture is needed for legacy reasons */
4384 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4386 /* change \ to \\ for the shell */
4387 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4389 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4390 cmd, printer->info_2->printername, printer->info_2->sharename,
4391 printer->info_2->portname, printer->info_2->drivername,
4392 printer->info_2->location, driverlocation, remote_machine);
4394 /* Convert script args to unix-codepage */
4395 DEBUG(10,("Running [%s]\n", command));
4396 ret = smbrun(command, &fd);
4397 DEBUGADD(10,("returned [%d]\n", ret));
4406 /* Get lines and convert them back to dos-codepage */
4407 qlines = fd_lines_load(fd, &numlines);
4408 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4412 /* Set the portname to what the script says the portname should be. */
4413 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4414 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4416 /* Send SIGHUP to process group... is there a better way? */
4421 file_lines_free(qlines);
4425 /* Return true if two devicemodes are equal */
4427 #define DEVMODE_CHECK_INT(field) \
4428 if (d1->field != d2->field) { \
4429 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4430 d1->field, d2->field)); \
4434 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4436 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4439 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4440 return False; /* if either is exclusively NULL are not equal */
4443 if (!strequal(d1->devicename, d2->devicename)) {
4444 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4448 if (!strequal(d1->formname, d2->formname)) {
4449 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4453 DEVMODE_CHECK_INT(specversion);
4454 DEVMODE_CHECK_INT(driverversion);
4455 DEVMODE_CHECK_INT(driverextra);
4456 DEVMODE_CHECK_INT(orientation);
4457 DEVMODE_CHECK_INT(papersize);
4458 DEVMODE_CHECK_INT(paperlength);
4459 DEVMODE_CHECK_INT(paperwidth);
4460 DEVMODE_CHECK_INT(scale);
4461 DEVMODE_CHECK_INT(copies);
4462 DEVMODE_CHECK_INT(defaultsource);
4463 DEVMODE_CHECK_INT(printquality);
4464 DEVMODE_CHECK_INT(color);
4465 DEVMODE_CHECK_INT(duplex);
4466 DEVMODE_CHECK_INT(yresolution);
4467 DEVMODE_CHECK_INT(ttoption);
4468 DEVMODE_CHECK_INT(collate);
4469 DEVMODE_CHECK_INT(logpixels);
4471 DEVMODE_CHECK_INT(fields);
4472 DEVMODE_CHECK_INT(bitsperpel);
4473 DEVMODE_CHECK_INT(pelswidth);
4474 DEVMODE_CHECK_INT(pelsheight);
4475 DEVMODE_CHECK_INT(displayflags);
4476 DEVMODE_CHECK_INT(displayfrequency);
4477 DEVMODE_CHECK_INT(icmmethod);
4478 DEVMODE_CHECK_INT(icmintent);
4479 DEVMODE_CHECK_INT(mediatype);
4480 DEVMODE_CHECK_INT(dithertype);
4481 DEVMODE_CHECK_INT(reserved1);
4482 DEVMODE_CHECK_INT(reserved2);
4483 DEVMODE_CHECK_INT(panningwidth);
4484 DEVMODE_CHECK_INT(panningheight);
4486 /* compare the private data if it exists */
4487 if (!d1->driverextra && !d2->driverextra) goto equal;
4490 DEVMODE_CHECK_INT(driverextra);
4492 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4493 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4498 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4502 /* Return true if two NT_PRINTER_PARAM structures are equal */
4504 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4505 NT_PRINTER_PARAM *p2)
4507 if (!p1 && !p2) goto equal;
4509 if ((!p1 && p2) || (p1 && !p2)) {
4510 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4514 /* Compare lists of printer parameters */
4518 NT_PRINTER_PARAM *q = p1;
4520 /* Find the parameter in the second structure */
4524 if (strequal(p1->value, q->value)) {
4526 if (p1->type != q->type) {
4527 DEBUG(10, ("nt_printer_param_equal():"
4528 "types for %s differ (%d != %d)\n",
4529 p1->value, p1->type,
4534 if (p1->data_len != q->data_len) {
4535 DEBUG(10, ("nt_printer_param_equal():"
4536 "len for %s differs (%d != %d)\n",
4537 p1->value, p1->data_len,
4542 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4545 DEBUG(10, ("nt_printer_param_equal():"
4546 "data for %s differs\n", p1->value));
4556 DEBUG(10, ("nt_printer_param_equal(): param %s "
4557 "does not exist\n", p1->value));
4566 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4570 /********************************************************************
4571 * Called by update_printer when trying to work out whether to
4572 * actually update printer info.
4573 ********************************************************************/
4575 #define PI_CHECK_INT(field) \
4576 if (pi1->field != pi2->field) { \
4577 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4578 pi1->field, pi2->field)); \
4582 #define PI_CHECK_STR(field) \
4583 if (!strequal(pi1->field, pi2->field)) { \
4584 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4585 pi1->field, pi2->field)); \
4589 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4590 NT_PRINTER_INFO_LEVEL *p2)
4592 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4594 /* Trivial conditions */
4596 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4600 if ((!p1 && p2) || (p1 && !p2) ||
4601 (!p1->info_2 && p2->info_2) ||
4602 (p1->info_2 && !p2->info_2)) {
4603 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4608 /* Compare two nt_printer_info_level structures. Don't compare
4609 status or cjobs as they seem to have something to do with the
4615 /* Don't check the attributes as we stomp on the value in
4616 check_printer_ok() anyway. */
4619 PI_CHECK_INT(attributes);
4622 PI_CHECK_INT(priority);
4623 PI_CHECK_INT(default_priority);
4624 PI_CHECK_INT(starttime);
4625 PI_CHECK_INT(untiltime);
4626 PI_CHECK_INT(averageppm);
4628 /* Yuck - don't check the printername or servername as the
4629 mod_a_printer() code plays games with them. You can't
4630 change the printername or the sharename through this interface
4633 PI_CHECK_STR(sharename);
4634 PI_CHECK_STR(portname);
4635 PI_CHECK_STR(drivername);
4636 PI_CHECK_STR(comment);
4637 PI_CHECK_STR(location);
4639 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4643 PI_CHECK_STR(sepfile);
4644 PI_CHECK_STR(printprocessor);
4645 PI_CHECK_STR(datatype);
4646 PI_CHECK_STR(parameters);
4648 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4652 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4656 PI_CHECK_INT(changeid);
4657 PI_CHECK_INT(c_setprinter);
4658 PI_CHECK_INT(setuptime);
4661 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4665 /********************************************************************
4666 * Called by spoolss_api_setprinter
4667 * when updating a printer description.
4668 ********************************************************************/
4670 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4671 const SPOOL_PRINTER_INFO_LEVEL *info,
4672 DEVICEMODE *devmode)
4675 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4676 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4679 DEBUG(8,("update_printer\n"));
4684 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
4685 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4686 result = WERR_UNKNOWN_LEVEL;
4691 result = WERR_BADFID;
4695 if (!get_printer_snum(p, handle, &snum)) {
4696 result = WERR_BADFID;
4700 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
4701 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
4702 result = WERR_BADFID;
4706 DEBUGADD(8,("Converting info_2 struct\n"));
4709 * convert_printer_info converts the incoming
4710 * info from the client and overwrites the info
4711 * just read from the tdb in the pointer 'printer'.
4714 if (!convert_printer_info(info, printer, level)) {
4715 result = WERR_NOMEM;
4719 if (info->info_2->devmode_ptr != 0) {
4720 /* we have a valid devmode
4721 convert it and link it*/
4723 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
4724 if (!convert_devicemode(printer->info_2->printername, devmode,
4725 &printer->info_2->devmode)) {
4726 result = WERR_NOMEM;
4731 /* Do sanity check on the requested changes for Samba */
4733 if (!check_printer_ok(printer->info_2, snum)) {
4734 result = WERR_INVALID_PARAM;
4738 /* NT likes to call this function even though nothing has actually
4739 changed. Check this so the user doesn't end up with an
4740 annoying permission denied dialog box. */
4742 if (nt_printer_info_level_equal(printer, old_printer)) {
4743 DEBUG(3, ("update_printer: printer info has not changed\n"));
4748 /* Check calling user has permission to update printer description */
4750 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4751 DEBUG(3, ("update_printer: printer property change denied by security descriptor\n"));
4752 result = WERR_ACCESS_DENIED;
4756 /* Call addprinter hook */
4758 if (*lp_addprinter_cmd()) {
4759 if ( !add_printer_hook(printer) ) {
4760 result = WERR_ACCESS_DENIED;
4766 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
4767 * DEVMODE.displayfrequency, which is not used for printer drivers. This
4768 * requires Win32 client code (see other notes elsewhere in the code).
4770 if (printer->info_2->devmode &&
4771 printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) {
4773 DEBUG(10,("update_printer: Save printer driver init data\n"));
4774 printer->info_2->devmode->displayfrequency = 0;
4776 if (update_driver_init(*printer, 2)!=0) {
4777 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
4778 result = WERR_ACCESS_DENIED;
4783 * When a *new* driver is bound to a printer, the drivername is used to
4784 * lookup previously saved driver initialization info, which is then
4785 * bound to the printer, simulating what happens in the Windows arch.
4787 if (strequal(printer->info_2->drivername, old_printer->info_2->drivername))
4788 set_driver_init(printer, 2);
4791 /* Update printer info */
4792 result = mod_a_printer(*printer, 2);
4795 free_a_printer(&printer, 2);
4796 free_a_printer(&old_printer, 2);
4798 srv_spoolss_sendnotify(0, PRINTER_CHANGE_SET_PRINTER);
4803 /****************************************************************************
4804 ****************************************************************************/
4806 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4808 POLICY_HND *handle = &q_u->handle;
4809 uint32 level = q_u->level;
4810 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4811 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4812 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4813 uint32 command = q_u->command;
4815 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4818 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4822 /* check the level */
4825 return control_printer(handle, command, p);
4827 return update_printer(p, handle, level, info, devmode_ctr.devmode);
4829 return update_printer_sec(handle, level, info, p,
4832 return WERR_UNKNOWN_LEVEL;
4836 /****************************************************************************
4837 ****************************************************************************/
4839 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4841 POLICY_HND *handle = &q_u->handle;
4843 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4846 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
4850 if (Printer->notify.client_connected==True)
4851 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4853 Printer->notify.flags=0;
4854 Printer->notify.options=0;
4855 Printer->notify.localmachine[0]='\0';
4856 Printer->notify.printerlocal=0;
4857 if (Printer->notify.option)
4858 free_spool_notify_option(&Printer->notify.option);
4859 Printer->notify.client_connected=False;
4864 /****************************************************************************
4865 ****************************************************************************/
4867 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4869 /* that's an [in out] buffer (despite appearences to the contrary) */
4870 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4873 return WERR_INVALID_PARAM; /* this is what a NT server
4874 returns for AddJob. AddJob
4875 must fail on non-local
4879 /****************************************************************************
4880 ****************************************************************************/
4881 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4882 int position, int snum)
4888 t=gmtime(&queue->time);
4889 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
4891 job_info->jobid=queue->job;
4892 init_unistr(&job_info->printername, lp_servicename(snum));
4893 init_unistr(&job_info->machinename, temp_name);
4894 init_unistr(&job_info->username, queue->user);
4895 init_unistr(&job_info->document, queue->file);
4896 init_unistr(&job_info->datatype, "RAW");
4897 init_unistr(&job_info->text_status, "");
4898 job_info->status=nt_printj_status(queue->status);
4899 job_info->priority=queue->priority;
4900 job_info->position=position;
4901 job_info->totalpages=0;
4902 job_info->pagesprinted=0;
4904 make_systemtime(&job_info->submitted, t);
4907 /****************************************************************************
4908 ****************************************************************************/
4909 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4910 int position, int snum,
4911 NT_PRINTER_INFO_LEVEL *ntprinter)
4917 t=gmtime(&queue->time);
4918 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
4920 job_info->jobid=queue->job;
4922 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
4924 init_unistr(&job_info->printername, chaine);
4926 init_unistr(&job_info->machinename, temp_name);
4927 init_unistr(&job_info->username, queue->user);
4928 init_unistr(&job_info->document, queue->file);
4929 init_unistr(&job_info->notifyname, queue->user);
4930 init_unistr(&job_info->datatype, "RAW");
4931 init_unistr(&job_info->printprocessor, "winprint");
4932 init_unistr(&job_info->parameters, "");
4933 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4934 init_unistr(&job_info->text_status, "");
4936 /* and here the security descriptor */
4938 job_info->status=nt_printj_status(queue->status);
4939 job_info->priority=queue->priority;
4940 job_info->position=position;
4941 job_info->starttime=0;
4942 job_info->untiltime=0;
4943 job_info->totalpages=0;
4944 job_info->size=queue->size;
4945 make_systemtime(&(job_info->submitted), t);
4946 job_info->timeelapsed=0;
4947 job_info->pagesprinted=0;
4949 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4956 /****************************************************************************
4957 Enumjobs at level 1.
4958 ****************************************************************************/
4959 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
4960 NEW_BUFFER *buffer, uint32 offered,
4961 uint32 *needed, uint32 *returned)
4966 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4973 for (i=0; i<*returned; i++)
4974 fill_job_info_1(&info[i], &queue[i], i, snum);
4978 /* check the required size. */
4979 for (i=0; i<*returned; i++)
4980 (*needed) += spoolss_size_job_info_1(&info[i]);
4982 if (!alloc_buffer_size(buffer, *needed)) {
4984 return WERR_INSUFFICIENT_BUFFER;
4987 /* fill the buffer with the structures */
4988 for (i=0; i<*returned; i++)
4989 smb_io_job_info_1("", buffer, &info[i], 0);
4994 if (*needed > offered) {
4996 return WERR_INSUFFICIENT_BUFFER;
5002 /****************************************************************************
5003 Enumjobs at level 2.
5004 ****************************************************************************/
5005 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
5006 NEW_BUFFER *buffer, uint32 offered,
5007 uint32 *needed, uint32 *returned)
5009 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
5014 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
5020 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
5021 if (!W_ERROR_IS_OK(result)) {
5026 for (i=0; i<*returned; i++)
5027 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
5029 free_a_printer(&ntprinter, 2);
5032 /* check the required size. */
5033 for (i=0; i<*returned; i++)
5034 (*needed) += spoolss_size_job_info_2(&info[i]);
5036 if (!alloc_buffer_size(buffer, *needed)) {
5038 return WERR_INSUFFICIENT_BUFFER;
5041 /* fill the buffer with the structures */
5042 for (i=0; i<*returned; i++)
5043 smb_io_job_info_2("", buffer, &info[i], 0);
5046 for (i = 0; i < *returned; i++)
5047 free_job_info_2(&info[i]);
5051 if (*needed > offered) {
5053 return WERR_INSUFFICIENT_BUFFER;
5059 /****************************************************************************
5061 ****************************************************************************/
5063 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5065 POLICY_HND *handle = &q_u->handle;
5066 /* uint32 firstjob = q_u->firstjob; - notused. */
5067 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5068 uint32 level = q_u->level;
5069 NEW_BUFFER *buffer = NULL;
5070 uint32 offered = q_u->offered;
5071 uint32 *needed = &r_u->needed;
5072 uint32 *returned = &r_u->returned;
5075 print_status_struct prt_status;
5076 print_queue_struct *queue=NULL;
5078 /* that's an [in out] buffer */
5079 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5080 buffer = r_u->buffer;
5082 DEBUG(4,("_spoolss_enumjobs\n"));
5087 if (!get_printer_snum(p, handle, &snum))
5090 *returned = print_queue_status(snum, &queue, &prt_status);
5091 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5093 if (*returned == 0) {
5100 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5102 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5106 return WERR_UNKNOWN_LEVEL;
5110 /****************************************************************************
5111 ****************************************************************************/
5113 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5118 /****************************************************************************
5119 ****************************************************************************/
5121 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5123 POLICY_HND *handle = &q_u->handle;
5124 uint32 jobid = q_u->jobid;
5125 /* uint32 level = q_u->level; - notused. */
5126 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5127 uint32 command = q_u->command;
5129 struct current_user user;
5131 WERROR errcode = WERR_BADFUNC;
5133 if (!get_printer_snum(p, handle, &snum)) {
5137 if (!print_job_exists(jobid)) {
5138 return WERR_INVALID_PRINTER_NAME;
5141 get_current_user(&user, p);
5144 case JOB_CONTROL_CANCEL:
5145 case JOB_CONTROL_DELETE:
5146 if (print_job_delete(&user, jobid, &errcode)) {
5150 case JOB_CONTROL_PAUSE:
5151 if (print_job_pause(&user, jobid, &errcode)) {
5155 case JOB_CONTROL_RESTART:
5156 case JOB_CONTROL_RESUME:
5157 if (print_job_resume(&user, jobid, &errcode)) {
5162 return WERR_UNKNOWN_LEVEL;
5168 /****************************************************************************
5169 Enumerates all printer drivers at level 1.
5170 ****************************************************************************/
5171 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5176 fstring *list = NULL;
5178 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5179 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5183 #define MAX_VERSION 4
5185 for (version=0; version<MAX_VERSION; version++) {
5187 ndrivers=get_ntdrivers(&list, architecture, version);
5188 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5194 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5195 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5196 SAFE_FREE(driver_info_1);
5200 else driver_info_1 = tdi1;
5203 for (i=0; i<ndrivers; i++) {
5205 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5206 ZERO_STRUCT(driver);
5207 status = get_a_printer_driver(&driver, 3, list[i],
5208 architecture, version);
5209 if (!W_ERROR_IS_OK(status)) {
5213 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5214 free_a_printer_driver(driver, 3);
5217 *returned+=ndrivers;
5221 /* check the required size. */
5222 for (i=0; i<*returned; i++) {
5223 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5224 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5227 if (!alloc_buffer_size(buffer, *needed)) {
5228 SAFE_FREE(driver_info_1);
5229 return WERR_INSUFFICIENT_BUFFER;
5232 /* fill the buffer with the driver structures */
5233 for (i=0; i<*returned; i++) {
5234 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5235 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5238 SAFE_FREE(driver_info_1);
5240 if (*needed > offered) {
5242 return WERR_INSUFFICIENT_BUFFER;
5248 /****************************************************************************
5249 Enumerates all printer drivers at level 2.
5250 ****************************************************************************/
5251 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5256 fstring *list = NULL;
5258 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5259 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5263 #define MAX_VERSION 4
5265 for (version=0; version<MAX_VERSION; version++) {
5267 ndrivers=get_ntdrivers(&list, architecture, version);
5268 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5274 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5275 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5276 SAFE_FREE(driver_info_2);
5280 else driver_info_2 = tdi2;
5283 for (i=0; i<ndrivers; i++) {
5286 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5287 ZERO_STRUCT(driver);
5288 status = get_a_printer_driver(&driver, 3, list[i],
5289 architecture, version);
5290 if (!W_ERROR_IS_OK(status)) {
5294 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5295 free_a_printer_driver(driver, 3);
5298 *returned+=ndrivers;
5302 /* check the required size. */
5303 for (i=0; i<*returned; i++) {
5304 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5305 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5308 if (!alloc_buffer_size(buffer, *needed)) {
5309 SAFE_FREE(driver_info_2);
5310 return WERR_INSUFFICIENT_BUFFER;
5313 /* fill the buffer with the form structures */
5314 for (i=0; i<*returned; i++) {
5315 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5316 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5319 SAFE_FREE(driver_info_2);
5321 if (*needed > offered) {
5323 return WERR_INSUFFICIENT_BUFFER;
5329 /****************************************************************************
5330 Enumerates all printer drivers at level 3.
5331 ****************************************************************************/
5332 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5337 fstring *list = NULL;
5339 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5340 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5344 #define MAX_VERSION 4
5346 for (version=0; version<MAX_VERSION; version++) {
5348 ndrivers=get_ntdrivers(&list, architecture, version);
5349 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5355 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5356 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5357 SAFE_FREE(driver_info_3);
5361 else driver_info_3 = tdi3;
5364 for (i=0; i<ndrivers; i++) {
5367 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5368 ZERO_STRUCT(driver);
5369 status = get_a_printer_driver(&driver, 3, list[i],
5370 architecture, version);
5371 if (!W_ERROR_IS_OK(status)) {
5375 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5376 free_a_printer_driver(driver, 3);
5379 *returned+=ndrivers;
5383 /* check the required size. */
5384 for (i=0; i<*returned; i++) {
5385 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5386 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5389 if (!alloc_buffer_size(buffer, *needed)) {
5390 SAFE_FREE(driver_info_3);
5391 return WERR_INSUFFICIENT_BUFFER;
5394 /* fill the buffer with the driver structures */
5395 for (i=0; i<*returned; i++) {
5396 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5397 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5400 for (i=0; i<*returned; i++)
5401 SAFE_FREE(driver_info_3[i].dependentfiles);
5403 SAFE_FREE(driver_info_3);
5405 if (*needed > offered) {
5407 return WERR_INSUFFICIENT_BUFFER;
5413 /****************************************************************************
5414 Enumerates all printer drivers.
5415 ****************************************************************************/
5417 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5419 /* UNISTR2 *name = &q_u->name; - notused. */
5420 UNISTR2 *environment = &q_u->environment;
5421 uint32 level = q_u->level;
5422 NEW_BUFFER *buffer = NULL;
5423 uint32 offered = q_u->offered;
5424 uint32 *needed = &r_u->needed;
5425 uint32 *returned = &r_u->returned;
5427 fstring *list = NULL;
5429 fstring architecture;
5431 /* that's an [in out] buffer */
5432 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5433 buffer = r_u->buffer;
5435 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5436 fstrcpy(servername, get_called_name());
5440 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5444 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5446 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5448 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5452 return WERR_UNKNOWN_LEVEL;
5456 /****************************************************************************
5457 ****************************************************************************/
5459 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5461 form->flag=list->flag;
5462 init_unistr(&form->name, list->name);
5463 form->width=list->width;
5464 form->length=list->length;
5465 form->left=list->left;
5466 form->top=list->top;
5467 form->right=list->right;
5468 form->bottom=list->bottom;
5471 /****************************************************************************
5472 ****************************************************************************/
5474 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5476 /* POLICY_HND *handle = &q_u->handle; - notused. */
5477 uint32 level = q_u->level;
5478 NEW_BUFFER *buffer = NULL;
5479 uint32 offered = q_u->offered;
5480 uint32 *needed = &r_u->needed;
5481 uint32 *numofforms = &r_u->numofforms;
5482 uint32 numbuiltinforms;
5484 nt_forms_struct *list=NULL;
5485 nt_forms_struct *builtinlist=NULL;
5490 /* that's an [in out] buffer */
5491 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5492 buffer = r_u->buffer;
5494 DEBUG(4,("_spoolss_enumforms\n"));
5495 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5496 DEBUGADD(5,("Info level [%d]\n", level));
5498 numbuiltinforms = get_builtin_ntforms(&builtinlist);
5499 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
5500 *numofforms = get_ntforms(&list);
5501 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
5502 *numofforms += numbuiltinforms;
5504 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
5508 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5513 /* construct the list of form structures */
5514 for (i=0; i<numbuiltinforms; i++) {
5515 DEBUGADD(6,("Filling form number [%d]\n",i));
5516 fill_form_1(&forms_1[i], &builtinlist[i]);
5519 SAFE_FREE(builtinlist);
5521 for (; i<*numofforms; i++) {
5522 DEBUGADD(6,("Filling form number [%d]\n",i));
5523 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5528 /* check the required size. */
5529 for (i=0; i<numbuiltinforms; i++) {
5530 DEBUGADD(6,("adding form [%d]'s size\n",i));
5531 buffer_size += spoolss_size_form_1(&forms_1[i]);
5533 for (; i<*numofforms; i++) {
5534 DEBUGADD(6,("adding form [%d]'s size\n",i));
5535 buffer_size += spoolss_size_form_1(&forms_1[i]);
5538 *needed=buffer_size;
5540 if (!alloc_buffer_size(buffer, buffer_size)){
5542 return WERR_INSUFFICIENT_BUFFER;
5545 /* fill the buffer with the form structures */
5546 for (i=0; i<numbuiltinforms; i++) {
5547 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5548 smb_io_form_1("", buffer, &forms_1[i], 0);
5550 for (; i<*numofforms; i++) {
5551 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5552 smb_io_form_1("", buffer, &forms_1[i], 0);
5557 if (*needed > offered) {
5559 return WERR_INSUFFICIENT_BUFFER;
5566 SAFE_FREE(builtinlist);
5567 return WERR_UNKNOWN_LEVEL;
5572 /****************************************************************************
5573 ****************************************************************************/
5575 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5577 /* POLICY_HND *handle = &q_u->handle; - notused. */
5578 uint32 level = q_u->level;
5579 UNISTR2 *uni_formname = &q_u->formname;
5580 NEW_BUFFER *buffer = NULL;
5581 uint32 offered = q_u->offered;
5582 uint32 *needed = &r_u->needed;
5584 nt_forms_struct *list=NULL;
5585 nt_forms_struct builtin_form;
5590 int numofforms=0, i=0;
5592 /* that's an [in out] buffer */
5593 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5594 buffer = r_u->buffer;
5596 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5598 DEBUG(4,("_spoolss_getform\n"));
5599 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5600 DEBUGADD(5,("Info level [%d]\n", level));
5602 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5603 if (!foundBuiltin) {
5604 numofforms = get_ntforms(&list);
5605 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5607 if (numofforms == 0)
5614 fill_form_1(&form_1, &builtin_form);
5617 /* Check if the requested name is in the list of form structures */
5618 for (i=0; i<numofforms; i++) {
5620 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5622 if (strequal(form_name, list[i].name)) {
5623 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5624 fill_form_1(&form_1, &list[i]);
5630 if (i == numofforms) {
5634 /* check the required size. */
5636 *needed=spoolss_size_form_1(&form_1);
5638 if (!alloc_buffer_size(buffer, buffer_size)){
5639 return WERR_INSUFFICIENT_BUFFER;
5642 if (*needed > offered) {
5643 return WERR_INSUFFICIENT_BUFFER;
5646 /* fill the buffer with the form structures */
5647 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5648 smb_io_form_1("", buffer, &form_1, 0);
5654 return WERR_UNKNOWN_LEVEL;
5658 /****************************************************************************
5659 ****************************************************************************/
5660 static void fill_port_1(PORT_INFO_1 *port, char *name)
5662 init_unistr(&port->port_name, name);
5665 /****************************************************************************
5666 ****************************************************************************/
5667 static void fill_port_2(PORT_INFO_2 *port, char *name)
5669 init_unistr(&port->port_name, name);
5670 init_unistr(&port->monitor_name, "Local Monitor");
5671 init_unistr(&port->description, "Local Port");
5672 #define PORT_TYPE_WRITE 1
5673 port->port_type=PORT_TYPE_WRITE;
5677 /****************************************************************************
5679 ****************************************************************************/
5680 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5682 PORT_INFO_1 *ports=NULL;
5685 if (*lp_enumports_cmd()) {
5686 char *cmd = lp_enumports_cmd();
5693 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5695 DEBUG(10,("Running [%s]\n", command));
5696 ret = smbrun(command, &fd);
5697 DEBUG(10,("Returned [%d]\n", ret));
5701 /* Is this the best error to return here? */
5702 return WERR_ACCESS_DENIED;
5706 qlines = fd_lines_load(fd, &numlines);
5707 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5711 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5712 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
5713 werror_str(WERR_NOMEM)));
5714 file_lines_free(qlines);
5718 for (i=0; i<numlines; i++) {
5719 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5720 fill_port_1(&ports[i], qlines[i]);
5723 file_lines_free(qlines);
5726 *returned = numlines;
5729 *returned = 1; /* Sole Samba port returned. */
5731 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5734 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5736 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5739 /* check the required size. */
5740 for (i=0; i<*returned; i++) {
5741 DEBUGADD(6,("adding port [%d]'s size\n", i));
5742 *needed += spoolss_size_port_info_1(&ports[i]);
5745 if (!alloc_buffer_size(buffer, *needed)) {
5747 return WERR_INSUFFICIENT_BUFFER;
5750 /* fill the buffer with the ports structures */
5751 for (i=0; i<*returned; i++) {
5752 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5753 smb_io_port_1("", buffer, &ports[i], 0);
5758 if (*needed > offered) {
5760 return WERR_INSUFFICIENT_BUFFER;
5766 /****************************************************************************
5768 ****************************************************************************/
5770 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5772 PORT_INFO_2 *ports=NULL;
5775 if (*lp_enumports_cmd()) {
5776 char *cmd = lp_enumports_cmd();
5785 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5786 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5788 path = lp_lockdir();
5790 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
5791 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5794 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5795 ret = smbrun(command, &fd);
5796 DEBUGADD(10,("returned [%d]\n", ret));
5800 /* Is this the best error to return here? */
5801 return WERR_ACCESS_DENIED;
5805 qlines = fd_lines_load(fd, &numlines);
5806 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5810 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5811 file_lines_free(qlines);
5815 for (i=0; i<numlines; i++) {
5816 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5817 fill_port_2(&(ports[i]), qlines[i]);
5820 file_lines_free(qlines);
5823 *returned = numlines;
5829 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5832 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5834 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5837 /* check the required size. */
5838 for (i=0; i<*returned; i++) {
5839 DEBUGADD(6,("adding port [%d]'s size\n", i));
5840 *needed += spoolss_size_port_info_2(&ports[i]);
5843 if (!alloc_buffer_size(buffer, *needed)) {
5845 return WERR_INSUFFICIENT_BUFFER;
5848 /* fill the buffer with the ports structures */
5849 for (i=0; i<*returned; i++) {
5850 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5851 smb_io_port_2("", buffer, &ports[i], 0);
5856 if (*needed > offered) {
5858 return WERR_INSUFFICIENT_BUFFER;
5864 /****************************************************************************
5866 ****************************************************************************/
5868 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5870 /* UNISTR2 *name = &q_u->name; - notused. */
5871 uint32 level = q_u->level;
5872 NEW_BUFFER *buffer = NULL;
5873 uint32 offered = q_u->offered;
5874 uint32 *needed = &r_u->needed;
5875 uint32 *returned = &r_u->returned;
5877 /* that's an [in out] buffer */
5878 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5879 buffer = r_u->buffer;
5881 DEBUG(4,("_spoolss_enumports\n"));
5888 return enumports_level_1(buffer, offered, needed, returned);
5890 return enumports_level_2(buffer, offered, needed, returned);
5892 return WERR_UNKNOWN_LEVEL;
5896 /****************************************************************************
5897 ****************************************************************************/
5898 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5899 const SPOOL_PRINTER_INFO_LEVEL *info,
5900 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
5901 uint32 user_switch, const SPOOL_USER_CTR *user,
5904 NT_PRINTER_INFO_LEVEL *printer = NULL;
5907 WERROR err = WERR_OK;
5909 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5910 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5914 ZERO_STRUCTP(printer);
5916 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5917 if (!convert_printer_info(info, printer, 2)) {
5918 free_a_printer(&printer, 2);
5922 /* check to see if the printer already exists */
5924 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
5925 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
5926 printer->info_2->sharename));
5927 free_a_printer(&printer, 2);
5928 return WERR_PRINTER_ALREADY_EXISTS;
5931 if (*lp_addprinter_cmd() )
5932 if ( !add_printer_hook(printer) ) {
5933 free_a_printer(&printer,2);
5934 return WERR_ACCESS_DENIED;
5937 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
5938 printer->info_2->sharename);
5940 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5941 free_a_printer(&printer,2);
5942 return WERR_ACCESS_DENIED;
5945 /* you must be a printer admin to add a new printer */
5946 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5947 free_a_printer(&printer,2);
5948 return WERR_ACCESS_DENIED;
5952 * Do sanity check on the requested changes for Samba.
5955 if (!check_printer_ok(printer->info_2, snum)) {
5956 free_a_printer(&printer,2);
5957 return WERR_INVALID_PARAM;
5961 * When a printer is created, the drivername bound to the printer is used
5962 * to lookup previously saved driver initialization info, which is then
5963 * bound to the new printer, simulating what happens in the Windows arch.
5967 set_driver_init(printer, 2);
5969 /* A valid devmode was included, convert and link it
5971 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
5973 if (!convert_devicemode(printer->info_2->printername, devmode,
5974 &printer->info_2->devmode))
5978 set_driver_init(printer, 2);
5980 /* write the ASCII on disk */
5981 err = mod_a_printer(*printer, 2);
5982 if (!W_ERROR_IS_OK(err)) {
5983 free_a_printer(&printer,2);
5987 if (!open_printer_hnd(p, handle, name)) {
5988 /* Handle open failed - remove addition. */
5989 del_a_printer(printer->info_2->sharename);
5990 free_a_printer(&printer,2);
5991 return WERR_ACCESS_DENIED;
5994 free_a_printer(&printer,2);
5996 update_c_setprinter(False);
5998 srv_spoolss_sendnotify(0, PRINTER_CHANGE_ADD_PRINTER);
6003 /****************************************************************************
6004 ****************************************************************************/
6006 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
6008 UNISTR2 *uni_srv_name = &q_u->server_name;
6009 uint32 level = q_u->level;
6010 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6011 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
6012 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
6013 uint32 user_switch = q_u->user_switch;
6014 SPOOL_USER_CTR *user = &q_u->user_ctr;
6015 POLICY_HND *handle = &r_u->handle;
6019 /* we don't handle yet */
6020 /* but I know what to do ... */
6021 return WERR_UNKNOWN_LEVEL;
6023 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
6025 user_switch, user, handle);
6027 return WERR_UNKNOWN_LEVEL;
6031 /****************************************************************************
6032 ****************************************************************************/
6034 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
6036 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
6037 uint32 level = q_u->level;
6038 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
6039 WERROR err = WERR_OK;
6040 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6041 struct current_user user;
6043 ZERO_STRUCT(driver);
6045 get_current_user(&user, p);
6047 if (!convert_printer_driver_info(info, &driver, level)) {
6052 DEBUG(5,("Cleaning driver's information\n"));
6053 err = clean_up_driver_struct(driver, level, &user);
6054 if (!W_ERROR_IS_OK(err))
6057 DEBUG(5,("Moving driver to final destination\n"));
6058 if(!move_driver_to_download_area(driver, level, &user, &err)) {
6059 if (W_ERROR_IS_OK(err))
6060 err = WERR_ACCESS_DENIED;
6064 if (add_a_printer_driver(driver, level)!=0) {
6065 err = WERR_ACCESS_DENIED;
6070 free_a_printer_driver(driver, level);
6074 /****************************************************************************
6075 ****************************************************************************/
6076 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6078 init_unistr(&info->name, name);
6081 /****************************************************************************
6082 ****************************************************************************/
6083 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6087 pstring short_archi;
6088 DRIVER_DIRECTORY_1 *info=NULL;
6090 fstring asc_name, servername;
6092 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6094 if (get_short_archi(short_archi, long_archi)==False)
6095 return WERR_INVALID_ENVIRONMENT;
6097 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6101 /* use the name the client sent us */
6103 unistr2_to_ascii(asc_name, name, sizeof(asc_name)-1);
6104 if (asc_name[0] == '\\' && asc_name[1] == '\\')
6105 fstrcpy(servername, asc_name);
6107 fstrcpy(servername, "\\\\");
6108 fstrcat(servername, asc_name);
6111 slprintf(path, sizeof(path)-1, "%s\\print$\\%s", servername, short_archi);
6114 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6116 DEBUG(4,("printer driver directory: [%s]\n", path));
6118 fill_driverdir_1(info, path);
6120 *needed += spoolss_size_driverdir_info_1(info);
6122 if (!alloc_buffer_size(buffer, *needed)) {
6124 return WERR_INSUFFICIENT_BUFFER;
6127 smb_io_driverdir_1("", buffer, info, 0);
6131 if (*needed > offered)
6132 return WERR_INSUFFICIENT_BUFFER;
6137 /****************************************************************************
6138 ****************************************************************************/
6140 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6142 UNISTR2 *name = &q_u->name;
6143 UNISTR2 *uni_environment = &q_u->environment;
6144 uint32 level = q_u->level;
6145 NEW_BUFFER *buffer = NULL;
6146 uint32 offered = q_u->offered;
6147 uint32 *needed = &r_u->needed;
6149 /* that's an [in out] buffer */
6150 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6151 buffer = r_u->buffer;
6153 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6159 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6161 return WERR_UNKNOWN_LEVEL;
6165 /****************************************************************************
6166 ****************************************************************************/
6168 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6170 POLICY_HND *handle = &q_u->handle;
6171 uint32 idx = q_u->index;
6172 uint32 in_value_len = q_u->valuesize;
6173 uint32 in_data_len = q_u->datasize;
6174 uint32 *out_max_value_len = &r_u->valuesize;
6175 uint16 **out_value = &r_u->value;
6176 uint32 *out_value_len = &r_u->realvaluesize;
6177 uint32 *out_type = &r_u->type;
6178 uint32 *out_max_data_len = &r_u->datasize;
6179 uint8 **data_out = &r_u->data;
6180 uint32 *out_data_len = &r_u->realdatasize;
6182 NT_PRINTER_INFO_LEVEL *printer = NULL;
6187 uint32 biggest_valuesize;
6188 uint32 biggest_datasize;
6190 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6196 ZERO_STRUCT(printer);
6200 *out_max_data_len=0;
6204 DEBUG(5,("spoolss_enumprinterdata\n"));
6207 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6211 if (!get_printer_snum(p,handle, &snum))
6214 result = get_a_printer(&printer, 2, lp_servicename(snum));
6215 if (!W_ERROR_IS_OK(result))
6219 * The NT machine wants to know the biggest size of value and data
6221 * cf: MSDN EnumPrinterData remark section
6223 if ( (in_value_len==0) && (in_data_len==0) ) {
6224 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6228 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6229 * if this parameter size doesn't exist.
6230 * Ok - my opinion here is that the client is not asking for the greatest
6231 * possible size of all the parameters, but is asking specifically for the size needed
6232 * for this specific parameter. In that case we can remove the loop below and
6233 * simplify this lookup code considerably. JF - comments welcome. JRA.
6236 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6238 free_a_printer(&printer, 2);
6239 return WERR_NO_MORE_ITEMS;
6246 biggest_valuesize=0;
6249 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6250 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6251 if (data_len > biggest_datasize) biggest_datasize=data_len;
6253 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6259 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6260 *out_value_len=2*(1+biggest_valuesize);
6261 *out_data_len=biggest_datasize;
6263 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6265 free_a_printer(&printer, 2);
6270 * the value len is wrong in NT sp3
6271 * that's the number of bytes not the number of unicode chars
6274 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6277 free_a_printer(&printer, 2);
6279 /* out_value should default to "" or else NT4 has
6280 problems unmarshalling the response */
6282 *out_max_value_len=(in_value_len/sizeof(uint16));
6283 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
6286 *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
6288 /* the data is counted in bytes */
6289 *out_max_data_len = in_data_len;
6290 *out_data_len = in_data_len;
6291 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
6294 return WERR_NO_MORE_ITEMS;
6297 free_a_printer(&printer, 2);
6301 * - counted in bytes in the request
6302 * - counted in UNICODE chars in the max reply
6303 * - counted in bytes in the real size
6305 * take a pause *before* coding not *during* coding
6308 *out_max_value_len=(in_value_len/sizeof(uint16));
6309 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6314 *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6318 /* the data is counted in bytes */
6319 *out_max_data_len=in_data_len;
6320 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6325 memcpy(*data_out, data, (size_t)data_len);
6326 *out_data_len=data_len;
6333 /****************************************************************************
6334 ****************************************************************************/
6336 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6338 POLICY_HND *handle = &q_u->handle;
6339 UNISTR2 *value = &q_u->value;
6340 uint32 type = q_u->type;
6341 /* uint32 max_len = q_u->max_len; - notused. */
6342 uint8 *data = q_u->data;
6343 uint32 real_len = q_u->real_len;
6344 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6346 NT_PRINTER_INFO_LEVEL *printer = NULL;
6347 NT_PRINTER_PARAM *param = NULL, old_param;
6349 WERROR status = WERR_OK;
6350 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6352 DEBUG(5,("spoolss_setprinterdata\n"));
6355 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6359 if (!get_printer_snum(p,handle, &snum))
6362 ZERO_STRUCT(old_param);
6365 * Access check : NT returns "access denied" if you make a
6366 * SetPrinterData call without the necessary privildge.
6367 * we were originally returning OK if nothing changed
6368 * which made Win2k issue **a lot** of SetPrinterData
6369 * when connecting to a printer --jerry
6372 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6373 DEBUG(3, ("security descriptor change denied by existing "
6374 "security descriptor\n"));
6375 status = WERR_ACCESS_DENIED;
6379 /* Check if we are making any changes or not. Return true if
6380 nothing is actually changing. This is not needed anymore but
6381 has been left in as an optimization to keep from from
6382 writing to disk as often --jerry */
6384 status = get_a_printer(&printer, 2, lp_servicename(snum));
6385 if (!W_ERROR_IS_OK(status))
6388 convert_specific_param(¶m, value , type, data, real_len);
6391 /* JRA. W2K always changes changeid. */
6393 if (get_specific_param(*printer, 2, param->value, &old_param.data,
6394 &old_param.type, (uint32 *)&old_param.data_len)) {
6396 if (param->type == old_param.type &&
6397 param->data_len == old_param.data_len &&
6398 memcmp(param->data, old_param.data,
6399 old_param.data_len) == 0) {
6401 DEBUG(3, ("setprinterdata hasn't changed\n"));
6408 unlink_specific_param_if_exist(printer->info_2, param);
6411 * When client side code sets a magic printer data key, detect it and save
6412 * the current printer data and the magic key's data (its the DEVMODE) for
6413 * future printer/driver initializations.
6415 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6417 * Set devmode and printer initialization info
6419 status = save_driver_init(printer, 2, param);
6422 add_a_specific_param(printer->info_2, ¶m);
6423 status = mod_a_printer(*printer, 2);
6427 free_a_printer(&printer, 2);
6429 free_nt_printer_param(¶m);
6430 SAFE_FREE(old_param.data);
6433 /* Is this correct. JRA ? */
6434 srv_spoolss_sendnotify(0, PRINTER_CHANGE_SET_PRINTER);
6440 /****************************************************************************
6441 ****************************************************************************/
6443 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6445 POLICY_HND *handle = &q_u->handle;
6446 UNISTR2 *value = &q_u->valuename;
6448 NT_PRINTER_INFO_LEVEL *printer = NULL;
6449 NT_PRINTER_PARAM param;
6451 WERROR status = WERR_OK;
6452 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6454 DEBUG(5,("spoolss_deleteprinterdata\n"));
6457 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6461 if (!get_printer_snum(p, handle, &snum))
6464 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6465 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6466 "change denied by existing security descriptor\n"));
6467 return WERR_ACCESS_DENIED;
6470 status = get_a_printer(&printer, 2, lp_servicename(snum));
6471 if (!W_ERROR_IS_OK(status))
6474 ZERO_STRUCTP(¶m);
6475 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6477 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
6478 status = WERR_INVALID_PARAM;
6480 status = mod_a_printer(*printer, 2);
6482 free_a_printer(&printer, 2);
6486 /****************************************************************************
6487 ****************************************************************************/
6489 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6491 POLICY_HND *handle = &q_u->handle;
6492 /* uint32 level = q_u->level; - notused. */
6493 FORM *form = &q_u->form;
6494 nt_forms_struct tmpForm;
6496 WERROR status = WERR_OK;
6497 NT_PRINTER_INFO_LEVEL *printer = NULL;
6500 nt_forms_struct *list=NULL;
6501 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6503 DEBUG(5,("spoolss_addform\n"));
6506 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6511 * FIXME!! Feels like there should be an access check here, but haven't
6512 * had time to verify. --jerry
6516 if (!get_printer_snum(p,handle, &snum))
6519 /* can't add if builtin */
6520 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6521 return WERR_ALREADY_EXISTS;
6524 count=get_ntforms(&list);
6525 if(!add_a_form(&list, form, &count))
6527 write_ntforms(&list, count);
6530 * ChangeID must always be set
6533 if (!get_printer_snum(p,handle, &snum))
6536 status = get_a_printer(&printer, 2, lp_servicename(snum));
6537 if (!W_ERROR_IS_OK(status))
6540 status = mod_a_printer(*printer, 2);
6541 if (!W_ERROR_IS_OK(status))
6545 free_a_printer(&printer, 2);
6551 /****************************************************************************
6552 ****************************************************************************/
6554 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6556 POLICY_HND *handle = &q_u->handle;
6557 UNISTR2 *form_name = &q_u->name;
6558 nt_forms_struct tmpForm;
6560 WERROR ret = WERR_OK;
6561 nt_forms_struct *list=NULL;
6562 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6564 WERROR status = WERR_OK;
6565 NT_PRINTER_INFO_LEVEL *printer = NULL;
6567 DEBUG(5,("spoolss_deleteform\n"));
6570 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6574 if (!get_printer_snum(p, handle, &snum))
6577 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6578 DEBUG(3, ("security descriptor change denied by existing "
6579 "security descriptor\n"));
6580 return WERR_ACCESS_DENIED;
6583 /* can't delete if builtin */
6584 if (get_a_builtin_ntform(form_name,&tmpForm)) {
6585 return WERR_INVALID_PARAM;
6588 count = get_ntforms(&list);
6589 if(!delete_a_form(&list, form_name, &count, &ret))
6590 return WERR_INVALID_PARAM;
6593 * ChangeID must always be set
6596 if (!get_printer_snum(p,handle, &snum))
6599 status = get_a_printer(&printer, 2, lp_servicename(snum));
6600 if (!W_ERROR_IS_OK(status))
6603 status = mod_a_printer(*printer, 2);
6604 if (!W_ERROR_IS_OK(status))
6608 free_a_printer(&printer, 2);
6614 /****************************************************************************
6615 ****************************************************************************/
6617 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6619 POLICY_HND *handle = &q_u->handle;
6620 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6621 /* uint32 level = q_u->level; - notused. */
6622 FORM *form = &q_u->form;
6623 nt_forms_struct tmpForm;
6625 WERROR status = WERR_OK;
6626 NT_PRINTER_INFO_LEVEL *printer = NULL;
6629 nt_forms_struct *list=NULL;
6630 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6632 DEBUG(5,("spoolss_setform\n"));
6635 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
6639 if (!get_printer_snum(p, handle, &snum))
6642 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6643 DEBUG(3, ("security descriptor change denied by existing "
6644 "security descriptor\n"));
6645 return WERR_ACCESS_DENIED;
6648 /* can't set if builtin */
6649 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6650 return WERR_INVALID_PARAM;
6653 count=get_ntforms(&list);
6654 update_a_form(&list, form, count);
6655 write_ntforms(&list, count);
6658 * ChangeID must always be set
6661 if (!get_printer_snum(p,handle, &snum))
6664 status = get_a_printer(&printer, 2, lp_servicename(snum));
6665 if (!W_ERROR_IS_OK(status))
6668 status = mod_a_printer(*printer, 2);
6669 if (!W_ERROR_IS_OK(status))
6673 free_a_printer(&printer, 2);
6679 /****************************************************************************
6680 enumprintprocessors level 1.
6681 ****************************************************************************/
6682 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6684 PRINTPROCESSOR_1 *info_1=NULL;
6686 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6691 init_unistr(&info_1->name, "winprint");
6693 *needed += spoolss_size_printprocessor_info_1(info_1);
6695 if (!alloc_buffer_size(buffer, *needed))
6696 return WERR_INSUFFICIENT_BUFFER;
6698 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6702 if (*needed > offered) {
6704 return WERR_INSUFFICIENT_BUFFER;
6710 /****************************************************************************
6711 ****************************************************************************/
6713 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6715 /* UNISTR2 *name = &q_u->name; - notused. */
6716 /* UNISTR2 *environment = &q_u->environment; - notused. */
6717 uint32 level = q_u->level;
6718 NEW_BUFFER *buffer = NULL;
6719 uint32 offered = q_u->offered;
6720 uint32 *needed = &r_u->needed;
6721 uint32 *returned = &r_u->returned;
6723 /* that's an [in out] buffer */
6724 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6725 buffer = r_u->buffer;
6727 DEBUG(5,("spoolss_enumprintprocessors\n"));
6730 * Enumerate the print processors ...
6732 * Just reply with "winprint", to keep NT happy
6733 * and I can use my nice printer checker.
6741 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6743 return WERR_UNKNOWN_LEVEL;
6747 /****************************************************************************
6748 enumprintprocdatatypes level 1.
6749 ****************************************************************************/
6750 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6752 PRINTPROCDATATYPE_1 *info_1=NULL;
6754 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6759 init_unistr(&info_1->name, "RAW");
6761 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6763 if (!alloc_buffer_size(buffer, *needed))
6764 return WERR_INSUFFICIENT_BUFFER;
6766 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6770 if (*needed > offered) {
6772 return WERR_INSUFFICIENT_BUFFER;
6778 /****************************************************************************
6779 ****************************************************************************/
6781 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6783 /* UNISTR2 *name = &q_u->name; - notused. */
6784 /* UNISTR2 *processor = &q_u->processor; - notused. */
6785 uint32 level = q_u->level;
6786 NEW_BUFFER *buffer = NULL;
6787 uint32 offered = q_u->offered;
6788 uint32 *needed = &r_u->needed;
6789 uint32 *returned = &r_u->returned;
6791 /* that's an [in out] buffer */
6792 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6793 buffer = r_u->buffer;
6795 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6802 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6804 return WERR_UNKNOWN_LEVEL;
6808 /****************************************************************************
6809 enumprintmonitors level 1.
6810 ****************************************************************************/
6812 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6814 PRINTMONITOR_1 *info_1=NULL;
6816 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6821 init_unistr(&info_1->name, "Local Port");
6823 *needed += spoolss_size_printmonitor_info_1(info_1);
6825 if (!alloc_buffer_size(buffer, *needed))
6826 return WERR_INSUFFICIENT_BUFFER;
6828 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6832 if (*needed > offered) {
6834 return WERR_INSUFFICIENT_BUFFER;
6840 /****************************************************************************
6841 enumprintmonitors level 2.
6842 ****************************************************************************/
6843 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6845 PRINTMONITOR_2 *info_2=NULL;
6847 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6852 init_unistr(&info_2->name, "Local Port");
6853 init_unistr(&info_2->environment, "Windows NT X86");
6854 init_unistr(&info_2->dll_name, "localmon.dll");
6856 *needed += spoolss_size_printmonitor_info_2(info_2);
6858 if (!alloc_buffer_size(buffer, *needed))
6859 return WERR_INSUFFICIENT_BUFFER;
6861 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6865 if (*needed > offered) {
6867 return WERR_INSUFFICIENT_BUFFER;
6873 /****************************************************************************
6874 ****************************************************************************/
6876 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6878 /* UNISTR2 *name = &q_u->name; - notused. */
6879 uint32 level = q_u->level;
6880 NEW_BUFFER *buffer = NULL;
6881 uint32 offered = q_u->offered;
6882 uint32 *needed = &r_u->needed;
6883 uint32 *returned = &r_u->returned;
6885 /* that's an [in out] buffer */
6886 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6887 buffer = r_u->buffer;
6889 DEBUG(5,("spoolss_enumprintmonitors\n"));
6892 * Enumerate the print monitors ...
6894 * Just reply with "Local Port", to keep NT happy
6895 * and I can use my nice printer checker.
6903 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6905 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6907 return WERR_UNKNOWN_LEVEL;
6911 /****************************************************************************
6912 ****************************************************************************/
6913 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6917 JOB_INFO_1 *info_1=NULL;
6919 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6921 if (info_1 == NULL) {
6926 for (i=0; i<count && found==False; i++) {
6927 if (queue[i].job==(int)jobid)
6934 /* NT treats not found as bad param... yet another bad choice */
6935 return WERR_INVALID_PARAM;
6938 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6942 *needed += spoolss_size_job_info_1(info_1);
6944 if (!alloc_buffer_size(buffer, *needed)) {
6946 return WERR_INSUFFICIENT_BUFFER;
6949 smb_io_job_info_1("", buffer, info_1, 0);
6953 if (*needed > offered)
6954 return WERR_INSUFFICIENT_BUFFER;
6960 /****************************************************************************
6961 ****************************************************************************/
6962 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6967 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6970 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6972 ZERO_STRUCTP(info_2);
6974 if (info_2 == NULL) {
6979 for (i=0; i<count && found==False; i++) {
6980 if (queue[i].job==(int)jobid)
6987 /* NT treats not found as bad param... yet another bad choice */
6988 return WERR_INVALID_PARAM;
6991 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6992 if (!W_ERROR_IS_OK(ret)) {
6997 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6999 free_a_printer(&ntprinter, 2);
7002 *needed += spoolss_size_job_info_2(info_2);
7004 if (!alloc_buffer_size(buffer, *needed)) {
7006 return WERR_INSUFFICIENT_BUFFER;
7009 smb_io_job_info_2("", buffer, info_2, 0);
7011 free_job_info_2(info_2);
7014 if (*needed > offered)
7015 return WERR_INSUFFICIENT_BUFFER;
7020 /****************************************************************************
7021 ****************************************************************************/
7023 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
7025 POLICY_HND *handle = &q_u->handle;
7026 uint32 jobid = q_u->jobid;
7027 uint32 level = q_u->level;
7028 NEW_BUFFER *buffer = NULL;
7029 uint32 offered = q_u->offered;
7030 uint32 *needed = &r_u->needed;
7034 print_queue_struct *queue=NULL;
7035 print_status_struct prt_status;
7037 /* that's an [in out] buffer */
7038 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7039 buffer = r_u->buffer;
7041 DEBUG(5,("spoolss_getjob\n"));
7045 if (!get_printer_snum(p, handle, &snum))
7048 count = print_queue_status(snum, &queue, &prt_status);
7050 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7051 count, prt_status.status, prt_status.message));
7055 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
7057 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
7060 return WERR_UNKNOWN_LEVEL;
7064 /********************************************************************
7065 * spoolss_getprinterdataex
7066 ********************************************************************/
7068 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
7070 POLICY_HND *handle = &q_u->handle;
7071 uint32 in_size = q_u->size;
7072 uint32 *type = &r_u->type;
7073 uint32 *out_size = &r_u->size;
7074 uint8 **data = &r_u->data;
7075 uint32 *needed = &r_u->needed;
7078 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7081 DEBUG(4,("_spoolss_getprinterdataex\n"));
7083 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
7084 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
7086 /* in case of problem, return some default values */
7093 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
7095 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7100 /* Is the handle to a printer or to the server? */
7102 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
7104 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7105 return WERR_INVALID_PARAM;
7110 * From MSDN documentation of GetPrinterDataEx: pass request
7111 * to GetPrinterData if key is "PrinterDriverData". This is
7112 * the only key we really support. Other keys to implement:
7118 if (strcmp(key, "PrinterDriverData") != 0)
7119 return WERR_INVALID_PARAM;
7121 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7122 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
7123 type, data, needed, in_size);
7128 DEBUG(5, ("value not found, allocating %d\n", *out_size));
7130 /* reply this param doesn't exist */
7132 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
7138 return WERR_INVALID_PARAM;
7141 if (*needed > *out_size)
7142 return WERR_MORE_DATA;
7147 /********************************************************************
7148 * spoolss_setprinterdata
7149 ********************************************************************/
7151 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
7153 SPOOL_Q_SETPRINTERDATA q_u_local;
7154 SPOOL_R_SETPRINTERDATA r_u_local;
7157 DEBUG(4,("_spoolss_setprinterdataex\n"));
7159 /* From MSDN documentation of SetPrinterDataEx: pass request to
7160 SetPrinterData if key is "PrinterDriverData" */
7162 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7164 if (strcmp(key, "PrinterDriverData") == 0)
7165 return WERR_INVALID_PARAM;
7167 ZERO_STRUCT(q_u_local);
7168 ZERO_STRUCT(r_u_local);
7170 /* make a copy to call _spoolss_setprinterdata() */
7172 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7173 copy_unistr2(&q_u_local.value, &q_u->value);
7174 q_u_local.type = q_u->type;
7175 q_u_local.max_len = q_u->max_len;
7176 q_u_local.data = q_u->data;
7177 q_u_local.real_len = q_u->real_len;
7178 q_u_local.numeric_data = q_u->numeric_data;
7180 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
7183 /********************************************************************
7184 * spoolss_enumprinterkey
7185 ********************************************************************/
7187 /* constants for EnumPrinterKey() */
7188 #define ENUMERATED_KEY_SIZE 19
7190 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
7193 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
7196 char *PrinterKey = "PrinterDriverData";
7198 DEBUG(4,("_spoolss_enumprinterkey\n"));
7200 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7203 * we only support enumating all keys (key == "")
7204 * Of course, the only key we support is the "PrinterDriverData"
7207 if (strlen(key) == 0)
7209 r_u->needed = ENUMERATED_KEY_SIZE *2;
7210 if (q_u->size < r_u->needed)
7211 return WERR_MORE_DATA;
7214 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
7216 enumkeys[i] = (uint16)(*ptr);
7220 /* tag of with 2 '\0's */
7221 enumkeys[i++] = '\0';
7224 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
7225 return WERR_BADFILE;
7230 /* The "PrinterDriverData" key should have no subkeys */
7231 if (strcmp(key, PrinterKey) == 0)
7234 if (q_u->size < r_u->needed)
7235 return WERR_MORE_DATA;
7237 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
7238 return WERR_BADFILE;
7244 /* The return value for an unknown key is documented in MSDN
7245 EnumPrinterKey description */
7246 return WERR_BADFILE;
7249 /********************************************************************
7250 * spoolss_enumprinterdataex
7251 ********************************************************************/
7253 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
7255 POLICY_HND *handle = &q_u->handle;
7256 uint32 in_size = q_u->size;
7259 NT_PRINTER_INFO_LEVEL *printer = NULL;
7260 PRINTER_ENUM_VALUES *enum_values = NULL;
7262 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7271 DEBUG(4,("_spoolss_enumprinterdataex\n"));
7274 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
7280 * The only key we support is "PrinterDriverData". This should return
7281 > an array of all the key/value pairs returned by EnumPrinterDataSee
7282 * _spoolss_getprinterdataex() for details --jerry
7285 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7286 if (strcmp(key, "PrinterDriverData") != 0)
7288 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
7289 return WERR_INVALID_PARAM;
7293 if (!get_printer_snum(p,handle, &snum))
7296 ZERO_STRUCT(printer);
7297 result = get_a_printer(&printer, 2, lp_servicename(snum));
7298 if (!W_ERROR_IS_OK(result))
7303 * loop through all params and build the array to pass
7304 * back to the client
7311 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
7313 PRINTER_ENUM_VALUES *ptr;
7316 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7318 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7320 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7321 result = WERR_NOMEM;
7327 init_unistr(&enum_values[num_entries].valuename, value);
7328 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7329 enum_values[num_entries].type = type;
7332 * NULL terminate REG_SZ
7333 * FIXME!!! We should not be correctly problems in the way
7334 * we store PrinterData here. Need to investogate
7335 * SetPrinterData[Ex] --jerry
7338 if (type == REG_SZ) {
7339 /* fix alignment if the string was stored
7340 in a bizarre fashion */
7341 if ((data_len % 2) == 0)
7344 add_len = data_len % 2;
7347 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7348 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7349 result = WERR_NOMEM;
7352 memcpy(enum_values[num_entries].data, data, data_len);
7353 enum_values[num_entries].data_len = data_len + add_len;
7355 /* keep track of the size of the array in bytes */
7357 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7363 r_u->needed = needed;
7364 r_u->returned = num_entries;
7366 if (needed > in_size) {
7367 result = WERR_MORE_DATA;
7371 /* copy data into the reply */
7373 r_u->ctr.size = r_u->needed;
7374 r_u->ctr.size_of_array = r_u->returned;
7375 r_u->ctr.values = enum_values;
7380 free_a_printer(&printer, 2);
7385 /****************************************************************************
7386 ****************************************************************************/
7388 /* Disabled because it doesn't fix the bug I am looking at but it would be
7389 a shame to throw away the code. -tpot */
7393 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
7395 init_unistr(&info->name, name);
7398 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
7399 UNISTR2 *environment,
7406 pstring short_archi;
7407 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
7409 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
7411 if (get_short_archi(short_archi, long_archi)==FALSE)
7412 return WERR_INVALID_ENVIRONMENT;
7414 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
7417 /* Not sure what to return here - are UNC names valid here?.
7418 Windows returns the string: C:\WINNT\System32\spool\PRTPROCS\W32X86
7419 which is pretty bogus for a RPC. */
7421 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7423 DEBUG(4,("print processor directory: [%s]\n", path));
7425 fill_printprocessordirectory_1(info, path);
7427 *needed += spoolss_size_printprocessordirectory_info_1(info);
7429 if (!alloc_buffer_size(buffer, *needed)) {
7431 return WERR_INSUFFICIENT_BUFFER;
7434 smb_io_printprocessordirectory_1("", buffer, info, 0);
7438 if (*needed > offered)
7439 return WERR_INSUFFICIENT_BUFFER;
7444 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
7446 uint32 level = q_u->level;
7447 NEW_BUFFER *buffer = NULL;
7448 uint32 offered = q_u->offered;
7449 uint32 *needed = &r_u->needed;
7451 /* that's an [in out] buffer */
7452 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7453 buffer = r_u->buffer;
7455 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7461 return getprintprocessordirectory_level_1
7462 (&q_u->name, &q_u->environment, buffer, offered, needed);
7464 return WERR_UNKNOWN_LEVEL;
7467 return WERR_ACCESS_DENIED;