2 * Unix SMB/Netbios implementation.
4 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-2000,
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7 * Copyright (C) Jean François Micouleau 1998-2000.
8 * Copyright (C) Jeremy Allison 2001.
9 * Copyright (C) Gerald Carter 2000-2001.
10 * Copyright (C) Tim Potter 2001.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
32 #ifndef MAX_OPEN_PRINTER_EXS
33 #define MAX_OPEN_PRINTER_EXS 50
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 BOOL document_started;
54 int jobid; /* jobid in printing backend */
58 fstring printerservername;
67 SPOOL_NOTIFY_OPTION *option;
68 POLICY_HND client_hnd;
69 uint32 client_connected;
77 typedef struct _counter_printer_0 {
85 static ubi_dlList counter_list;
87 static struct cli_state cli;
88 static uint32 smb_connections=0;
90 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
92 /* translate between internal status numbers and NT status numbers */
93 static int nt_printj_status(int v)
99 return JOB_STATUS_PAUSED;
101 return JOB_STATUS_SPOOLING;
103 return JOB_STATUS_PRINTING;
105 return JOB_STATUS_ERROR;
107 return JOB_STATUS_DELETING;
109 return JOB_STATUS_OFFLINE;
111 return JOB_STATUS_PAPEROUT;
113 return JOB_STATUS_PRINTED;
115 return JOB_STATUS_DELETED;
117 return JOB_STATUS_BLOCKED;
118 case LPQ_USER_INTERVENTION:
119 return JOB_STATUS_USER_INTERVENTION;
124 static int nt_printq_status(int v)
128 return PRINTER_STATUS_PAUSED;
137 /****************************************************************************
138 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
139 ****************************************************************************/
141 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
146 SAFE_FREE((*pp)->ctr.type);
150 /***************************************************************************
151 Disconnect from the client
152 ****************************************************************************/
154 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
158 /* weird if the test succeds !!! */
159 if (smb_connections==0) {
160 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
164 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
165 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
167 /* if it's the last connection, deconnect the IPC$ share */
168 if (smb_connections==1) {
169 if(!spoolss_disconnect_from_client(&cli))
172 message_deregister(MSG_PRINTER_NOTIFY);
178 /****************************************************************************
179 Functions to free a printer entry datastruct.
180 ****************************************************************************/
182 static void free_printer_entry(void *ptr)
184 Printer_entry *Printer = (Printer_entry *)ptr;
186 if (Printer->notify.client_connected==True)
187 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
189 Printer->notify.flags=0;
190 Printer->notify.options=0;
191 Printer->notify.localmachine[0]='\0';
192 Printer->notify.printerlocal=0;
193 free_spool_notify_option(&Printer->notify.option);
194 Printer->notify.option=NULL;
195 Printer->notify.client_connected=False;
200 /****************************************************************************
201 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
202 ****************************************************************************/
204 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
206 SPOOL_NOTIFY_OPTION *new_sp = NULL;
211 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
218 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
220 if (!new_sp->ctr.type) {
229 /****************************************************************************
230 find printer index by handle
231 ****************************************************************************/
233 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
235 Printer_entry *find_printer = NULL;
237 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
238 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
245 /****************************************************************************
246 close printer index by handle
247 ****************************************************************************/
249 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
251 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
254 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
258 close_policy_hnd(p, hnd);
263 /****************************************************************************
264 delete a printer given a handle
265 ****************************************************************************/
266 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
268 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
271 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
275 if (del_a_printer(Printer->dev.handlename) != 0) {
276 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
280 /* Check calling user has permission to delete printer. Note that
281 since we set the snum parameter to -1 only administrators can
282 delete the printer. This stops people with the Full Control
283 permission from deleting the printer. */
285 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
286 DEBUG(3, ("printer delete denied by security descriptor\n"));
287 return WERR_ACCESS_DENIED;
290 if (*lp_deleteprinter_cmd()) {
292 char *cmd = lp_deleteprinter_cmd();
297 /* Printer->dev.handlename equals portname equals sharename */
298 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
299 Printer->dev.handlename);
301 DEBUG(10,("Running [%s]\n", command));
302 ret = smbrun(command, NULL);
304 return WERR_BADFID; /* What to return here? */
306 DEBUGADD(10,("returned [%d]\n", ret));
308 /* Send SIGHUP to process group... is there a better way? */
311 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
315 return WERR_ACCESS_DENIED;
321 /****************************************************************************
322 return the snum of a printer corresponding to an handle
323 ****************************************************************************/
324 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
326 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
329 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
333 switch (Printer->printer_type) {
334 case PRINTER_HANDLE_IS_PRINTER:
335 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
336 *number = print_queue_snum(Printer->dev.handlename);
337 return (*number != -1);
338 case PRINTER_HANDLE_IS_PRINTSERVER:
345 /****************************************************************************
346 set printer handle type.
347 ****************************************************************************/
348 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
350 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
353 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
357 DEBUG(4,("Setting printer access=%x\n", access_required));
358 Printer->access = access_required;
362 /****************************************************************************
363 Set printer handle type.
364 Check if it's \\server or \\server\printer
365 ****************************************************************************/
367 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
369 DEBUG(3,("Setting printer type=%s\n", handlename));
371 if ( strlen(handlename) < 3 ) {
372 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
376 /* it's a print server */
377 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
378 DEBUGADD(4,("Printer is a print server\n"));
379 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
383 DEBUGADD(4,("Printer is a printer\n"));
384 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
390 /****************************************************************************
391 Set printer handle name.
392 ****************************************************************************/
394 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
396 NT_PRINTER_INFO_LEVEL *printer = NULL;
398 int n_services=lp_numservices();
402 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
404 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
405 ZERO_STRUCT(Printer->dev.printerservername);
406 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
410 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
413 if (*handlename=='\\') {
414 aprinter=strchr_m(handlename+2, '\\');
421 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
424 * store the Samba share name in it
425 * in back we have the long printer name
426 * need to iterate all the snum and do a
427 * get_a_printer each time to find the printer
428 * faster to do it here than later.
431 for (snum=0;snum<n_services && found==False;snum++) {
434 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
437 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
439 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
442 printername=strchr_m(printer->info_2->printername+2, '\\');
445 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
446 printer->info_2->printername, aprinter ));
448 if ( strlen(printername) != strlen(aprinter) ) {
449 free_a_printer(&printer, 2);
453 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
454 free_a_printer(&printer, 2);
462 * if we haven't found a printer with the given handlename
463 * then it can be a share name as you can open both \\server\printer and
468 * we still check if the printer description file exists as NT won't be happy
469 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
473 DEBUGADD(5,("Printer not found, checking for share now\n"));
475 for (snum=0;snum<n_services && found==False;snum++) {
477 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
480 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
482 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
485 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
486 printer->info_2->printername, aprinter ));
488 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
489 free_a_printer(&printer, 2);
493 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
494 free_a_printer(&printer, 2);
503 DEBUGADD(4,("Printer not found\n"));
508 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
509 printer->info_2->printername, lp_servicename(snum),snum));
511 ZERO_STRUCT(Printer->dev.handlename);
512 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
514 free_a_printer(&printer, 2);
519 /****************************************************************************
520 find first available printer slot. creates a printer handle for you.
521 ****************************************************************************/
523 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
525 Printer_entry *new_printer;
527 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
529 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
532 ZERO_STRUCTP(new_printer);
534 new_printer->notify.option=NULL;
536 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
537 SAFE_FREE(new_printer);
541 if (!set_printer_hnd_printertype(new_printer, name)) {
542 close_printer_handle(p, hnd);
546 if (!set_printer_hnd_name(new_printer, name)) {
547 close_printer_handle(p, hnd);
551 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
556 /********************************************************************
557 Return True is the handle is a print server.
558 ********************************************************************/
560 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
562 Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
567 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
573 /****************************************************************************
574 allocate more memory for a BUFFER.
575 ****************************************************************************/
576 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
584 /* damn, I'm doing the reverse operation of prs_grow() :) */
585 if (buffer_size < prs_data_size(ps))
588 extra_space = buffer_size - prs_data_size(ps);
591 * save the offset and move to the end of the buffer
592 * prs_grow() checks the extra_space against the offset
594 old_offset=prs_offset(ps);
595 prs_set_offset(ps, prs_data_size(ps));
597 if (!prs_grow(ps, extra_space))
600 prs_set_offset(ps, old_offset);
602 buffer->string_at_end=prs_data_size(ps);
607 /***************************************************************************
608 receive the notify message
609 ****************************************************************************/
611 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
615 struct pipes_struct *p;
617 struct handle_list *hl;
620 fstrcpy(printer,buf);
623 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
627 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
630 * We need to enumerate all printers. The handle list is shared
631 * across pipes of the same name, so just find the first open
636 for ( p = get_first_pipe(); p; p = get_next_pipe(p)) {
637 if (strequal(p->name, "spoolss")) {
638 hl = p->pipe_handles;
644 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
648 /* Iterate the printer list on this pipe. */
649 for (pol = hl->Policy; pol; pol = pol->next ) {
650 Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
656 * if the entry is the given printer or if it's a printerserver
657 * we send the message
660 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
661 if (strcmp(find_printer->dev.handlename, printer))
664 if (find_printer->notify.client_connected==True)
665 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
669 /***************************************************************************
671 ****************************************************************************/
672 static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle)
676 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
679 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
683 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
684 fstrcpy(printer, Printer->dev.handlename);
686 fstrcpy(printer, "");
688 /*srv_spoolss_receive_message(printer);*/
689 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
691 broadcast_printer_notify(printer);
696 /********************************************************************
697 * spoolss_open_printer
699 * called from the spoolss dispatcher
700 ********************************************************************/
702 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
705 WERROR result = WERR_OK;
708 UNISTR2 *printername = NULL;
709 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
710 /* uint32 user_switch = q_u->user_switch; - notused */
711 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
712 POLICY_HND *handle = &r_u->handle;
716 struct current_user user;
718 if (q_u->printername_ptr != 0)
719 printername = &q_u->printername;
721 if (printername == NULL)
722 return WERR_INVALID_PRINTER_NAME;
724 /* some sanity check because you can open a printer or a print server */
725 /* aka: \\server\printer or \\server */
726 unistr2_to_ascii(name, printername, sizeof(name)-1);
728 DEBUGADD(3,("checking name: %s\n",name));
730 if (!open_printer_hnd(p, handle, name))
731 return WERR_INVALID_PRINTER_NAME;
734 if (printer_default->datatype_ptr != NULL)
736 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
737 set_printer_hnd_datatype(handle, datatype);
740 set_printer_hnd_datatype(handle, "");
743 if (!set_printer_hnd_accesstype(p, handle, printer_default->access_required)) {
744 close_printer_handle(p, handle);
745 return WERR_ACCESS_DENIED;
749 First case: the user is opening the print server:
751 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
752 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
754 Then both Win2k and WinNT clients try an OpenPrinterEx with
755 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
756 or if the user is listed in the smb.conf printer admin parameter.
758 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
759 client view printer folder, but does not show the MSAPW.
761 Note: this test needs code to check access rights here too. Jeremy
762 could you look at this?
765 Second case: the user is opening a printer:
766 NT doesn't let us connect to a printer if the connecting user
767 doesn't have print permission.
771 get_current_user(&user, p);
773 if (handle_is_printserver(p, handle)) {
774 if (printer_default->access_required == 0) {
777 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
779 /* Printserver handles use global struct... */
782 if (!lp_ms_add_printer_wizard()) {
783 close_printer_handle(p, handle);
784 return WERR_ACCESS_DENIED;
786 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
790 close_printer_handle(p, handle);
791 return WERR_ACCESS_DENIED;
797 /* NT doesn't let us connect to a printer if the connecting user
798 doesn't have print permission. */
800 if (!get_printer_snum(p, handle, &snum))
803 /* map an empty access mask to the minimum access mask */
804 if (printer_default->access_required == 0x0)
805 printer_default->access_required = PRINTER_ACCESS_USE;
809 * If we are not serving the printer driver for this printer,
810 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
811 * will keep NT clients happy --jerry
814 if (lp_use_client_driver(snum)
815 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
817 printer_default->access_required = PRINTER_ACCESS_USE;
820 if (!print_access_check(&user, snum, printer_default->access_required)) {
821 DEBUG(3, ("access DENIED for printer open\n"));
822 close_printer_handle(p, handle);
823 return WERR_ACCESS_DENIED;
827 * If we have a default device pointer in the
828 * printer_default struct, then we need to get
829 * the printer info from the tdb and if there is
830 * no default devicemode there then we do a *SET*
831 * here ! This is insanity.... JRA.
835 * If the openprinterex rpc call contains a devmode,
836 * it's a per-user one. This per-user devmode is derivated
837 * from the global devmode. Openprinterex() contains a per-user
838 * devmode for when you do EMF printing and spooling.
839 * In the EMF case, the NT workstation is only doing half the job
840 * of rendering the page. The other half is done by running the printer
841 * driver on the server.
842 * The EMF file doesn't contain the page description (paper size, orientation, ...).
843 * The EMF file only contains what is to be printed on the page.
844 * So in order for the server to know how to print, the NT client sends
845 * a devicemode attached to the openprinterex call.
846 * But this devicemode is short lived, it's only valid for the current print job.
848 * If Samba would have supported EMF spooling, this devicemode would
849 * have been attached to the handle, to sent it to the driver to correctly
850 * rasterize the EMF file.
852 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
853 * we just act as a pass-thru between windows and the printer.
855 * In order to know that Samba supports only RAW spooling, NT has to call
856 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
857 * and until NT sends a RAW job, we refuse it.
859 * But to call getprinter() or startdoc(), you first need a valid handle,
860 * and to get an handle you have to call openprintex(). Hence why you have
861 * a devicemode in the openprinterex() call.
864 * Differences between NT4 and NT 2000.
867 * On NT4, you only have a global devicemode. This global devicemode can be changed
868 * by the administrator (or by a user with enough privs). Everytime a user
869 * wants to print, the devicemode is resetted to the default. In Word, everytime
870 * you print, the printer's characteristics are always reset to the global devicemode.
874 * In W2K, there is the notion of per-user devicemode. The first time you use
875 * a printer, a per-user devicemode is build from the global devicemode.
876 * If you change your per-user devicemode, it is saved in the registry, under the
877 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
878 * printer preferences available.
880 * To change the per-user devicemode: it's the "Printing Preferences ..." button
881 * on the General Tab of the printer properties windows.
883 * To change the global devicemode: it's the "Printing Defaults..." button
884 * on the Advanced Tab of the printer properties window.
892 if (printer_default->devmode_cont.devmode != NULL) {
893 result = printer_write_default_dev( snum, printer_default);
895 close_printer_handle(p, handle);
905 /****************************************************************************
906 ****************************************************************************/
907 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
908 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
914 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
923 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
924 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
930 printer->info_3=NULL;
931 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
935 printer->info_6=NULL;
936 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
946 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
947 NT_DEVICEMODE **pp_nt_devmode)
949 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
952 * Ensure nt_devmode is a valid pointer
953 * as we will be overwriting it.
956 if (nt_devmode == NULL) {
957 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
958 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
962 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
963 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
965 nt_devmode->specversion=devmode->specversion;
966 nt_devmode->driverversion=devmode->driverversion;
967 nt_devmode->size=devmode->size;
968 nt_devmode->fields=devmode->fields;
969 nt_devmode->orientation=devmode->orientation;
970 nt_devmode->papersize=devmode->papersize;
971 nt_devmode->paperlength=devmode->paperlength;
972 nt_devmode->paperwidth=devmode->paperwidth;
973 nt_devmode->scale=devmode->scale;
974 nt_devmode->copies=devmode->copies;
975 nt_devmode->defaultsource=devmode->defaultsource;
976 nt_devmode->printquality=devmode->printquality;
977 nt_devmode->color=devmode->color;
978 nt_devmode->duplex=devmode->duplex;
979 nt_devmode->yresolution=devmode->yresolution;
980 nt_devmode->ttoption=devmode->ttoption;
981 nt_devmode->collate=devmode->collate;
983 nt_devmode->logpixels=devmode->logpixels;
984 nt_devmode->bitsperpel=devmode->bitsperpel;
985 nt_devmode->pelswidth=devmode->pelswidth;
986 nt_devmode->pelsheight=devmode->pelsheight;
987 nt_devmode->displayflags=devmode->displayflags;
988 nt_devmode->displayfrequency=devmode->displayfrequency;
989 nt_devmode->icmmethod=devmode->icmmethod;
990 nt_devmode->icmintent=devmode->icmintent;
991 nt_devmode->mediatype=devmode->mediatype;
992 nt_devmode->dithertype=devmode->dithertype;
993 nt_devmode->reserved1=devmode->reserved1;
994 nt_devmode->reserved2=devmode->reserved2;
995 nt_devmode->panningwidth=devmode->panningwidth;
996 nt_devmode->panningheight=devmode->panningheight;
999 * Only change private and driverextra if the incoming devmode
1000 * has a new one. JRA.
1003 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1004 SAFE_FREE(nt_devmode->private);
1005 nt_devmode->driverextra=devmode->driverextra;
1006 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1008 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1011 *pp_nt_devmode = nt_devmode;
1016 /********************************************************************
1017 * _spoolss_enddocprinter_internal.
1018 ********************************************************************/
1020 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1022 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1025 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1029 Printer->document_started=False;
1030 print_job_end(Printer->jobid,True);
1031 /* error codes unhandled so far ... */
1036 /********************************************************************
1037 * api_spoolss_closeprinter
1038 ********************************************************************/
1040 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1042 POLICY_HND *handle = &q_u->handle;
1044 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1046 if (Printer && Printer->document_started)
1047 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1049 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1051 if (!close_printer_handle(p, handle))
1057 /********************************************************************
1058 * api_spoolss_deleteprinter
1060 ********************************************************************/
1062 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1064 POLICY_HND *handle = &q_u->handle;
1065 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1068 if (Printer && Printer->document_started)
1069 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1071 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1073 result = delete_printer_handle(p, handle);
1075 if (W_ERROR_IS_OK(result)) {
1076 srv_spoolss_sendnotify(p, handle);
1082 /*******************************************************************
1083 * static function to lookup the version id corresponding to an
1084 * long architecture string
1085 ******************************************************************/
1086 static int get_version_id (char * arch)
1089 struct table_node archi_table[]= {
1091 {"Windows 4.0", "WIN40", 0 },
1092 {"Windows NT x86", "W32X86", 2 },
1093 {"Windows NT R4000", "W32MIPS", 2 },
1094 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1095 {"Windows NT PowerPC", "W32PPC", 2 },
1099 for (i=0; archi_table[i].long_archi != NULL; i++)
1101 if (strcmp(arch, archi_table[i].long_archi) == 0)
1102 return (archi_table[i].version);
1108 /********************************************************************
1109 * _spoolss_deleteprinterdriver
1111 * We currently delete the driver for the architecture only.
1112 * This can leave the driver for other archtectures. However,
1113 * since every printer associates a "Windows NT x86" driver name
1114 * and we cannot delete that one while it is in use, **and** since
1115 * it is impossible to assign a driver to a Samba printer without
1116 * having the "Windows NT x86" driver installed,...
1118 * ....we should not get into trouble here.
1121 ********************************************************************/
1123 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
1124 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1128 NT_PRINTER_DRIVER_INFO_LEVEL info;
1131 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1132 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1134 /* check that we have a valid driver name first */
1135 if ((version=get_version_id(arch)) == -1) {
1136 /* this is what NT returns */
1137 return WERR_INVALID_ENVIRONMENT;
1141 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1142 return WERR_UNKNOWN_PRINTER_DRIVER;
1146 if (printer_driver_in_use(arch, driver))
1148 return WERR_PRINTER_DRIVER_IN_USE;
1151 return delete_printer_driver(info.info_3);
1155 /********************************************************************
1156 GetPrinterData on a printer server Handle.
1157 ********************************************************************/
1158 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1162 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1164 if (!strcmp(value, "BeepEnabled")) {
1166 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1168 SIVAL(*data, 0, 0x01);
1173 if (!strcmp(value, "EventLog")) {
1175 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1177 SIVAL(*data, 0, 0x1B);
1182 if (!strcmp(value, "NetPopup")) {
1184 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1186 SIVAL(*data, 0, 0x01);
1191 if (!strcmp(value, "MajorVersion")) {
1193 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1195 SIVAL(*data, 0, 0x02);
1200 if (!strcmp(value, "DefaultSpoolDirectory")) {
1201 pstring string="You are using a Samba server";
1203 *needed = 2*(strlen(string)+1);
1204 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1206 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1208 /* it's done by hand ready to go on the wire */
1209 for (i=0; i<strlen(string); i++) {
1210 (*data)[2*i]=string[i];
1211 (*data)[2*i+1]='\0';
1216 if (!strcmp(value, "Architecture")) {
1217 pstring string="Windows NT x86";
1219 *needed = 2*(strlen(string)+1);
1220 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1222 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1223 for (i=0; i<strlen(string); i++) {
1224 (*data)[2*i]=string[i];
1225 (*data)[2*i+1]='\0';
1233 /********************************************************************
1234 GetPrinterData on a printer Handle.
1235 ********************************************************************/
1236 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1237 fstring value, uint32 *type,
1238 uint8 **data, uint32 *needed, uint32 in_size )
1240 NT_PRINTER_INFO_LEVEL *printer = NULL;
1244 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1246 DEBUG(5,("getprinterdata_printer\n"));
1249 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1253 if(!get_printer_snum(p, handle, &snum))
1256 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1259 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1260 free_a_printer(&printer, 2);
1264 free_a_printer(&printer, 2);
1266 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1269 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1273 memset(*data, 0, in_size *sizeof(uint8));
1274 /* copy the min(in_size, len) */
1275 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1282 DEBUG(5,("getprinterdata_printer:copy done\n"));
1289 /********************************************************************
1290 * spoolss_getprinterdata
1291 ********************************************************************/
1293 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1295 POLICY_HND *handle = &q_u->handle;
1296 UNISTR2 *valuename = &q_u->valuename;
1297 uint32 in_size = q_u->size;
1298 uint32 *type = &r_u->type;
1299 uint32 *out_size = &r_u->size;
1300 uint8 **data = &r_u->data;
1301 uint32 *needed = &r_u->needed;
1305 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1308 * Reminder: when it's a string, the length is in BYTES
1309 * even if UNICODE is negociated.
1316 /* in case of problem, return some default values */
1320 DEBUG(4,("_spoolss_getprinterdata\n"));
1323 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1325 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1329 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1331 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1332 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1334 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1337 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1338 /* reply this param doesn't exist */
1340 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1346 return WERR_INVALID_PARAM;
1349 if (*needed > *out_size)
1350 return WERR_STATUS_MORE_ENTRIES;
1355 /***************************************************************************
1356 connect to the client
1357 ****************************************************************************/
1358 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1363 * If it's the first connection, contact the client
1364 * and connect to the IPC$ share anonumously
1366 if (smb_connections==0) {
1367 fstring unix_printer;
1369 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1371 if(!spoolss_connect_to_client(&cli, unix_printer))
1373 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1379 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1385 /********************************************************************
1387 * ReplyFindFirstPrinterChangeNotifyEx
1389 * jfmxxxx: before replying OK: status=0
1390 * should do a rpc call to the workstation asking ReplyOpenPrinter
1391 * have to code it, later.
1393 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1394 * called from api_spoolss_rffpcnex
1395 ********************************************************************/
1397 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1399 POLICY_HND *handle = &q_u->handle;
1400 uint32 flags = q_u->flags;
1401 uint32 options = q_u->options;
1402 UNISTR2 *localmachine = &q_u->localmachine;
1403 uint32 printerlocal = q_u->printerlocal;
1404 SPOOL_NOTIFY_OPTION *option = q_u->option;
1406 /* store the notify value in the printer struct */
1408 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1411 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1415 Printer->notify.flags=flags;
1416 Printer->notify.options=options;
1417 Printer->notify.printerlocal=printerlocal;
1419 if (Printer->notify.option)
1420 free_spool_notify_option(&Printer->notify.option);
1422 Printer->notify.option=dup_spool_notify_option(option);
1424 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1426 /* connect to the client machine and send a ReplyOpenPrinter */
1427 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1428 Printer->notify.printerlocal, 1,
1429 &Printer->notify.client_hnd))
1430 Printer->notify.client_connected=True;
1435 /*******************************************************************
1436 * fill a notify_info_data with the servername
1437 ********************************************************************/
1439 static void spoolss_notify_server_name(int snum,
1440 SPOOL_NOTIFY_INFO_DATA *data,
1441 print_queue_struct *queue,
1442 NT_PRINTER_INFO_LEVEL *printer,
1443 TALLOC_CTX *mem_ctx)
1445 pstring temp_name, temp;
1448 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
1450 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
1452 data->notify_data.data.length = len / 2;
1453 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1455 if (!data->notify_data.data.string) {
1456 data->notify_data.data.length = 0;
1460 memcpy(data->notify_data.data.string, temp, len);
1463 /*******************************************************************
1464 * fill a notify_info_data with the printername (not including the servername).
1465 ********************************************************************/
1466 static void spoolss_notify_printer_name(int snum,
1467 SPOOL_NOTIFY_INFO_DATA *data,
1468 print_queue_struct *queue,
1469 NT_PRINTER_INFO_LEVEL *printer,
1470 TALLOC_CTX *mem_ctx)
1475 /* the notify name should not contain the \\server\ part */
1476 char *p = strrchr_m(printer->info_2->printername, '\\');
1479 p = printer->info_2->printername;
1484 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
1485 data->notify_data.data.length = len / 2;
1486 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1488 if (!data->notify_data.data.string) {
1489 data->notify_data.data.length = 0;
1493 memcpy(data->notify_data.data.string, temp, len);
1496 /*******************************************************************
1497 * fill a notify_info_data with the servicename
1498 ********************************************************************/
1499 static void spoolss_notify_share_name(int snum,
1500 SPOOL_NOTIFY_INFO_DATA *data,
1501 print_queue_struct *queue,
1502 NT_PRINTER_INFO_LEVEL *printer,
1503 TALLOC_CTX *mem_ctx)
1508 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
1510 data->notify_data.data.length = len / 2;
1511 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1513 if (!data->notify_data.data.string) {
1514 data->notify_data.data.length = 0;
1518 memcpy(data->notify_data.data.string, temp, len);
1521 /*******************************************************************
1522 * fill a notify_info_data with the port name
1523 ********************************************************************/
1524 static void spoolss_notify_port_name(int snum,
1525 SPOOL_NOTIFY_INFO_DATA *data,
1526 print_queue_struct *queue,
1527 NT_PRINTER_INFO_LEVEL *printer,
1528 TALLOC_CTX *mem_ctx)
1533 /* even if it's strange, that's consistant in all the code */
1535 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
1537 data->notify_data.data.length = len / 2;
1538 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1540 if (!data->notify_data.data.string) {
1541 data->notify_data.data.length = 0;
1545 memcpy(data->notify_data.data.string, temp, len);
1548 /*******************************************************************
1549 * fill a notify_info_data with the printername
1550 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1551 * but it doesn't exist, have to see what to do
1552 ********************************************************************/
1553 static void spoolss_notify_driver_name(int snum,
1554 SPOOL_NOTIFY_INFO_DATA *data,
1555 print_queue_struct *queue,
1556 NT_PRINTER_INFO_LEVEL *printer,
1557 TALLOC_CTX *mem_ctx)
1562 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
1563 data->notify_data.data.length = len / 2;
1564 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1566 if (!data->notify_data.data.string) {
1567 data->notify_data.data.length = 0;
1571 memcpy(data->notify_data.data.string, temp, len);
1574 /*******************************************************************
1575 * fill a notify_info_data with the comment
1576 ********************************************************************/
1577 static void spoolss_notify_comment(int snum,
1578 SPOOL_NOTIFY_INFO_DATA *data,
1579 print_queue_struct *queue,
1580 NT_PRINTER_INFO_LEVEL *printer,
1581 TALLOC_CTX *mem_ctx)
1586 if (*printer->info_2->comment == '\0')
1587 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
1590 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
1592 data->notify_data.data.length = len / 2;
1593 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1595 if (!data->notify_data.data.string) {
1596 data->notify_data.data.length = 0;
1600 memcpy(data->notify_data.data.string, temp, len);
1603 /*******************************************************************
1604 * fill a notify_info_data with the comment
1605 * jfm:xxxx incorrect, have to create a new smb.conf option
1606 * location = "Room 1, floor 2, building 3"
1607 ********************************************************************/
1608 static void spoolss_notify_location(int snum,
1609 SPOOL_NOTIFY_INFO_DATA *data,
1610 print_queue_struct *queue,
1611 NT_PRINTER_INFO_LEVEL *printer,
1612 TALLOC_CTX *mem_ctx)
1617 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
1619 data->notify_data.data.length = len / 2;
1620 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1622 if (!data->notify_data.data.string) {
1623 data->notify_data.data.length = 0;
1627 memcpy(data->notify_data.data.string, temp, len);
1630 /*******************************************************************
1631 * fill a notify_info_data with the device mode
1632 * jfm:xxxx don't to it for know but that's a real problem !!!
1633 ********************************************************************/
1634 static void spoolss_notify_devmode(int snum,
1635 SPOOL_NOTIFY_INFO_DATA *data,
1636 print_queue_struct *queue,
1637 NT_PRINTER_INFO_LEVEL *printer,
1638 TALLOC_CTX *mem_ctx)
1642 /*******************************************************************
1643 * fill a notify_info_data with the separator file name
1644 * jfm:xxxx just return no file could add an option to smb.conf
1645 * separator file = "separator.txt"
1646 ********************************************************************/
1647 static void spoolss_notify_sepfile(int snum,
1648 SPOOL_NOTIFY_INFO_DATA *data,
1649 print_queue_struct *queue,
1650 NT_PRINTER_INFO_LEVEL *printer,
1651 TALLOC_CTX *mem_ctx)
1656 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
1658 data->notify_data.data.length = len / 2;
1659 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1661 if (!data->notify_data.data.string) {
1662 data->notify_data.data.length = 0;
1666 memcpy(data->notify_data.data.string, temp, len);
1669 /*******************************************************************
1670 * fill a notify_info_data with the print processor
1671 * jfm:xxxx return always winprint to indicate we don't do anything to it
1672 ********************************************************************/
1673 static void spoolss_notify_print_processor(int snum,
1674 SPOOL_NOTIFY_INFO_DATA *data,
1675 print_queue_struct *queue,
1676 NT_PRINTER_INFO_LEVEL *printer,
1677 TALLOC_CTX *mem_ctx)
1682 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
1684 data->notify_data.data.length = len / 2;
1685 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1687 if (!data->notify_data.data.string) {
1688 data->notify_data.data.length = 0;
1692 memcpy(data->notify_data.data.string, temp, len);
1695 /*******************************************************************
1696 * fill a notify_info_data with the print processor options
1697 * jfm:xxxx send an empty string
1698 ********************************************************************/
1699 static void spoolss_notify_parameters(int snum,
1700 SPOOL_NOTIFY_INFO_DATA *data,
1701 print_queue_struct *queue,
1702 NT_PRINTER_INFO_LEVEL *printer,
1703 TALLOC_CTX *mem_ctx)
1708 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
1710 data->notify_data.data.length = len / 2;
1711 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1713 if (!data->notify_data.data.string) {
1714 data->notify_data.data.length = 0;
1718 memcpy(data->notify_data.data.string, temp, len);
1721 /*******************************************************************
1722 * fill a notify_info_data with the data type
1723 * jfm:xxxx always send RAW as data type
1724 ********************************************************************/
1725 static void spoolss_notify_datatype(int snum,
1726 SPOOL_NOTIFY_INFO_DATA *data,
1727 print_queue_struct *queue,
1728 NT_PRINTER_INFO_LEVEL *printer,
1729 TALLOC_CTX *mem_ctx)
1734 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
1736 data->notify_data.data.length = len / 2;
1737 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1739 if (!data->notify_data.data.string) {
1740 data->notify_data.data.length = 0;
1744 memcpy(data->notify_data.data.string, temp, len);
1747 /*******************************************************************
1748 * fill a notify_info_data with the security descriptor
1749 * jfm:xxxx send an null pointer to say no security desc
1750 * have to implement security before !
1751 ********************************************************************/
1752 static void spoolss_notify_security_desc(int snum,
1753 SPOOL_NOTIFY_INFO_DATA *data,
1754 print_queue_struct *queue,
1755 NT_PRINTER_INFO_LEVEL *printer,
1756 TALLOC_CTX *mem_ctx)
1758 data->notify_data.data.length=0;
1759 data->notify_data.data.string = NULL;
1762 /*******************************************************************
1763 * fill a notify_info_data with the attributes
1764 * jfm:xxxx a samba printer is always shared
1765 ********************************************************************/
1766 static void spoolss_notify_attributes(int snum,
1767 SPOOL_NOTIFY_INFO_DATA *data,
1768 print_queue_struct *queue,
1769 NT_PRINTER_INFO_LEVEL *printer,
1770 TALLOC_CTX *mem_ctx)
1772 data->notify_data.value[0] = printer->info_2->attributes;
1773 data->notify_data.value[1] = 0;
1776 /*******************************************************************
1777 * fill a notify_info_data with the priority
1778 ********************************************************************/
1779 static void spoolss_notify_priority(int snum,
1780 SPOOL_NOTIFY_INFO_DATA *data,
1781 print_queue_struct *queue,
1782 NT_PRINTER_INFO_LEVEL *printer,
1783 TALLOC_CTX *mem_ctx)
1785 data->notify_data.value[0] = printer->info_2->priority;
1786 data->notify_data.value[1] = 0;
1789 /*******************************************************************
1790 * fill a notify_info_data with the default priority
1791 ********************************************************************/
1792 static void spoolss_notify_default_priority(int snum,
1793 SPOOL_NOTIFY_INFO_DATA *data,
1794 print_queue_struct *queue,
1795 NT_PRINTER_INFO_LEVEL *printer,
1796 TALLOC_CTX *mem_ctx)
1798 data->notify_data.value[0] = printer->info_2->default_priority;
1799 data->notify_data.value[1] = 0;
1802 /*******************************************************************
1803 * fill a notify_info_data with the start time
1804 ********************************************************************/
1805 static void spoolss_notify_start_time(int snum,
1806 SPOOL_NOTIFY_INFO_DATA *data,
1807 print_queue_struct *queue,
1808 NT_PRINTER_INFO_LEVEL *printer,
1809 TALLOC_CTX *mem_ctx)
1811 data->notify_data.value[0] = printer->info_2->starttime;
1812 data->notify_data.value[1] = 0;
1815 /*******************************************************************
1816 * fill a notify_info_data with the until time
1817 ********************************************************************/
1818 static void spoolss_notify_until_time(int snum,
1819 SPOOL_NOTIFY_INFO_DATA *data,
1820 print_queue_struct *queue,
1821 NT_PRINTER_INFO_LEVEL *printer,
1822 TALLOC_CTX *mem_ctx)
1824 data->notify_data.value[0] = printer->info_2->untiltime;
1825 data->notify_data.value[1] = 0;
1828 /*******************************************************************
1829 * fill a notify_info_data with the status
1830 ********************************************************************/
1831 static void spoolss_notify_status(int snum,
1832 SPOOL_NOTIFY_INFO_DATA *data,
1833 print_queue_struct *queue,
1834 NT_PRINTER_INFO_LEVEL *printer,
1835 TALLOC_CTX *mem_ctx)
1837 print_status_struct status;
1839 print_queue_length(snum, &status);
1840 data->notify_data.value[0]=(uint32) status.status;
1841 data->notify_data.value[1] = 0;
1844 /*******************************************************************
1845 * fill a notify_info_data with the number of jobs queued
1846 ********************************************************************/
1847 static void spoolss_notify_cjobs(int snum,
1848 SPOOL_NOTIFY_INFO_DATA *data,
1849 print_queue_struct *queue,
1850 NT_PRINTER_INFO_LEVEL *printer,
1851 TALLOC_CTX *mem_ctx)
1853 data->notify_data.value[0] = print_queue_length(snum, NULL);
1854 data->notify_data.value[1] = 0;
1857 /*******************************************************************
1858 * fill a notify_info_data with the average ppm
1859 ********************************************************************/
1860 static void spoolss_notify_average_ppm(int snum,
1861 SPOOL_NOTIFY_INFO_DATA *data,
1862 print_queue_struct *queue,
1863 NT_PRINTER_INFO_LEVEL *printer,
1864 TALLOC_CTX *mem_ctx)
1866 /* always respond 8 pages per minutes */
1867 /* a little hard ! */
1868 data->notify_data.value[0] = printer->info_2->averageppm;
1869 data->notify_data.value[1] = 0;
1872 /*******************************************************************
1873 * fill a notify_info_data with username
1874 ********************************************************************/
1875 static void spoolss_notify_username(int snum,
1876 SPOOL_NOTIFY_INFO_DATA *data,
1877 print_queue_struct *queue,
1878 NT_PRINTER_INFO_LEVEL *printer,
1879 TALLOC_CTX *mem_ctx)
1884 len = rpcstr_push(temp, queue->user, sizeof(temp)-2, STR_TERMINATE);
1887 data->notify_data.data.length = len / 2;
1888 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1890 if (!data->notify_data.data.string) {
1891 data->notify_data.data.length = 0;
1895 memcpy(data->notify_data.data.string, temp, len);
1898 /*******************************************************************
1899 * fill a notify_info_data with job status
1900 ********************************************************************/
1901 static void spoolss_notify_job_status(int snum,
1902 SPOOL_NOTIFY_INFO_DATA *data,
1903 print_queue_struct *queue,
1904 NT_PRINTER_INFO_LEVEL *printer,
1905 TALLOC_CTX *mem_ctx)
1907 data->notify_data.value[0]=nt_printj_status(queue->status);
1908 data->notify_data.value[1] = 0;
1911 /*******************************************************************
1912 * fill a notify_info_data with job name
1913 ********************************************************************/
1914 static void spoolss_notify_job_name(int snum,
1915 SPOOL_NOTIFY_INFO_DATA *data,
1916 print_queue_struct *queue,
1917 NT_PRINTER_INFO_LEVEL *printer,
1918 TALLOC_CTX *mem_ctx)
1923 len = rpcstr_push(temp, queue->file, sizeof(temp)-2, STR_TERMINATE);
1925 data->notify_data.data.length = len / 2;
1926 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1928 if (!data->notify_data.data.string) {
1929 data->notify_data.data.length = 0;
1933 memcpy(data->notify_data.data.string, temp, len);
1936 /*******************************************************************
1937 * fill a notify_info_data with job status
1938 ********************************************************************/
1939 static void spoolss_notify_job_status_string(int snum,
1940 SPOOL_NOTIFY_INFO_DATA *data,
1941 print_queue_struct *queue,
1942 NT_PRINTER_INFO_LEVEL *printer,
1943 TALLOC_CTX *mem_ctx)
1946 * Now we're returning job status codes we just return a "" here. JRA.
1953 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1956 switch (queue->status) {
1961 p = ""; /* NT provides the paused string */
1970 #endif /* NO LONGER NEEDED. */
1972 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
1974 data->notify_data.data.length = len / 2;
1975 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1977 if (!data->notify_data.data.string) {
1978 data->notify_data.data.length = 0;
1982 memcpy(data->notify_data.data.string, temp, len);
1985 /*******************************************************************
1986 * fill a notify_info_data with job time
1987 ********************************************************************/
1988 static void spoolss_notify_job_time(int snum,
1989 SPOOL_NOTIFY_INFO_DATA *data,
1990 print_queue_struct *queue,
1991 NT_PRINTER_INFO_LEVEL *printer,
1992 TALLOC_CTX *mem_ctx)
1994 data->notify_data.value[0]=0x0;
1995 data->notify_data.value[1]=0;
1998 /*******************************************************************
1999 * fill a notify_info_data with job size
2000 ********************************************************************/
2001 static void spoolss_notify_job_size(int snum,
2002 SPOOL_NOTIFY_INFO_DATA *data,
2003 print_queue_struct *queue,
2004 NT_PRINTER_INFO_LEVEL *printer,
2005 TALLOC_CTX *mem_ctx)
2007 data->notify_data.value[0]=queue->size;
2008 data->notify_data.value[1]=0;
2011 /*******************************************************************
2012 * fill a notify_info_data with job position
2013 ********************************************************************/
2014 static void spoolss_notify_job_position(int snum,
2015 SPOOL_NOTIFY_INFO_DATA *data,
2016 print_queue_struct *queue,
2017 NT_PRINTER_INFO_LEVEL *printer,
2018 TALLOC_CTX *mem_ctx)
2020 data->notify_data.value[0]=queue->job;
2021 data->notify_data.value[1]=0;
2024 /*******************************************************************
2025 * fill a notify_info_data with submitted time
2026 ********************************************************************/
2027 static void spoolss_notify_submitted_time(int snum,
2028 SPOOL_NOTIFY_INFO_DATA *data,
2029 print_queue_struct *queue,
2030 NT_PRINTER_INFO_LEVEL *printer,
2031 TALLOC_CTX *mem_ctx)
2037 t=gmtime(&queue->time);
2039 len = sizeof(SYSTEMTIME);
2041 data->notify_data.data.length = len;
2042 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2044 if (!data->notify_data.data.string) {
2045 data->notify_data.data.length = 0;
2049 make_systemtime(&st, t);
2050 memcpy(data->notify_data.data.string,&st,len);
2055 struct s_notify_info_data_table
2061 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2062 print_queue_struct *queue,
2063 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2066 struct s_notify_info_data_table notify_info_data_table[] =
2068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2090 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2091 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2092 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2093 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2094 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2095 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2096 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2097 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2098 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2099 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2100 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2101 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2102 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2103 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2104 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2105 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2106 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2107 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2108 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2109 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2110 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2111 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2112 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2113 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2114 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2115 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2116 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2117 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2118 { END, END, "", END, NULL }
2121 /*******************************************************************
2122 return the size of info_data structure
2123 ********************************************************************/
2124 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2128 while (notify_info_data_table[i].type != END)
2130 if ( (notify_info_data_table[i].type == type ) &&
2131 (notify_info_data_table[i].field == field ) )
2133 return (notify_info_data_table[i].size);
2140 /*******************************************************************
2141 return the type of notify_info_data
2142 ********************************************************************/
2143 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2147 while (notify_info_data_table[i].type != END)
2149 if ( (notify_info_data_table[i].type == type ) &&
2150 (notify_info_data_table[i].field == field ) )
2152 if (notify_info_data_table[i].size == POINTER)
2166 /****************************************************************************
2167 ****************************************************************************/
2168 static int search_notify(uint16 type, uint16 field, int *value)
2173 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2175 if ( (notify_info_data_table[j].type == type ) &&
2176 (notify_info_data_table[j].field == field ) )
2181 if ( found && (notify_info_data_table[j].fn != NULL) )
2187 /****************************************************************************
2188 ****************************************************************************/
2189 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2191 info_data->type = type;
2192 info_data->field = field;
2193 info_data->reserved = 0;
2195 info_data->size = size_of_notify_info_data(type, field);
2196 info_data->enc_type = type_of_notify_info_data(type, field);
2200 /*******************************************************************
2202 * fill a notify_info struct with info asked
2204 ********************************************************************/
2205 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2206 snum, SPOOL_NOTIFY_OPTION_TYPE
2207 *option_type, uint32 id,
2208 TALLOC_CTX *mem_ctx)
2214 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2215 NT_PRINTER_INFO_LEVEL *printer = NULL;
2216 print_queue_struct *queue=NULL;
2218 type=option_type->type;
2220 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2221 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2222 option_type->count, lp_servicename(snum)));
2224 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2227 for(field_num=0; field_num<option_type->count; field_num++) {
2228 field = option_type->fields[field_num];
2229 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2231 if (!search_notify(type, field, &j) )
2234 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2235 DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2238 else info->data = tid;
2240 current_data=&info->data[info->count];
2242 construct_info_data(current_data, type, field, id);
2244 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2245 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2247 notify_info_data_table[j].fn(snum, current_data, queue,
2253 free_a_printer(&printer, 2);
2257 /*******************************************************************
2259 * fill a notify_info struct with info asked
2261 ********************************************************************/
2262 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2263 SPOOL_NOTIFY_INFO *info,
2264 NT_PRINTER_INFO_LEVEL *printer,
2265 int snum, SPOOL_NOTIFY_OPTION_TYPE
2266 *option_type, uint32 id,
2267 TALLOC_CTX *mem_ctx)
2273 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2275 DEBUG(4,("construct_notify_jobs_info\n"));
2277 type = option_type->type;
2279 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2280 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2281 option_type->count));
2283 for(field_num=0; field_num<option_type->count; field_num++) {
2284 field = option_type->fields[field_num];
2286 if (!search_notify(type, field, &j) )
2289 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2290 DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2293 else info->data = tid;
2295 current_data=&(info->data[info->count]);
2297 construct_info_data(current_data, type, field, id);
2298 notify_info_data_table[j].fn(snum, current_data, queue,
2307 * JFM: The enumeration is not that simple, it's even non obvious.
2309 * let's take an example: I want to monitor the PRINTER SERVER for
2310 * the printer's name and the number of jobs currently queued.
2311 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2312 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2314 * I have 3 printers on the back of my server.
2316 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2319 * 1 printer 1 name 1
2320 * 2 printer 1 cjob 1
2321 * 3 printer 2 name 2
2322 * 4 printer 2 cjob 2
2323 * 5 printer 3 name 3
2324 * 6 printer 3 name 3
2326 * that's the print server case, the printer case is even worse.
2329 /*******************************************************************
2331 * enumerate all printers on the printserver
2332 * fill a notify_info struct with info asked
2334 ********************************************************************/
2336 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2337 SPOOL_NOTIFY_INFO *info,
2338 TALLOC_CTX *mem_ctx)
2341 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2342 int n_services=lp_numservices();
2345 SPOOL_NOTIFY_OPTION *option;
2346 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2348 DEBUG(4,("printserver_notify_info\n"));
2350 option=Printer->notify.option;
2356 for (i=0; i<option->count; i++) {
2357 option_type=&(option->ctr.type[i]);
2359 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2362 for (snum=0; snum<n_services; snum++)
2363 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2364 if (construct_notify_printer_info
2365 (info, snum, option_type, id, mem_ctx))
2370 * Debugging information, don't delete.
2373 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2374 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2375 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2377 for (i=0; i<info->count; i++) {
2378 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2379 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2380 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2387 /*******************************************************************
2389 * fill a notify_info struct with info asked
2391 ********************************************************************/
2392 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2393 TALLOC_CTX *mem_ctx)
2396 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2399 SPOOL_NOTIFY_OPTION *option;
2400 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2402 print_queue_struct *queue=NULL;
2403 print_status_struct status;
2405 DEBUG(4,("printer_notify_info\n"));
2407 option=Printer->notify.option;
2413 get_printer_snum(p, hnd, &snum);
2415 for (i=0; i<option->count; i++) {
2416 option_type=&option->ctr.type[i];
2418 switch ( option_type->type ) {
2419 case PRINTER_NOTIFY_TYPE:
2420 if(construct_notify_printer_info(info, snum,
2426 case JOB_NOTIFY_TYPE: {
2427 NT_PRINTER_INFO_LEVEL *printer = NULL;
2429 count = print_queue_status(snum, &queue, &status);
2431 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
2432 lp_servicename(snum))))
2435 for (j=0; j<count; j++) {
2436 construct_notify_jobs_info(&queue[j], info,
2443 free_a_printer(&printer, 2);
2453 * Debugging information, don't delete.
2456 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2457 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2458 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2460 for (i=0; i<info->count; i++) {
2461 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2462 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2463 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2469 /********************************************************************
2471 ********************************************************************/
2473 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2475 POLICY_HND *handle = &q_u->handle;
2476 /* uint32 change = q_u->change; - notused. */
2477 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2478 SPOOL_NOTIFY_INFO *info = &r_u->info;
2480 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2481 WERROR result = WERR_BADFID;
2483 /* we always have a NOTIFY_INFO struct */
2487 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2488 OUR_HANDLE(handle)));
2492 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2494 /* jfm: the change value isn't used right now.
2495 * we will honour it when
2496 * a) we'll be able to send notification to the client
2497 * b) we'll have a way to communicate between the spoolss process.
2499 * same thing for option->flags
2500 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2501 * I don't have a global notification system, I'm sending back all the
2502 * informations even when _NOTHING_ has changed.
2505 /* just ignore the SPOOL_NOTIFY_OPTION */
2507 switch (Printer->printer_type) {
2508 case PRINTER_HANDLE_IS_PRINTSERVER:
2509 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2512 case PRINTER_HANDLE_IS_PRINTER:
2513 result = printer_notify_info(p, handle, info, p->mem_ctx);
2521 /********************************************************************
2522 * construct_printer_info_0
2523 * fill a printer_info_0 struct
2524 ********************************************************************/
2525 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2529 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2530 counter_printer_0 *session_counter;
2531 uint32 global_counter;
2534 print_status_struct status;
2536 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2539 count = print_queue_length(snum, &status);
2541 /* check if we already have a counter for this printer */
2542 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2544 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2545 if (session_counter->snum == snum)
2549 /* it's the first time, add it to the list */
2550 if (session_counter==NULL) {
2551 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2552 free_a_printer(&ntprinter, 2);
2555 ZERO_STRUCTP(session_counter);
2556 session_counter->snum=snum;
2557 session_counter->counter=0;
2558 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2562 session_counter->counter++;
2565 * the global_counter should be stored in a TDB as it's common to all the clients
2566 * and should be zeroed on samba startup
2568 global_counter=session_counter->counter;
2570 pstrcpy(chaine,ntprinter->info_2->printername);
2572 init_unistr(&printer->printername, chaine);
2574 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
2575 init_unistr(&printer->servername, chaine);
2577 printer->cjobs = count;
2578 printer->total_jobs = 0;
2579 printer->total_bytes = 0;
2581 setuptime = (time_t)ntprinter->info_2->setuptime;
2582 t=gmtime(&setuptime);
2584 printer->year = t->tm_year+1900;
2585 printer->month = t->tm_mon+1;
2586 printer->dayofweek = t->tm_wday;
2587 printer->day = t->tm_mday;
2588 printer->hour = t->tm_hour;
2589 printer->minute = t->tm_min;
2590 printer->second = t->tm_sec;
2591 printer->milliseconds = 0;
2593 printer->global_counter = global_counter;
2594 printer->total_pages = 0;
2595 printer->major_version = 0x0004; /* NT 4 */
2596 printer->build_version = 0x0565; /* build 1381 */
2597 printer->unknown7 = 0x1;
2598 printer->unknown8 = 0x0;
2599 printer->unknown9 = 0x0;
2600 printer->session_counter = session_counter->counter;
2601 printer->unknown11 = 0x0;
2602 printer->printer_errors = 0x0; /* number of print failure */
2603 printer->unknown13 = 0x0;
2604 printer->unknown14 = 0x1;
2605 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2606 printer->unknown16 = 0x0;
2607 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2608 printer->unknown18 = 0x0;
2609 printer->status = nt_printq_status(status.status);
2610 printer->unknown20 = 0x0;
2611 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2612 printer->unknown22 = 0x0;
2613 printer->unknown23 = 0x6; /* 6 ???*/
2614 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2615 printer->unknown25 = 0;
2616 printer->unknown26 = 0;
2617 printer->unknown27 = 0;
2618 printer->unknown28 = 0;
2619 printer->unknown29 = 0;
2621 free_a_printer(&ntprinter,2);
2625 /********************************************************************
2626 * construct_printer_info_1
2627 * fill a printer_info_1 struct
2628 ********************************************************************/
2629 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2633 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2635 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2638 printer->flags=flags;
2640 if (*ntprinter->info_2->comment == '\0') {
2641 init_unistr(&printer->comment, lp_comment(snum));
2642 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
2643 ntprinter->info_2->drivername, lp_comment(snum));
2646 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2647 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
2648 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2651 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2653 init_unistr(&printer->description, chaine);
2654 init_unistr(&printer->name, chaine2);
2656 free_a_printer(&ntprinter,2);
2661 /****************************************************************************
2662 Free a DEVMODE struct.
2663 ****************************************************************************/
2665 static void free_dev_mode(DEVICEMODE *dev)
2670 SAFE_FREE(dev->private);
2674 /****************************************************************************
2675 Create a DEVMODE struct. Returns malloced memory.
2676 ****************************************************************************/
2678 static DEVICEMODE *construct_dev_mode(int snum)
2682 NT_PRINTER_INFO_LEVEL *printer = NULL;
2683 NT_DEVICEMODE *ntdevmode = NULL;
2684 DEVICEMODE *devmode = NULL;
2686 DEBUG(7,("construct_dev_mode\n"));
2688 DEBUGADD(8,("getting printer characteristics\n"));
2690 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2691 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2695 ZERO_STRUCTP(devmode);
2697 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2700 if (printer->info_2->devmode)
2701 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2703 if (ntdevmode == NULL)
2706 DEBUGADD(8,("loading DEVICEMODE\n"));
2708 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2709 init_unistr(&devmode->devicename, adevice);
2711 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2712 init_unistr(&devmode->formname, aform);
2714 devmode->specversion = ntdevmode->specversion;
2715 devmode->driverversion = ntdevmode->driverversion;
2716 devmode->size = ntdevmode->size;
2717 devmode->driverextra = ntdevmode->driverextra;
2718 devmode->fields = ntdevmode->fields;
2720 devmode->orientation = ntdevmode->orientation;
2721 devmode->papersize = ntdevmode->papersize;
2722 devmode->paperlength = ntdevmode->paperlength;
2723 devmode->paperwidth = ntdevmode->paperwidth;
2724 devmode->scale = ntdevmode->scale;
2725 devmode->copies = ntdevmode->copies;
2726 devmode->defaultsource = ntdevmode->defaultsource;
2727 devmode->printquality = ntdevmode->printquality;
2728 devmode->color = ntdevmode->color;
2729 devmode->duplex = ntdevmode->duplex;
2730 devmode->yresolution = ntdevmode->yresolution;
2731 devmode->ttoption = ntdevmode->ttoption;
2732 devmode->collate = ntdevmode->collate;
2733 devmode->icmmethod = ntdevmode->icmmethod;
2734 devmode->icmintent = ntdevmode->icmintent;
2735 devmode->mediatype = ntdevmode->mediatype;
2736 devmode->dithertype = ntdevmode->dithertype;
2738 if (ntdevmode->private != NULL) {
2739 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2743 free_nt_devicemode(&ntdevmode);
2744 free_a_printer(&printer,2);
2751 free_nt_devicemode(&ntdevmode);
2753 free_a_printer(&printer,2);
2754 free_dev_mode(devmode);
2759 /********************************************************************
2760 * construct_printer_info_2
2761 * fill a printer_info_2 struct
2762 ********************************************************************/
2764 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2767 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2769 print_status_struct status;
2771 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2774 count = print_queue_length(snum, &status);
2776 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2777 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2778 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2779 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2780 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2782 if (*ntprinter->info_2->comment == '\0')
2783 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2785 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2787 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2788 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2789 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2790 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2791 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2793 printer->attributes = ntprinter->info_2->attributes;
2795 printer->priority = ntprinter->info_2->priority; /* priority */
2796 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2797 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2798 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2799 printer->status = nt_printq_status(status.status); /* status */
2800 printer->cjobs = count; /* jobs */
2801 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2803 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2804 DEBUG(8, ("Returning NULL Devicemode!\n"));
2807 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2808 /* steal the printer info sec_desc structure. [badly done]. */
2809 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2810 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2811 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2812 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2815 printer->secdesc = NULL;
2818 free_a_printer(&ntprinter, 2);
2822 /********************************************************************
2823 * construct_printer_info_3
2824 * fill a printer_info_3 struct
2825 ********************************************************************/
2826 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2828 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2829 PRINTER_INFO_3 *printer = NULL;
2831 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2835 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2836 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2840 ZERO_STRUCTP(printer);
2842 printer->flags = 4; /* These are the components of the SD we are returning. */
2843 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2844 /* steal the printer info sec_desc structure. [badly done]. */
2845 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2849 * Set the flags for the components we are returning.
2852 if (printer->secdesc->owner_sid)
2853 printer->flags |= OWNER_SECURITY_INFORMATION;
2855 if (printer->secdesc->grp_sid)
2856 printer->flags |= GROUP_SECURITY_INFORMATION;
2858 if (printer->secdesc->dacl)
2859 printer->flags |= DACL_SECURITY_INFORMATION;
2861 if (printer->secdesc->sacl)
2862 printer->flags |= SACL_SECURITY_INFORMATION;
2865 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2866 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2867 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2870 free_a_printer(&ntprinter, 2);
2872 *pp_printer = printer;
2876 /********************************************************************
2877 * construct_printer_info_4
2878 * fill a printer_info_4 struct
2879 ********************************************************************/
2881 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
2883 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2885 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2888 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2889 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2890 printer->attributes = ntprinter->info_2->attributes;
2892 free_a_printer(&ntprinter, 2);
2896 /********************************************************************
2897 * construct_printer_info_5
2898 * fill a printer_info_5 struct
2899 ********************************************************************/
2901 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
2903 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2905 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2908 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2909 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
2910 printer->attributes = ntprinter->info_2->attributes;
2911 printer->device_not_selected_timeout = 0x3a98;
2912 printer->transmission_retry_timeout = 0xafc8;
2914 free_a_printer(&ntprinter, 2);
2919 /********************************************************************
2920 Spoolss_enumprinters.
2921 ********************************************************************/
2922 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2926 int n_services=lp_numservices();
2927 PRINTER_INFO_1 *tp, *printers=NULL;
2928 PRINTER_INFO_1 current_prt;
2930 DEBUG(4,("enum_all_printers_info_1\n"));
2932 for (snum=0; snum<n_services; snum++) {
2933 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2934 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2936 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2937 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2938 DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2939 SAFE_FREE(printers);
2944 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2945 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
2951 /* check the required size. */
2952 for (i=0; i<*returned; i++)
2953 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2955 if (!alloc_buffer_size(buffer, *needed))
2956 return WERR_INSUFFICIENT_BUFFER;
2958 /* fill the buffer with the structures */
2959 for (i=0; i<*returned; i++)
2960 smb_io_printer_info_1("", buffer, &printers[i], 0);
2963 SAFE_FREE(printers);
2965 if (*needed > offered) {
2967 return WERR_INSUFFICIENT_BUFFER;
2973 /********************************************************************
2974 enum_all_printers_info_1_local.
2975 *********************************************************************/
2976 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2978 DEBUG(4,("enum_all_printers_info_1_local\n"));
2980 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2983 /********************************************************************
2984 enum_all_printers_info_1_name.
2985 *********************************************************************/
2986 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2990 DEBUG(4,("enum_all_printers_info_1_name\n"));
2992 if ((name[0] == '\\') && (name[1] == '\\'))
2995 if (is_myname_or_ipaddr(s)) {
2996 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2999 return WERR_INVALID_NAME;
3002 /********************************************************************
3003 enum_all_printers_info_1_remote.
3004 *********************************************************************/
3005 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3007 PRINTER_INFO_1 *printer;
3008 fstring printername;
3011 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3013 /* JFM: currently it's more a place holder than anything else.
3014 * In the spooler world there is a notion of server registration.
3015 * the print servers are registring (sp ?) on the PDC (in the same domain)
3017 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3020 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3025 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3026 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3027 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3029 init_unistr(&printer->description, desc);
3030 init_unistr(&printer->name, printername);
3031 init_unistr(&printer->comment, comment);
3032 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3034 /* check the required size. */
3035 *needed += spoolss_size_printer_info_1(printer);
3037 if (!alloc_buffer_size(buffer, *needed)) {
3039 return WERR_INSUFFICIENT_BUFFER;
3042 /* fill the buffer with the structures */
3043 smb_io_printer_info_1("", buffer, printer, 0);
3048 if (*needed > offered) {
3050 return WERR_INSUFFICIENT_BUFFER;
3056 /********************************************************************
3057 enum_all_printers_info_1_network.
3058 *********************************************************************/
3060 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3062 DEBUG(4,("enum_all_printers_info_1_network\n"));
3064 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3067 /********************************************************************
3068 * api_spoolss_enumprinters
3070 * called from api_spoolss_enumprinters (see this to understand)
3071 ********************************************************************/
3073 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3077 int n_services=lp_numservices();
3078 PRINTER_INFO_2 *tp, *printers=NULL;
3079 PRINTER_INFO_2 current_prt;
3081 for (snum=0; snum<n_services; snum++) {
3082 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3083 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3085 if (construct_printer_info_2(¤t_prt, snum)) {
3086 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3087 DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3088 SAFE_FREE(printers);
3093 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3094 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
3100 /* check the required size. */
3101 for (i=0; i<*returned; i++)
3102 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3104 if (!alloc_buffer_size(buffer, *needed)) {
3105 for (i=0; i<*returned; i++) {
3106 free_devmode(printers[i].devmode);
3108 SAFE_FREE(printers);
3109 return WERR_INSUFFICIENT_BUFFER;
3112 /* fill the buffer with the structures */
3113 for (i=0; i<*returned; i++)
3114 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3117 for (i=0; i<*returned; i++) {
3118 free_devmode(printers[i].devmode);
3120 SAFE_FREE(printers);
3122 if (*needed > offered) {
3124 return WERR_INSUFFICIENT_BUFFER;
3130 /********************************************************************
3131 * handle enumeration of printers at level 1
3132 ********************************************************************/
3133 static WERROR enumprinters_level1( uint32 flags, fstring name,
3134 NEW_BUFFER *buffer, uint32 offered,
3135 uint32 *needed, uint32 *returned)
3137 /* Not all the flags are equals */
3139 if (flags & PRINTER_ENUM_LOCAL)
3140 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3142 if (flags & PRINTER_ENUM_NAME)
3143 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3145 if (flags & PRINTER_ENUM_REMOTE)
3146 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3148 if (flags & PRINTER_ENUM_NETWORK)
3149 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3151 return WERR_OK; /* NT4sp5 does that */
3154 /********************************************************************
3155 * handle enumeration of printers at level 2
3156 ********************************************************************/
3157 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3158 NEW_BUFFER *buffer, uint32 offered,
3159 uint32 *needed, uint32 *returned)
3161 char *s = servername;
3163 if (flags & PRINTER_ENUM_LOCAL) {
3164 return enum_all_printers_info_2(buffer, offered, needed, returned);
3167 if (flags & PRINTER_ENUM_NAME) {
3168 if ((servername[0] == '\\') && (servername[1] == '\\'))
3170 if (is_myname_or_ipaddr(s))
3171 return enum_all_printers_info_2(buffer, offered, needed, returned);
3173 return WERR_INVALID_NAME;
3176 if (flags & PRINTER_ENUM_REMOTE)
3177 return WERR_UNKNOWN_LEVEL;
3182 /********************************************************************
3183 * handle enumeration of printers at level 5
3184 ********************************************************************/
3185 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3186 NEW_BUFFER *buffer, uint32 offered,
3187 uint32 *needed, uint32 *returned)
3189 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3193 /********************************************************************
3194 * api_spoolss_enumprinters
3196 * called from api_spoolss_enumprinters (see this to understand)
3197 ********************************************************************/
3199 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3201 uint32 flags = q_u->flags;
3202 UNISTR2 *servername = &q_u->servername;
3203 uint32 level = q_u->level;
3204 NEW_BUFFER *buffer = NULL;
3205 uint32 offered = q_u->offered;
3206 uint32 *needed = &r_u->needed;
3207 uint32 *returned = &r_u->returned;
3211 /* that's an [in out] buffer */
3212 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3213 buffer = r_u->buffer;
3215 DEBUG(4,("_spoolss_enumprinters\n"));
3222 * flags==PRINTER_ENUM_NAME
3223 * if name=="" then enumerates all printers
3224 * if name!="" then enumerate the printer
3225 * flags==PRINTER_ENUM_REMOTE
3226 * name is NULL, enumerate printers
3227 * Level 2: name!="" enumerates printers, name can't be NULL
3228 * Level 3: doesn't exist
3229 * Level 4: does a local registry lookup
3230 * Level 5: same as Level 2
3233 unistr2_to_ascii(name, servername, sizeof(name)-1);
3238 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3240 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3242 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3247 return WERR_UNKNOWN_LEVEL;
3250 /****************************************************************************
3251 ****************************************************************************/
3252 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3254 PRINTER_INFO_0 *printer=NULL;
3256 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3259 construct_printer_info_0(printer, snum);
3261 /* check the required size. */
3262 *needed += spoolss_size_printer_info_0(printer);
3264 if (!alloc_buffer_size(buffer, *needed)) {
3266 return WERR_INSUFFICIENT_BUFFER;
3269 /* fill the buffer with the structures */
3270 smb_io_printer_info_0("", buffer, printer, 0);
3275 if (*needed > offered) {
3276 return WERR_INSUFFICIENT_BUFFER;
3282 /****************************************************************************
3283 ****************************************************************************/
3284 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3286 PRINTER_INFO_1 *printer=NULL;
3288 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3291 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3293 /* check the required size. */
3294 *needed += spoolss_size_printer_info_1(printer);
3296 if (!alloc_buffer_size(buffer, *needed)) {
3298 return WERR_INSUFFICIENT_BUFFER;
3301 /* fill the buffer with the structures */
3302 smb_io_printer_info_1("", buffer, printer, 0);
3307 if (*needed > offered) {
3308 return WERR_INSUFFICIENT_BUFFER;
3314 /****************************************************************************
3315 ****************************************************************************/
3316 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3318 PRINTER_INFO_2 *printer=NULL;
3320 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3323 construct_printer_info_2(printer, snum);
3325 /* check the required size. */
3326 *needed += spoolss_size_printer_info_2(printer);
3328 if (!alloc_buffer_size(buffer, *needed)) {
3329 free_printer_info_2(printer);
3330 return WERR_INSUFFICIENT_BUFFER;
3333 /* fill the buffer with the structures */
3334 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3335 free_printer_info_2(printer);
3340 free_printer_info_2(printer);
3342 if (*needed > offered) {
3343 return WERR_INSUFFICIENT_BUFFER;
3349 /****************************************************************************
3350 ****************************************************************************/
3351 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3353 PRINTER_INFO_3 *printer=NULL;
3355 if (!construct_printer_info_3(&printer, snum))
3358 /* check the required size. */
3359 *needed += spoolss_size_printer_info_3(printer);
3361 if (!alloc_buffer_size(buffer, *needed)) {
3362 free_printer_info_3(printer);
3363 return WERR_INSUFFICIENT_BUFFER;
3366 /* fill the buffer with the structures */
3367 smb_io_printer_info_3("", buffer, printer, 0);
3370 free_printer_info_3(printer);
3372 if (*needed > offered) {
3373 return WERR_INSUFFICIENT_BUFFER;
3379 /****************************************************************************
3380 ****************************************************************************/
3381 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3383 PRINTER_INFO_4 *printer=NULL;
3385 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
3388 if (!construct_printer_info_4(printer, snum))
3391 /* check the required size. */
3392 *needed += spoolss_size_printer_info_4(printer);
3394 if (!alloc_buffer_size(buffer, *needed)) {
3395 free_printer_info_4(printer);
3396 return WERR_INSUFFICIENT_BUFFER;
3399 /* fill the buffer with the structures */
3400 smb_io_printer_info_4("", buffer, printer, 0);
3403 free_printer_info_4(printer);
3405 if (*needed > offered) {
3406 return WERR_INSUFFICIENT_BUFFER;
3412 /****************************************************************************
3413 ****************************************************************************/
3414 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3416 PRINTER_INFO_5 *printer=NULL;
3418 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
3421 if (!construct_printer_info_5(printer, snum))
3424 /* check the required size. */
3425 *needed += spoolss_size_printer_info_5(printer);
3427 if (!alloc_buffer_size(buffer, *needed)) {
3428 free_printer_info_5(printer);
3429 return WERR_INSUFFICIENT_BUFFER;
3432 /* fill the buffer with the structures */
3433 smb_io_printer_info_5("", buffer, printer, 0);
3436 free_printer_info_5(printer);
3438 if (*needed > offered) {
3439 return WERR_INSUFFICIENT_BUFFER;
3445 /****************************************************************************
3446 ****************************************************************************/
3448 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3450 POLICY_HND *handle = &q_u->handle;
3451 uint32 level = q_u->level;
3452 NEW_BUFFER *buffer = NULL;
3453 uint32 offered = q_u->offered;
3454 uint32 *needed = &r_u->needed;
3458 /* that's an [in out] buffer */
3459 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3460 buffer = r_u->buffer;
3464 if (!get_printer_snum(p, handle, &snum))
3469 return getprinter_level_0(snum, buffer, offered, needed);
3471 return getprinter_level_1(snum, buffer, offered, needed);
3473 return getprinter_level_2(snum, buffer, offered, needed);
3475 return getprinter_level_3(snum, buffer, offered, needed);
3477 return getprinter_level_4(snum, buffer, offered, needed);
3479 return getprinter_level_5(snum, buffer, offered, needed);
3481 return WERR_UNKNOWN_LEVEL;
3484 /********************************************************************
3485 * fill a DRIVER_INFO_1 struct
3486 ********************************************************************/
3487 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3489 init_unistr( &info->name, driver.info_3->name);
3492 /********************************************************************
3493 * construct_printer_driver_info_1
3494 ********************************************************************/
3495 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3497 NT_PRINTER_INFO_LEVEL *printer = NULL;
3498 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3500 ZERO_STRUCT(driver);
3502 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3503 return WERR_INVALID_PRINTER_NAME;
3505 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3506 return WERR_UNKNOWN_PRINTER_DRIVER;
3508 fill_printer_driver_info_1(info, driver, servername, architecture);
3510 free_a_printer(&printer,2);
3515 /********************************************************************
3516 * construct_printer_driver_info_2
3517 * fill a printer_info_2 struct
3518 ********************************************************************/
3519 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3523 info->version=driver.info_3->cversion;
3525 init_unistr( &info->name, driver.info_3->name );
3526 init_unistr( &info->architecture, driver.info_3->environment );
3529 if (strlen(driver.info_3->driverpath)) {
3530 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3531 init_unistr( &info->driverpath, temp );
3533 init_unistr( &info->driverpath, "" );
3535 if (strlen(driver.info_3->datafile)) {
3536 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3537 init_unistr( &info->datafile, temp );
3539 init_unistr( &info->datafile, "" );
3541 if (strlen(driver.info_3->configfile)) {
3542 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3543 init_unistr( &info->configfile, temp );
3545 init_unistr( &info->configfile, "" );
3548 /********************************************************************
3549 * construct_printer_driver_info_2
3550 * fill a printer_info_2 struct
3551 ********************************************************************/
3552 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3554 NT_PRINTER_INFO_LEVEL *printer = NULL;
3555 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3557 ZERO_STRUCT(printer);
3558 ZERO_STRUCT(driver);
3560 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3561 return WERR_INVALID_PRINTER_NAME;
3563 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3564 return WERR_UNKNOWN_PRINTER_DRIVER;
3566 fill_printer_driver_info_2(info, driver, servername);
3568 free_a_printer(&printer,2);
3573 /********************************************************************
3574 * copy a strings array and convert to UNICODE
3576 * convert an array of ascii string to a UNICODE string
3577 ********************************************************************/
3578 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3586 DEBUG(6,("init_unistr_array\n"));
3590 if (char_array == NULL)
3594 if (!v) v = ""; /* hack to handle null lists */
3596 if (strlen(v) == 0) break;
3597 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3598 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3599 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3600 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3603 else *uni_array = tuary;
3604 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3609 (*uni_array)[j]=0x0000;
3612 DEBUGADD(6,("last one:done\n"));
3615 /********************************************************************
3616 * construct_printer_info_3
3617 * fill a printer_info_3 struct
3618 ********************************************************************/
3619 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3625 info->version=driver.info_3->cversion;
3627 init_unistr( &info->name, driver.info_3->name );
3628 init_unistr( &info->architecture, driver.info_3->environment );
3630 if (strlen(driver.info_3->driverpath)) {
3631 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3632 init_unistr( &info->driverpath, temp );
3634 init_unistr( &info->driverpath, "" );
3636 if (strlen(driver.info_3->datafile)) {
3637 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3638 init_unistr( &info->datafile, temp );
3640 init_unistr( &info->datafile, "" );
3642 if (strlen(driver.info_3->configfile)) {
3643 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3644 init_unistr( &info->configfile, temp );
3646 init_unistr( &info->configfile, "" );
3648 if (strlen(driver.info_3->helpfile)) {
3649 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3650 init_unistr( &info->helpfile, temp );
3652 init_unistr( &info->helpfile, "" );
3654 init_unistr( &info->monitorname, driver.info_3->monitorname );
3655 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3657 info->dependentfiles=NULL;
3658 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3661 /********************************************************************
3662 * construct_printer_info_3
3663 * fill a printer_info_3 struct
3664 ********************************************************************/
3665 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3667 NT_PRINTER_INFO_LEVEL *printer = NULL;
3668 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3670 ZERO_STRUCT(driver);
3672 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3673 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3674 if (!W_ERROR_IS_OK(status))
3675 return WERR_INVALID_PRINTER_NAME;
3677 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3678 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3679 if (!W_ERROR_IS_OK(status)) {
3680 free_a_printer(&printer,2);
3681 return WERR_UNKNOWN_PRINTER_DRIVER;
3684 fill_printer_driver_info_3(info, driver, servername);
3686 free_a_printer(&printer,2);
3691 /********************************************************************
3692 * construct_printer_info_6
3693 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3694 ********************************************************************/
3696 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3702 memset(&nullstr, '\0', sizeof(fstring));
3704 info->version=driver.info_3->cversion;
3706 init_unistr( &info->name, driver.info_3->name );
3707 init_unistr( &info->architecture, driver.info_3->environment );
3709 if (strlen(driver.info_3->driverpath)) {
3710 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3711 init_unistr( &info->driverpath, temp );
3713 init_unistr( &info->driverpath, "" );
3715 if (strlen(driver.info_3->datafile)) {
3716 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3717 init_unistr( &info->datafile, temp );
3719 init_unistr( &info->datafile, "" );
3721 if (strlen(driver.info_3->configfile)) {
3722 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3723 init_unistr( &info->configfile, temp );
3725 init_unistr( &info->configfile, "" );
3727 if (strlen(driver.info_3->helpfile)) {
3728 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3729 init_unistr( &info->helpfile, temp );
3731 init_unistr( &info->helpfile, "" );
3733 init_unistr( &info->monitorname, driver.info_3->monitorname );
3734 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3736 info->dependentfiles=NULL;
3737 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3739 info->previousdrivernames=NULL;
3740 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3742 info->driver_date.low=0;
3743 info->driver_date.high=0;
3746 info->driver_version_low=0;
3747 info->driver_version_high=0;
3749 init_unistr( &info->mfgname, "");
3750 init_unistr( &info->oem_url, "");
3751 init_unistr( &info->hardware_id, "");
3752 init_unistr( &info->provider, "");
3755 /********************************************************************
3756 * construct_printer_info_6
3757 * fill a printer_info_6 struct
3758 ********************************************************************/
3759 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3761 NT_PRINTER_INFO_LEVEL *printer = NULL;
3762 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3764 ZERO_STRUCT(driver);
3766 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3767 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3768 if (!W_ERROR_IS_OK(status))
3769 return WERR_INVALID_PRINTER_NAME;
3771 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3772 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3773 if (!W_ERROR_IS_OK(status)) {
3775 * Is this a W2k client ?
3779 free_a_printer(&printer,2);
3780 return WERR_UNKNOWN_PRINTER_DRIVER;
3783 /* Yes - try again with a WinNT driver. */
3785 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3786 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3787 if (!W_ERROR_IS_OK(status)) {
3788 free_a_printer(&printer,2);
3789 return WERR_UNKNOWN_PRINTER_DRIVER;
3793 fill_printer_driver_info_6(info, driver, servername);
3795 free_a_printer(&printer,2);
3800 /****************************************************************************
3801 ****************************************************************************/
3803 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3805 SAFE_FREE(info->dependentfiles);
3808 /****************************************************************************
3809 ****************************************************************************/
3811 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3813 SAFE_FREE(info->dependentfiles);
3817 /****************************************************************************
3818 ****************************************************************************/
3819 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3821 DRIVER_INFO_1 *info=NULL;
3824 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3827 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3828 if (!W_ERROR_IS_OK(status)) {
3833 /* check the required size. */
3834 *needed += spoolss_size_printer_driver_info_1(info);
3836 if (!alloc_buffer_size(buffer, *needed)) {
3838 return WERR_INSUFFICIENT_BUFFER;
3841 /* fill the buffer with the structures */
3842 smb_io_printer_driver_info_1("", buffer, info, 0);
3847 if (*needed > offered)
3848 return WERR_INSUFFICIENT_BUFFER;
3853 /****************************************************************************
3854 ****************************************************************************/
3855 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3857 DRIVER_INFO_2 *info=NULL;
3860 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3863 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3864 if (!W_ERROR_IS_OK(status)) {
3869 /* check the required size. */
3870 *needed += spoolss_size_printer_driver_info_2(info);
3872 if (!alloc_buffer_size(buffer, *needed)) {
3874 return WERR_INSUFFICIENT_BUFFER;
3877 /* fill the buffer with the structures */
3878 smb_io_printer_driver_info_2("", buffer, info, 0);
3883 if (*needed > offered)
3884 return WERR_INSUFFICIENT_BUFFER;
3889 /****************************************************************************
3890 ****************************************************************************/
3891 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3898 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3899 if (!W_ERROR_IS_OK(status)) {
3903 /* check the required size. */
3904 *needed += spoolss_size_printer_driver_info_3(&info);
3906 if (!alloc_buffer_size(buffer, *needed)) {
3907 free_printer_driver_info_3(&info);
3908 return WERR_INSUFFICIENT_BUFFER;
3911 /* fill the buffer with the structures */
3912 smb_io_printer_driver_info_3("", buffer, &info, 0);
3914 free_printer_driver_info_3(&info);
3916 if (*needed > offered)
3917 return WERR_INSUFFICIENT_BUFFER;
3922 /****************************************************************************
3923 ****************************************************************************/
3924 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3931 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3932 if (!W_ERROR_IS_OK(status)) {
3936 /* check the required size. */
3937 *needed += spoolss_size_printer_driver_info_6(&info);
3939 if (!alloc_buffer_size(buffer, *needed)) {
3940 free_printer_driver_info_6(&info);
3941 return WERR_INSUFFICIENT_BUFFER;
3944 /* fill the buffer with the structures */
3945 smb_io_printer_driver_info_6("", buffer, &info, 0);
3947 free_printer_driver_info_6(&info);
3949 if (*needed > offered)
3950 return WERR_INSUFFICIENT_BUFFER;
3955 /****************************************************************************
3956 ****************************************************************************/
3958 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3960 POLICY_HND *handle = &q_u->handle;
3961 UNISTR2 *uni_arch = &q_u->architecture;
3962 uint32 level = q_u->level;
3963 uint32 clientmajorversion = q_u->clientmajorversion;
3964 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3965 NEW_BUFFER *buffer = NULL;
3966 uint32 offered = q_u->offered;
3967 uint32 *needed = &r_u->needed;
3968 uint32 *servermajorversion = &r_u->servermajorversion;
3969 uint32 *serverminorversion = &r_u->serverminorversion;
3972 fstring architecture;
3975 /* that's an [in out] buffer */
3976 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3977 buffer = r_u->buffer;
3979 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3982 *servermajorversion=0;
3983 *serverminorversion=0;
3985 pstrcpy(servername, get_called_name());
3986 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3988 if (!get_printer_snum(p, handle, &snum))
3993 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3995 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3997 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3999 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4002 return WERR_UNKNOWN_LEVEL;
4005 /****************************************************************************
4006 ****************************************************************************/
4008 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4010 POLICY_HND *handle = &q_u->handle;
4012 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4015 Printer->page_started=True;
4019 DEBUG(3,("Error in startpageprinter printer handle\n"));
4023 /****************************************************************************
4024 ****************************************************************************/
4026 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4028 POLICY_HND *handle = &q_u->handle;
4030 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4033 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
4037 Printer->page_started=False;
4042 /********************************************************************
4043 * api_spoolss_getprinter
4044 * called from the spoolss dispatcher
4046 ********************************************************************/
4048 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4050 POLICY_HND *handle = &q_u->handle;
4051 /* uint32 level = q_u->doc_info_container.level; - notused. */
4052 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4053 uint32 *jobid = &r_u->jobid;
4055 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4059 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4060 struct current_user user;
4063 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4067 get_current_user(&user, p);
4070 * a nice thing with NT is it doesn't listen to what you tell it.
4071 * when asked to send _only_ RAW datas, it tries to send datas
4074 * So I add checks like in NT Server ...
4076 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4077 * there's a bug in NT client-side code, so we'll fix it in the
4078 * server-side code. *nnnnnggggh!*
4081 if (info_1->p_datatype != 0) {
4082 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4083 if (strcmp(datatype, "RAW") != 0) {
4085 return WERR_INVALID_DATATYPE;
4089 /* get the share number of the printer */
4090 if (!get_printer_snum(p, handle, &snum)) {
4094 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4096 Printer->jobid = print_job_start(&user, snum, jobname);
4098 /* An error occured in print_job_start() so return an appropriate
4101 if (Printer->jobid == -1) {
4102 return map_werror_from_unix(errno);
4105 Printer->document_started=True;
4106 (*jobid) = Printer->jobid;
4111 /********************************************************************
4112 * api_spoolss_getprinter
4113 * called from the spoolss dispatcher
4115 ********************************************************************/
4117 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4119 POLICY_HND *handle = &q_u->handle;
4121 return _spoolss_enddocprinter_internal(p, handle);
4124 /****************************************************************************
4125 ****************************************************************************/
4127 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4129 POLICY_HND *handle = &q_u->handle;
4130 uint32 buffer_size = q_u->buffer_size;
4131 uint8 *buffer = q_u->buffer;
4132 uint32 *buffer_written = &q_u->buffer_size2;
4134 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4137 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
4138 r_u->buffer_written = q_u->buffer_size2;
4142 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4145 r_u->buffer_written = q_u->buffer_size2;
4150 /********************************************************************
4151 * api_spoolss_getprinter
4152 * called from the spoolss dispatcher
4154 ********************************************************************/
4155 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4158 struct current_user user;
4160 WERROR errcode = WERR_BADFUNC;
4161 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4163 get_current_user(&user, p);
4166 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4170 if (!get_printer_snum(p, handle, &snum))
4174 case PRINTER_CONTROL_PAUSE:
4175 if (print_queue_pause(&user, snum, &errcode)) {
4179 case PRINTER_CONTROL_RESUME:
4180 case PRINTER_CONTROL_UNPAUSE:
4181 if (print_queue_resume(&user, snum, &errcode)) {
4185 case PRINTER_CONTROL_PURGE:
4186 if (print_queue_purge(&user, snum, &errcode)) {
4191 return WERR_UNKNOWN_LEVEL;
4197 /********************************************************************
4198 * api_spoolss_abortprinter
4199 ********************************************************************/
4201 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4203 POLICY_HND *handle = &q_u->handle;
4205 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4208 /********************************************************************
4209 * called by spoolss_api_setprinter
4210 * when updating a printer description
4211 ********************************************************************/
4212 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4213 const SPOOL_PRINTER_INFO_LEVEL *info,
4214 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4216 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4217 struct current_user user;
4221 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4223 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4224 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4225 OUR_HANDLE(handle)));
4227 result = WERR_BADFID;
4231 /* NT seems to like setting the security descriptor even though
4232 nothing may have actually changed. This causes annoying
4233 dialog boxes when the user doesn't have permission to change
4234 the security descriptor. */
4236 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4238 if (DEBUGLEVEL >= 10) {
4242 the_acl = old_secdesc_ctr->sec->dacl;
4243 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4244 PRINTERNAME(snum), the_acl->num_aces));
4246 for (i = 0; i < the_acl->num_aces; i++) {
4249 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4251 DEBUG(10, ("%s 0x%08x\n", sid_str,
4252 the_acl->ace[i].info.mask));
4255 the_acl = secdesc_ctr->sec->dacl;
4258 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4259 PRINTERNAME(snum), the_acl->num_aces));
4261 for (i = 0; i < the_acl->num_aces; i++) {
4264 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4266 DEBUG(10, ("%s 0x%08x\n", sid_str,
4267 the_acl->ace[i].info.mask));
4270 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4274 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4276 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4281 /* Work out which user is performing the operation */
4283 get_current_user(&user, p);
4285 /* Check the user has permissions to change the security
4286 descriptor. By experimentation with two NT machines, the user
4287 requires Full Access to the printer to change security
4290 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4291 result = WERR_ACCESS_DENIED;
4295 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4302 /********************************************************************
4303 Do Samba sanity checks on a printer info struct.
4304 this has changed purpose: it now "canonicalises" printer
4305 info from a client rather than just checking it is correct
4306 ********************************************************************/
4308 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4310 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4311 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4313 /* we force some elements to "correct" values */
4314 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
4315 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4316 get_called_name(), lp_servicename(snum));
4317 fstrcpy(info->sharename, lp_servicename(snum));
4318 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4319 | PRINTER_ATTRIBUTE_LOCAL \
4320 | PRINTER_ATTRIBUTE_RAW_ONLY \
4321 | PRINTER_ATTRIBUTE_QUEUED ;
4326 /****************************************************************************
4327 ****************************************************************************/
4328 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4330 char *cmd = lp_addprinter_cmd();
4333 pstring driverlocation;
4338 /* build driver path... only 9X architecture is needed for legacy reasons */
4339 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4341 /* change \ to \\ for the shell */
4342 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4344 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4345 cmd, printer->info_2->printername, printer->info_2->sharename,
4346 printer->info_2->portname, printer->info_2->drivername,
4347 printer->info_2->location, driverlocation);
4349 DEBUG(10,("Running [%s]\n", command));
4350 ret = smbrun(command, &fd);
4351 DEBUGADD(10,("returned [%d]\n", ret));
4360 /* Get lines and convert them back to dos-codepage */
4361 qlines = fd_lines_load(fd, &numlines);
4362 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4366 /* Set the portname to what the script says the portname should be. */
4367 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4368 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4370 /* Send SIGHUP to process group... is there a better way? */
4375 file_lines_free(qlines);
4379 /* Return true if two devicemodes are equal */
4381 #define DEVMODE_CHECK_INT(field) \
4382 if (d1->field != d2->field) { \
4383 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4384 d1->field, d2->field)); \
4388 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4390 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4393 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4394 return False; /* if either is exclusively NULL are not equal */
4397 if (!strequal(d1->devicename, d2->devicename)) {
4398 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4402 if (!strequal(d1->formname, d2->formname)) {
4403 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4407 DEVMODE_CHECK_INT(specversion);
4408 DEVMODE_CHECK_INT(driverversion);
4409 DEVMODE_CHECK_INT(driverextra);
4410 DEVMODE_CHECK_INT(orientation);
4411 DEVMODE_CHECK_INT(papersize);
4412 DEVMODE_CHECK_INT(paperlength);
4413 DEVMODE_CHECK_INT(paperwidth);
4414 DEVMODE_CHECK_INT(scale);
4415 DEVMODE_CHECK_INT(copies);
4416 DEVMODE_CHECK_INT(defaultsource);
4417 DEVMODE_CHECK_INT(printquality);
4418 DEVMODE_CHECK_INT(color);
4419 DEVMODE_CHECK_INT(duplex);
4420 DEVMODE_CHECK_INT(yresolution);
4421 DEVMODE_CHECK_INT(ttoption);
4422 DEVMODE_CHECK_INT(collate);
4423 DEVMODE_CHECK_INT(logpixels);
4425 DEVMODE_CHECK_INT(fields);
4426 DEVMODE_CHECK_INT(bitsperpel);
4427 DEVMODE_CHECK_INT(pelswidth);
4428 DEVMODE_CHECK_INT(pelsheight);
4429 DEVMODE_CHECK_INT(displayflags);
4430 DEVMODE_CHECK_INT(displayfrequency);
4431 DEVMODE_CHECK_INT(icmmethod);
4432 DEVMODE_CHECK_INT(icmintent);
4433 DEVMODE_CHECK_INT(mediatype);
4434 DEVMODE_CHECK_INT(dithertype);
4435 DEVMODE_CHECK_INT(reserved1);
4436 DEVMODE_CHECK_INT(reserved2);
4437 DEVMODE_CHECK_INT(panningwidth);
4438 DEVMODE_CHECK_INT(panningheight);
4440 /* compare the private data if it exists */
4441 if (!d1->driverextra && !d2->driverextra) goto equal;
4444 DEVMODE_CHECK_INT(driverextra);
4446 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4447 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4452 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4456 /* Return true if two NT_PRINTER_PARAM structures are equal */
4458 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4459 NT_PRINTER_PARAM *p2)
4461 if (!p1 && !p2) goto equal;
4463 if ((!p1 && p2) || (p1 && !p2)) {
4464 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4468 /* Compare lists of printer parameters */
4472 NT_PRINTER_PARAM *q = p1;
4474 /* Find the parameter in the second structure */
4478 if (strequal(p1->value, q->value)) {
4480 if (p1->type != q->type) {
4481 DEBUG(10, ("nt_printer_param_equal():"
4482 "types for %s differ (%d != %d)\n",
4483 p1->value, p1->type,
4488 if (p1->data_len != q->data_len) {
4489 DEBUG(10, ("nt_printer_param_equal():"
4490 "len for %s differs (%d != %d)\n",
4491 p1->value, p1->data_len,
4496 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4499 DEBUG(10, ("nt_printer_param_equal():"
4500 "data for %s differs\n", p1->value));
4510 DEBUG(10, ("nt_printer_param_equal(): param %s "
4511 "does not exist\n", p1->value));
4520 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4524 /********************************************************************
4525 * Called by update_printer when trying to work out whether to
4526 * actually update printer info.
4527 ********************************************************************/
4529 #define PI_CHECK_INT(field) \
4530 if (pi1->field != pi2->field) { \
4531 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4532 pi1->field, pi2->field)); \
4536 #define PI_CHECK_STR(field) \
4537 if (!strequal(pi1->field, pi2->field)) { \
4538 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4539 pi1->field, pi2->field)); \
4543 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4544 NT_PRINTER_INFO_LEVEL *p2)
4546 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4548 /* Trivial conditions */
4550 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4554 if ((!p1 && p2) || (p1 && !p2) ||
4555 (!p1->info_2 && p2->info_2) ||
4556 (p1->info_2 && !p2->info_2)) {
4557 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4562 /* Compare two nt_printer_info_level structures. Don't compare
4563 status or cjobs as they seem to have something to do with the
4569 /* Don't check the attributes as we stomp on the value in
4570 check_printer_ok() anyway. */
4573 PI_CHECK_INT(attributes);
4576 PI_CHECK_INT(priority);
4577 PI_CHECK_INT(default_priority);
4578 PI_CHECK_INT(starttime);
4579 PI_CHECK_INT(untiltime);
4580 PI_CHECK_INT(averageppm);
4582 /* Yuck - don't check the printername or servername as the
4583 add_a_printer() code plays games with them. You can't
4584 change the printername or the sharename through this interface
4587 PI_CHECK_STR(sharename);
4588 PI_CHECK_STR(portname);
4589 PI_CHECK_STR(drivername);
4590 PI_CHECK_STR(comment);
4591 PI_CHECK_STR(location);
4593 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4597 PI_CHECK_STR(sepfile);
4598 PI_CHECK_STR(printprocessor);
4599 PI_CHECK_STR(datatype);
4600 PI_CHECK_STR(parameters);
4602 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4606 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4610 PI_CHECK_INT(changeid);
4611 PI_CHECK_INT(c_setprinter);
4612 PI_CHECK_INT(setuptime);
4615 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4619 /********************************************************************
4620 * called by spoolss_api_setprinter
4621 * when updating a printer description
4622 ********************************************************************/
4624 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4625 const SPOOL_PRINTER_INFO_LEVEL *info,
4626 DEVICEMODE *devmode)
4629 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4630 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4633 DEBUG(8,("update_printer\n"));
4638 DEBUG(0,("Send a mail to samba@samba.org\n"));
4639 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4640 result = WERR_UNKNOWN_LEVEL;
4645 result = WERR_BADFID;
4649 if (!get_printer_snum(p, handle, &snum)) {
4650 result = WERR_BADFID;
4654 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
4655 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
4656 result = WERR_BADFID;
4660 DEBUGADD(8,("Converting info_2 struct\n"));
4663 * convert_printer_info converts the incoming
4664 * info from the client and overwrites the info
4665 * just read from the tdb in the pointer 'printer'.
4668 if (!convert_printer_info(info, printer, level)) {
4669 result = WERR_NOMEM;
4673 if (info->info_2->devmode_ptr != 0) {
4674 /* we have a valid devmode
4675 convert it and link it*/
4677 DEBUGADD(8,("Converting the devicemode struct\n"));
4678 if (!convert_devicemode(printer->info_2->printername, devmode,
4679 &printer->info_2->devmode)) {
4680 result = WERR_NOMEM;
4685 /* Do sanity check on the requested changes for Samba */
4687 if (!check_printer_ok(printer->info_2, snum)) {
4688 result = WERR_INVALID_PARAM;
4692 /* NT likes to call this function even though nothing has actually
4693 changed. Check this so the user doesn't end up with an
4694 annoying permission denied dialog box. */
4696 if (nt_printer_info_level_equal(printer, old_printer)) {
4697 DEBUG(3, ("printer info has not changed\n"));
4702 /* Check calling user has permission to update printer description */
4704 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4705 DEBUG(3, ("printer property change denied by security "
4707 result = WERR_ACCESS_DENIED;
4711 /* Call addprinter hook */
4713 if (*lp_addprinter_cmd()) {
4714 if (!add_printer_hook(printer)) {
4715 result = WERR_ACCESS_DENIED;
4720 /* Update printer info */
4721 result = add_a_printer(*printer, 2);
4724 free_a_printer(&printer, 2);
4725 free_a_printer(&old_printer, 2);
4727 srv_spoolss_sendnotify(p, handle);
4732 /****************************************************************************
4733 ****************************************************************************/
4735 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4737 POLICY_HND *handle = &q_u->handle;
4738 uint32 level = q_u->level;
4739 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4740 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4741 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4742 uint32 command = q_u->command;
4744 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4747 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4751 /* check the level */
4754 return control_printer(handle, command, p);
4756 return update_printer(p, handle, level, info, devmode_ctr.devmode);
4758 return update_printer_sec(handle, level, info, p,
4761 return WERR_UNKNOWN_LEVEL;
4765 /****************************************************************************
4766 ****************************************************************************/
4768 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4770 POLICY_HND *handle = &q_u->handle;
4772 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4775 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4779 if (Printer->notify.client_connected==True)
4780 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4782 Printer->notify.flags=0;
4783 Printer->notify.options=0;
4784 Printer->notify.localmachine[0]='\0';
4785 Printer->notify.printerlocal=0;
4786 if (Printer->notify.option)
4787 free_spool_notify_option(&Printer->notify.option);
4788 Printer->notify.client_connected=False;
4793 /****************************************************************************
4794 ****************************************************************************/
4796 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4798 /* that's an [in out] buffer (despite appearences to the contrary) */
4799 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4802 return WERR_INVALID_PARAM; /* this is what a NT server
4803 returns for AddJob. AddJob
4804 must fail on non-local
4808 /****************************************************************************
4809 ****************************************************************************/
4810 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4811 int position, int snum)
4817 t=gmtime(&queue->time);
4818 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
4820 job_info->jobid=queue->job;
4821 init_unistr(&job_info->printername, lp_servicename(snum));
4822 init_unistr(&job_info->machinename, temp_name);
4823 init_unistr(&job_info->username, queue->user);
4824 init_unistr(&job_info->document, queue->file);
4825 init_unistr(&job_info->datatype, "RAW");
4826 init_unistr(&job_info->text_status, "");
4827 job_info->status=nt_printj_status(queue->status);
4828 job_info->priority=queue->priority;
4829 job_info->position=position;
4830 job_info->totalpages=0;
4831 job_info->pagesprinted=0;
4833 make_systemtime(&job_info->submitted, t);
4836 /****************************************************************************
4837 ****************************************************************************/
4838 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4839 int position, int snum,
4840 NT_PRINTER_INFO_LEVEL *ntprinter)
4846 t=gmtime(&queue->time);
4847 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
4849 job_info->jobid=queue->job;
4851 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
4853 init_unistr(&job_info->printername, chaine);
4855 init_unistr(&job_info->machinename, temp_name);
4856 init_unistr(&job_info->username, queue->user);
4857 init_unistr(&job_info->document, queue->file);
4858 init_unistr(&job_info->notifyname, queue->user);
4859 init_unistr(&job_info->datatype, "RAW");
4860 init_unistr(&job_info->printprocessor, "winprint");
4861 init_unistr(&job_info->parameters, "");
4862 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4863 init_unistr(&job_info->text_status, "");
4865 /* and here the security descriptor */
4867 job_info->status=nt_printj_status(queue->status);
4868 job_info->priority=queue->priority;
4869 job_info->position=position;
4870 job_info->starttime=0;
4871 job_info->untiltime=0;
4872 job_info->totalpages=0;
4873 job_info->size=queue->size;
4874 make_systemtime(&(job_info->submitted), t);
4875 job_info->timeelapsed=0;
4876 job_info->pagesprinted=0;
4878 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4885 /****************************************************************************
4886 Enumjobs at level 1.
4887 ****************************************************************************/
4888 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
4889 NEW_BUFFER *buffer, uint32 offered,
4890 uint32 *needed, uint32 *returned)
4895 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4902 for (i=0; i<*returned; i++)
4903 fill_job_info_1(&info[i], &queue[i], i, snum);
4907 /* check the required size. */
4908 for (i=0; i<*returned; i++)
4909 (*needed) += spoolss_size_job_info_1(&info[i]);
4911 if (!alloc_buffer_size(buffer, *needed)) {
4913 return WERR_INSUFFICIENT_BUFFER;
4916 /* fill the buffer with the structures */
4917 for (i=0; i<*returned; i++)
4918 smb_io_job_info_1("", buffer, &info[i], 0);
4923 if (*needed > offered) {
4925 return WERR_INSUFFICIENT_BUFFER;
4931 /****************************************************************************
4932 Enumjobs at level 2.
4933 ****************************************************************************/
4934 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
4935 NEW_BUFFER *buffer, uint32 offered,
4936 uint32 *needed, uint32 *returned)
4938 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4943 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4949 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
4950 if (!W_ERROR_IS_OK(result)) {
4955 for (i=0; i<*returned; i++)
4956 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4958 free_a_printer(&ntprinter, 2);
4961 /* check the required size. */
4962 for (i=0; i<*returned; i++)
4963 (*needed) += spoolss_size_job_info_2(&info[i]);
4965 if (!alloc_buffer_size(buffer, *needed)) {
4967 return WERR_INSUFFICIENT_BUFFER;
4970 /* fill the buffer with the structures */
4971 for (i=0; i<*returned; i++)
4972 smb_io_job_info_2("", buffer, &info[i], 0);
4975 for (i = 0; i < *returned; i++)
4976 free_job_info_2(&info[i]);
4980 if (*needed > offered) {
4982 return WERR_INSUFFICIENT_BUFFER;
4988 /****************************************************************************
4990 ****************************************************************************/
4992 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4994 POLICY_HND *handle = &q_u->handle;
4995 /* uint32 firstjob = q_u->firstjob; - notused. */
4996 /* uint32 numofjobs = q_u->numofjobs; - notused. */
4997 uint32 level = q_u->level;
4998 NEW_BUFFER *buffer = NULL;
4999 uint32 offered = q_u->offered;
5000 uint32 *needed = &r_u->needed;
5001 uint32 *returned = &r_u->returned;
5004 print_status_struct prt_status;
5005 print_queue_struct *queue=NULL;
5007 /* that's an [in out] buffer */
5008 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5009 buffer = r_u->buffer;
5011 DEBUG(4,("_spoolss_enumjobs\n"));
5016 if (!get_printer_snum(p, handle, &snum))
5019 *returned = print_queue_status(snum, &queue, &prt_status);
5020 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5022 if (*returned == 0) {
5029 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5031 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5035 return WERR_UNKNOWN_LEVEL;
5039 /****************************************************************************
5040 ****************************************************************************/
5042 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5047 /****************************************************************************
5048 ****************************************************************************/
5050 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5052 POLICY_HND *handle = &q_u->handle;
5053 uint32 jobid = q_u->jobid;
5054 /* uint32 level = q_u->level; - notused. */
5055 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5056 uint32 command = q_u->command;
5058 struct current_user user;
5060 WERROR errcode = WERR_BADFUNC;
5062 if (!get_printer_snum(p, handle, &snum)) {
5066 if (!print_job_exists(jobid)) {
5067 return WERR_INVALID_PRINTER_NAME;
5070 get_current_user(&user, p);
5073 case JOB_CONTROL_CANCEL:
5074 case JOB_CONTROL_DELETE:
5075 if (print_job_delete(&user, jobid, &errcode)) {
5079 case JOB_CONTROL_PAUSE:
5080 if (print_job_pause(&user, jobid, &errcode)) {
5084 case JOB_CONTROL_RESTART:
5085 case JOB_CONTROL_RESUME:
5086 if (print_job_resume(&user, jobid, &errcode)) {
5091 return WERR_UNKNOWN_LEVEL;
5097 /****************************************************************************
5098 Enumerates all printer drivers at level 1.
5099 ****************************************************************************/
5100 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5105 fstring *list = NULL;
5107 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5108 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5112 #define MAX_VERSION 4
5114 for (version=0; version<MAX_VERSION; version++) {
5116 ndrivers=get_ntdrivers(&list, architecture, version);
5117 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5123 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5124 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5125 SAFE_FREE(driver_info_1);
5129 else driver_info_1 = tdi1;
5132 for (i=0; i<ndrivers; i++) {
5134 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5135 ZERO_STRUCT(driver);
5136 status = get_a_printer_driver(&driver, 3, list[i],
5137 architecture, version);
5138 if (!W_ERROR_IS_OK(status)) {
5142 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5143 free_a_printer_driver(driver, 3);
5146 *returned+=ndrivers;
5150 /* check the required size. */
5151 for (i=0; i<*returned; i++) {
5152 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5153 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5156 if (!alloc_buffer_size(buffer, *needed)) {
5157 SAFE_FREE(driver_info_1);
5158 return WERR_INSUFFICIENT_BUFFER;
5161 /* fill the buffer with the driver structures */
5162 for (i=0; i<*returned; i++) {
5163 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5164 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5167 SAFE_FREE(driver_info_1);
5169 if (*needed > offered) {
5171 return WERR_INSUFFICIENT_BUFFER;
5177 /****************************************************************************
5178 Enumerates all printer drivers at level 2.
5179 ****************************************************************************/
5180 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5185 fstring *list = NULL;
5187 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5188 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5192 #define MAX_VERSION 4
5194 for (version=0; version<MAX_VERSION; version++) {
5196 ndrivers=get_ntdrivers(&list, architecture, version);
5197 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5203 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5204 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5205 SAFE_FREE(driver_info_2);
5209 else driver_info_2 = tdi2;
5212 for (i=0; i<ndrivers; i++) {
5215 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5216 ZERO_STRUCT(driver);
5217 status = get_a_printer_driver(&driver, 3, list[i],
5218 architecture, version);
5219 if (!W_ERROR_IS_OK(status)) {
5223 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5224 free_a_printer_driver(driver, 3);
5227 *returned+=ndrivers;
5231 /* check the required size. */
5232 for (i=0; i<*returned; i++) {
5233 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5234 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5237 if (!alloc_buffer_size(buffer, *needed)) {
5238 SAFE_FREE(driver_info_2);
5239 return WERR_INSUFFICIENT_BUFFER;
5242 /* fill the buffer with the form structures */
5243 for (i=0; i<*returned; i++) {
5244 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5245 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5248 SAFE_FREE(driver_info_2);
5250 if (*needed > offered) {
5252 return WERR_INSUFFICIENT_BUFFER;
5258 /****************************************************************************
5259 Enumerates all printer drivers at level 3.
5260 ****************************************************************************/
5261 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5266 fstring *list = NULL;
5268 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5269 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5273 #define MAX_VERSION 4
5275 for (version=0; version<MAX_VERSION; version++) {
5277 ndrivers=get_ntdrivers(&list, architecture, version);
5278 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5284 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5285 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5286 SAFE_FREE(driver_info_3);
5290 else driver_info_3 = tdi3;
5293 for (i=0; i<ndrivers; i++) {
5296 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5297 ZERO_STRUCT(driver);
5298 status = get_a_printer_driver(&driver, 3, list[i],
5299 architecture, version);
5300 if (!W_ERROR_IS_OK(status)) {
5304 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5305 free_a_printer_driver(driver, 3);
5308 *returned+=ndrivers;
5312 /* check the required size. */
5313 for (i=0; i<*returned; i++) {
5314 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5315 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5318 if (!alloc_buffer_size(buffer, *needed)) {
5319 SAFE_FREE(driver_info_3);
5320 return WERR_INSUFFICIENT_BUFFER;
5323 /* fill the buffer with the driver structures */
5324 for (i=0; i<*returned; i++) {
5325 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5326 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5329 for (i=0; i<*returned; i++)
5330 SAFE_FREE(driver_info_3[i].dependentfiles);
5332 SAFE_FREE(driver_info_3);
5334 if (*needed > offered) {
5336 return WERR_INSUFFICIENT_BUFFER;
5342 /****************************************************************************
5343 Enumerates all printer drivers.
5344 ****************************************************************************/
5346 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5348 /* UNISTR2 *name = &q_u->name; - notused. */
5349 UNISTR2 *environment = &q_u->environment;
5350 uint32 level = q_u->level;
5351 NEW_BUFFER *buffer = NULL;
5352 uint32 offered = q_u->offered;
5353 uint32 *needed = &r_u->needed;
5354 uint32 *returned = &r_u->returned;
5356 fstring *list = NULL;
5358 fstring architecture;
5360 /* that's an [in out] buffer */
5361 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5362 buffer = r_u->buffer;
5364 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5365 fstrcpy(servername, get_called_name());
5369 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5373 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5375 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5377 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5381 return WERR_UNKNOWN_LEVEL;
5385 /****************************************************************************
5386 ****************************************************************************/
5388 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5390 form->flag=list->flag;
5391 init_unistr(&form->name, list->name);
5392 form->width=list->width;
5393 form->length=list->length;
5394 form->left=list->left;
5395 form->top=list->top;
5396 form->right=list->right;
5397 form->bottom=list->bottom;
5400 /****************************************************************************
5401 ****************************************************************************/
5403 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5405 /* POLICY_HND *handle = &q_u->handle; - notused. */
5406 uint32 level = q_u->level;
5407 NEW_BUFFER *buffer = NULL;
5408 uint32 offered = q_u->offered;
5409 uint32 *needed = &r_u->needed;
5410 uint32 *numofforms = &r_u->numofforms;
5411 uint32 numbuiltinforms;
5413 nt_forms_struct *list=NULL;
5414 nt_forms_struct *builtinlist=NULL;
5419 /* that's an [in out] buffer */
5420 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5421 buffer = r_u->buffer;
5423 DEBUG(4,("_spoolss_enumforms\n"));
5424 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5425 DEBUGADD(5,("Info level [%d]\n", level));
5427 numbuiltinforms = get_builtin_ntforms(&builtinlist);
5428 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
5429 *numofforms = get_ntforms(&list);
5430 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
5431 *numofforms += numbuiltinforms;
5433 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
5437 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5442 /* construct the list of form structures */
5443 for (i=0; i<numbuiltinforms; i++) {
5444 DEBUGADD(6,("Filling form number [%d]\n",i));
5445 fill_form_1(&forms_1[i], &builtinlist[i]);
5448 SAFE_FREE(builtinlist);
5450 for (; i<*numofforms; i++) {
5451 DEBUGADD(6,("Filling form number [%d]\n",i));
5452 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5457 /* check the required size. */
5458 for (i=0; i<numbuiltinforms; i++) {
5459 DEBUGADD(6,("adding form [%d]'s size\n",i));
5460 buffer_size += spoolss_size_form_1(&forms_1[i]);
5462 for (; i<*numofforms; i++) {
5463 DEBUGADD(6,("adding form [%d]'s size\n",i));
5464 buffer_size += spoolss_size_form_1(&forms_1[i]);
5467 *needed=buffer_size;
5469 if (!alloc_buffer_size(buffer, buffer_size)){
5471 return WERR_INSUFFICIENT_BUFFER;
5474 /* fill the buffer with the form structures */
5475 for (i=0; i<numbuiltinforms; i++) {
5476 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5477 smb_io_form_1("", buffer, &forms_1[i], 0);
5479 for (; i<*numofforms; i++) {
5480 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5481 smb_io_form_1("", buffer, &forms_1[i], 0);
5486 if (*needed > offered) {
5488 return WERR_INSUFFICIENT_BUFFER;
5495 SAFE_FREE(builtinlist);
5496 return WERR_UNKNOWN_LEVEL;
5501 /****************************************************************************
5502 ****************************************************************************/
5504 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5506 /* POLICY_HND *handle = &q_u->handle; - notused. */
5507 uint32 level = q_u->level;
5508 UNISTR2 *uni_formname = &q_u->formname;
5509 NEW_BUFFER *buffer = NULL;
5510 uint32 offered = q_u->offered;
5511 uint32 *needed = &r_u->needed;
5513 nt_forms_struct *list=NULL;
5514 nt_forms_struct builtin_form;
5519 int numofforms=0, i=0;
5521 /* that's an [in out] buffer */
5522 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5523 buffer = r_u->buffer;
5525 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5527 DEBUG(4,("_spoolss_getform\n"));
5528 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5529 DEBUGADD(5,("Info level [%d]\n", level));
5531 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5532 if (!foundBuiltin) {
5533 numofforms = get_ntforms(&list);
5534 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5536 if (numofforms == 0)
5543 fill_form_1(&form_1, &builtin_form);
5546 /* Check if the requested name is in the list of form structures */
5547 for (i=0; i<numofforms; i++) {
5549 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5551 if (strequal(form_name, list[i].name)) {
5552 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5553 fill_form_1(&form_1, &list[i]);
5559 if (i == numofforms) {
5563 /* check the required size. */
5565 *needed=spoolss_size_form_1(&form_1);
5567 if (!alloc_buffer_size(buffer, buffer_size)){
5568 return WERR_INSUFFICIENT_BUFFER;
5571 if (*needed > offered) {
5572 return WERR_INSUFFICIENT_BUFFER;
5575 /* fill the buffer with the form structures */
5576 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5577 smb_io_form_1("", buffer, &form_1, 0);
5583 return WERR_UNKNOWN_LEVEL;
5587 /****************************************************************************
5588 ****************************************************************************/
5589 static void fill_port_1(PORT_INFO_1 *port, char *name)
5591 init_unistr(&port->port_name, name);
5594 /****************************************************************************
5595 ****************************************************************************/
5596 static void fill_port_2(PORT_INFO_2 *port, char *name)
5598 init_unistr(&port->port_name, name);
5599 init_unistr(&port->monitor_name, "Local Monitor");
5600 init_unistr(&port->description, "Local Port");
5601 #define PORT_TYPE_WRITE 1
5602 port->port_type=PORT_TYPE_WRITE;
5606 /****************************************************************************
5608 ****************************************************************************/
5609 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5611 PORT_INFO_1 *ports=NULL;
5614 if (*lp_enumports_cmd()) {
5615 char *cmd = lp_enumports_cmd();
5622 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5624 DEBUG(10,("Running [%s]\n", command));
5625 ret = smbrun(command, &fd);
5626 DEBUG(10,("Returned [%d]\n", ret));
5630 /* Is this the best error to return here? */
5631 return WERR_ACCESS_DENIED;
5635 qlines = fd_lines_load(fd, &numlines);
5636 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5640 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5641 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
5642 werror_str(WERR_NOMEM)));
5643 file_lines_free(qlines);
5647 for (i=0; i<numlines; i++) {
5648 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5649 fill_port_1(&ports[i], qlines[i]);
5652 file_lines_free(qlines);
5655 *returned = numlines;
5658 *returned = 1; /* Sole Samba port returned. */
5660 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5663 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5665 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5668 /* check the required size. */
5669 for (i=0; i<*returned; i++) {
5670 DEBUGADD(6,("adding port [%d]'s size\n", i));
5671 *needed += spoolss_size_port_info_1(&ports[i]);
5674 if (!alloc_buffer_size(buffer, *needed)) {
5676 return WERR_INSUFFICIENT_BUFFER;
5679 /* fill the buffer with the ports structures */
5680 for (i=0; i<*returned; i++) {
5681 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5682 smb_io_port_1("", buffer, &ports[i], 0);
5687 if (*needed > offered) {
5689 return WERR_INSUFFICIENT_BUFFER;
5695 /****************************************************************************
5697 ****************************************************************************/
5699 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5701 PORT_INFO_2 *ports=NULL;
5704 if (*lp_enumports_cmd()) {
5705 char *cmd = lp_enumports_cmd();
5714 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5715 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5717 path = lp_lockdir();
5719 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
5720 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5723 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5724 ret = smbrun(command, &fd);
5725 DEBUGADD(10,("returned [%d]\n", ret));
5729 /* Is this the best error to return here? */
5730 return WERR_ACCESS_DENIED;
5734 qlines = fd_lines_load(fd, &numlines);
5735 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5739 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5740 file_lines_free(qlines);
5744 for (i=0; i<numlines; i++) {
5745 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5746 fill_port_2(&(ports[i]), qlines[i]);
5749 file_lines_free(qlines);
5752 *returned = numlines;
5758 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5761 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5763 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5766 /* check the required size. */
5767 for (i=0; i<*returned; i++) {
5768 DEBUGADD(6,("adding port [%d]'s size\n", i));
5769 *needed += spoolss_size_port_info_2(&ports[i]);
5772 if (!alloc_buffer_size(buffer, *needed)) {
5774 return WERR_INSUFFICIENT_BUFFER;
5777 /* fill the buffer with the ports structures */
5778 for (i=0; i<*returned; i++) {
5779 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5780 smb_io_port_2("", buffer, &ports[i], 0);
5785 if (*needed > offered) {
5787 return WERR_INSUFFICIENT_BUFFER;
5793 /****************************************************************************
5795 ****************************************************************************/
5797 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5799 /* UNISTR2 *name = &q_u->name; - notused. */
5800 uint32 level = q_u->level;
5801 NEW_BUFFER *buffer = NULL;
5802 uint32 offered = q_u->offered;
5803 uint32 *needed = &r_u->needed;
5804 uint32 *returned = &r_u->returned;
5806 /* that's an [in out] buffer */
5807 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5808 buffer = r_u->buffer;
5810 DEBUG(4,("_spoolss_enumports\n"));
5817 return enumports_level_1(buffer, offered, needed, returned);
5819 return enumports_level_2(buffer, offered, needed, returned);
5821 return WERR_UNKNOWN_LEVEL;
5825 /****************************************************************************
5826 ****************************************************************************/
5827 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5828 const SPOOL_PRINTER_INFO_LEVEL *info,
5829 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5830 uint32 user_switch, const SPOOL_USER_CTR *user,
5833 NT_PRINTER_INFO_LEVEL *printer = NULL;
5836 WERROR err = WERR_OK;
5838 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5839 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5843 ZERO_STRUCTP(printer);
5845 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5846 if (!convert_printer_info(info, printer, 2)) {
5847 free_a_printer(&printer, 2);
5851 /* check to see if the printer already exists */
5853 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
5854 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
5855 printer->info_2->sharename));
5856 free_a_printer(&printer, 2);
5857 return WERR_PRINTER_ALREADY_EXISTS;
5860 if (*lp_addprinter_cmd() )
5861 if ( !add_printer_hook(printer) ) {
5862 free_a_printer(&printer,2);
5863 return WERR_ACCESS_DENIED;
5866 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
5867 printer->info_2->sharename);
5869 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5870 free_a_printer(&printer,2);
5871 return WERR_ACCESS_DENIED;
5874 /* you must be a printer admin to add a new printer */
5875 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5876 free_a_printer(&printer,2);
5877 return WERR_ACCESS_DENIED;
5881 * Do sanity check on the requested changes for Samba.
5884 if (!check_printer_ok(printer->info_2, snum)) {
5885 free_a_printer(&printer,2);
5886 return WERR_INVALID_PARAM;
5890 * When a printer is created, the drivername bound to the printer is used
5891 * to lookup previously saved driver initialization info, which is then
5892 * bound to the new printer, simulating what happens in the Windows arch.
5894 set_driver_init(printer, 2);
5896 /* write the ASCII on disk */
5897 err = add_a_printer(*printer, 2);
5898 if (!W_ERROR_IS_OK(err)) {
5899 free_a_printer(&printer,2);
5903 if (!open_printer_hnd(p, handle, name)) {
5904 /* Handle open failed - remove addition. */
5905 del_a_printer(printer->info_2->sharename);
5906 free_a_printer(&printer,2);
5907 return WERR_ACCESS_DENIED;
5910 free_a_printer(&printer,2);
5912 srv_spoolss_sendnotify(p, handle);
5917 /****************************************************************************
5918 ****************************************************************************/
5920 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5922 UNISTR2 *uni_srv_name = &q_u->server_name;
5923 uint32 level = q_u->level;
5924 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5925 uint32 unk0 = q_u->unk0;
5926 uint32 unk1 = q_u->unk1;
5927 uint32 unk2 = q_u->unk2;
5928 uint32 unk3 = q_u->unk3;
5929 uint32 user_switch = q_u->user_switch;
5930 SPOOL_USER_CTR *user = &q_u->user_ctr;
5931 POLICY_HND *handle = &r_u->handle;
5935 /* we don't handle yet */
5936 /* but I know what to do ... */
5937 return WERR_UNKNOWN_LEVEL;
5939 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5940 unk0, unk1, unk2, unk3,
5941 user_switch, user, handle);
5943 return WERR_UNKNOWN_LEVEL;
5947 /****************************************************************************
5948 ****************************************************************************/
5950 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5952 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5953 uint32 level = q_u->level;
5954 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5955 WERROR err = WERR_OK;
5956 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5957 struct current_user user;
5959 ZERO_STRUCT(driver);
5961 get_current_user(&user, p);
5963 if (!convert_printer_driver_info(info, &driver, level)) {
5968 DEBUG(5,("Cleaning driver's information\n"));
5969 err = clean_up_driver_struct(driver, level, &user);
5970 if (!W_ERROR_IS_OK(err))
5973 DEBUG(5,("Moving driver to final destination\n"));
5974 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5975 if (W_ERROR_IS_OK(err))
5976 err = WERR_ACCESS_DENIED;
5980 if (add_a_printer_driver(driver, level)!=0) {
5981 err = WERR_ACCESS_DENIED;
5986 free_a_printer_driver(driver, level);
5990 /****************************************************************************
5991 ****************************************************************************/
5992 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5994 init_unistr(&info->name, name);
5997 /****************************************************************************
5998 ****************************************************************************/
5999 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6003 pstring short_archi;
6004 DRIVER_DIRECTORY_1 *info=NULL;
6006 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6008 if (get_short_archi(short_archi, long_archi)==False)
6009 return WERR_INVALID_ENVIRONMENT;
6011 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6014 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6016 DEBUG(4,("printer driver directory: [%s]\n", path));
6018 fill_driverdir_1(info, path);
6020 *needed += spoolss_size_driverdir_info_1(info);
6022 if (!alloc_buffer_size(buffer, *needed)) {
6024 return WERR_INSUFFICIENT_BUFFER;
6027 smb_io_driverdir_1("", buffer, info, 0);
6031 if (*needed > offered)
6032 return WERR_INSUFFICIENT_BUFFER;
6037 /****************************************************************************
6038 ****************************************************************************/
6040 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6042 UNISTR2 *name = &q_u->name;
6043 UNISTR2 *uni_environment = &q_u->environment;
6044 uint32 level = q_u->level;
6045 NEW_BUFFER *buffer = NULL;
6046 uint32 offered = q_u->offered;
6047 uint32 *needed = &r_u->needed;
6049 /* that's an [in out] buffer */
6050 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6051 buffer = r_u->buffer;
6053 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6059 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6061 return WERR_UNKNOWN_LEVEL;
6065 /****************************************************************************
6066 ****************************************************************************/
6068 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6070 POLICY_HND *handle = &q_u->handle;
6071 uint32 idx = q_u->index;
6072 uint32 in_value_len = q_u->valuesize;
6073 uint32 in_data_len = q_u->datasize;
6074 uint32 *out_max_value_len = &r_u->valuesize;
6075 uint16 **out_value = &r_u->value;
6076 uint32 *out_value_len = &r_u->realvaluesize;
6077 uint32 *out_type = &r_u->type;
6078 uint32 *out_max_data_len = &r_u->datasize;
6079 uint8 **data_out = &r_u->data;
6080 uint32 *out_data_len = &r_u->realdatasize;
6082 NT_PRINTER_INFO_LEVEL *printer = NULL;
6087 uint32 biggest_valuesize;
6088 uint32 biggest_datasize;
6090 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6096 ZERO_STRUCT(printer);
6100 *out_max_data_len=0;
6104 DEBUG(5,("spoolss_enumprinterdata\n"));
6107 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6111 if (!get_printer_snum(p,handle, &snum))
6114 result = get_a_printer(&printer, 2, lp_servicename(snum));
6115 if (!W_ERROR_IS_OK(result))
6119 * The NT machine wants to know the biggest size of value and data
6121 * cf: MSDN EnumPrinterData remark section
6123 if ( (in_value_len==0) && (in_data_len==0) ) {
6124 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6128 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6129 * if this parameter size doesn't exist.
6130 * Ok - my opinion here is that the client is not asking for the greatest
6131 * possible size of all the parameters, but is asking specifically for the size needed
6132 * for this specific parameter. In that case we can remove the loop below and
6133 * simplify this lookup code considerably. JF - comments welcome. JRA.
6136 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6138 free_a_printer(&printer, 2);
6139 return WERR_NO_MORE_ITEMS;
6146 biggest_valuesize=0;
6149 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6150 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6151 if (data_len > biggest_datasize) biggest_datasize=data_len;
6153 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6159 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6160 *out_value_len=2*(1+biggest_valuesize);
6161 *out_data_len=biggest_datasize;
6163 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6165 free_a_printer(&printer, 2);
6170 * the value len is wrong in NT sp3
6171 * that's the number of bytes not the number of unicode chars
6174 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6177 free_a_printer(&printer, 2);
6179 /* out_value should default to "" or else NT4 has
6180 problems unmarshalling the response */
6182 *out_max_value_len=(in_value_len/sizeof(uint16));
6183 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL)
6186 ZERO_STRUCTP(*out_value);
6187 *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
6189 /* the data is counted in bytes */
6190 *out_max_data_len = in_data_len;
6191 *out_data_len = in_data_len;
6192 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL)
6195 memset(*data_out,'\0',in_data_len);
6197 return WERR_NO_MORE_ITEMS;
6200 free_a_printer(&printer, 2);
6204 * - counted in bytes in the request
6205 * - counted in UNICODE chars in the max reply
6206 * - counted in bytes in the real size
6208 * take a pause *before* coding not *during* coding
6211 *out_max_value_len=(in_value_len/sizeof(uint16));
6212 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6217 *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6221 /* the data is counted in bytes */
6222 *out_max_data_len=in_data_len;
6223 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6228 memcpy(*data_out, data, (size_t)data_len);
6229 *out_data_len=data_len;
6236 /****************************************************************************
6237 ****************************************************************************/
6239 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6241 POLICY_HND *handle = &q_u->handle;
6242 UNISTR2 *value = &q_u->value;
6243 uint32 type = q_u->type;
6244 /* uint32 max_len = q_u->max_len; - notused. */
6245 uint8 *data = q_u->data;
6246 uint32 real_len = q_u->real_len;
6247 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6249 NT_PRINTER_INFO_LEVEL *printer = NULL;
6250 NT_PRINTER_PARAM *param = NULL, old_param;
6252 WERROR status = WERR_OK;
6253 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6255 DEBUG(5,("spoolss_setprinterdata\n"));
6258 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6262 if (!get_printer_snum(p,handle, &snum))
6265 ZERO_STRUCT(old_param);
6268 * Access check : NT returns "access denied" if you make a
6269 * SetPrinterData call without the necessary privildge.
6270 * we were originally returning OK if nothing changed
6271 * which made Win2k issue **a lot** of SetPrinterData
6272 * when connecting to a printer --jerry
6275 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6276 DEBUG(3, ("security descriptor change denied by existing "
6277 "security descriptor\n"));
6278 status = WERR_ACCESS_DENIED;
6282 /* Check if we are making any changes or not. Return true if
6283 nothing is actually changing. This is not needed anymore but
6284 has been left in as an optimization to keep from from
6285 writing to disk as often --jerry */
6287 status = get_a_printer(&printer, 2, lp_servicename(snum));
6288 if (!W_ERROR_IS_OK(status))
6291 convert_specific_param(¶m, value , type, data, real_len);
6294 if (get_specific_param(*printer, 2, param->value, &old_param.data,
6295 &old_param.type, (uint32 *)&old_param.data_len)) {
6297 if (param->type == old_param.type &&
6298 param->data_len == old_param.data_len &&
6299 memcmp(param->data, old_param.data,
6300 old_param.data_len) == 0) {
6302 DEBUG(3, ("setprinterdata hasn't changed\n"));
6309 unlink_specific_param_if_exist(printer->info_2, param);
6312 * When client side code sets a magic printer data key, detect it and save
6313 * the current printer data and the magic key's data (its the DEVMODE) for
6314 * future printer/driver initializations.
6316 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6318 * Set devmode and printer initialization info
6320 status = save_driver_init(printer, 2, param);
6323 add_a_specific_param(printer->info_2, ¶m);
6324 status = mod_a_printer(*printer, 2);
6328 free_a_printer(&printer, 2);
6330 free_nt_printer_param(¶m);
6331 SAFE_FREE(old_param.data);
6336 /****************************************************************************
6337 ****************************************************************************/
6339 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6341 POLICY_HND *handle = &q_u->handle;
6342 UNISTR2 *value = &q_u->valuename;
6344 NT_PRINTER_INFO_LEVEL *printer = NULL;
6345 NT_PRINTER_PARAM param;
6347 WERROR status = WERR_OK;
6348 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6350 DEBUG(5,("spoolss_deleteprinterdata\n"));
6353 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6357 if (!get_printer_snum(p, handle, &snum))
6360 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6361 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6362 "change denied by existing security descriptor\n"));
6363 return WERR_ACCESS_DENIED;
6366 status = get_a_printer(&printer, 2, lp_servicename(snum));
6367 if (!W_ERROR_IS_OK(status))
6370 ZERO_STRUCTP(¶m);
6371 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6373 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
6374 status = WERR_INVALID_PARAM;
6376 status = mod_a_printer(*printer, 2);
6378 free_a_printer(&printer, 2);
6382 /****************************************************************************
6383 ****************************************************************************/
6385 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6387 POLICY_HND *handle = &q_u->handle;
6388 /* uint32 level = q_u->level; - notused. */
6389 FORM *form = &q_u->form;
6390 nt_forms_struct tmpForm;
6393 nt_forms_struct *list=NULL;
6394 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6396 DEBUG(5,("spoolss_addform\n"));
6399 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6404 * FIXME!! Feels like there should be an access check here, but haven't
6405 * had time to verify. --jerry
6408 /* can't add if builtin */
6409 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6410 return WERR_INVALID_PARAM;
6413 count=get_ntforms(&list);
6414 if(!add_a_form(&list, form, &count))
6416 write_ntforms(&list, count);
6423 /****************************************************************************
6424 ****************************************************************************/
6426 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6428 POLICY_HND *handle = &q_u->handle;
6429 UNISTR2 *form_name = &q_u->name;
6430 nt_forms_struct tmpForm;
6432 WERROR ret = WERR_OK;
6433 nt_forms_struct *list=NULL;
6434 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6436 DEBUG(5,("spoolss_deleteform\n"));
6439 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6443 /* can't delete if builtin */
6444 if (get_a_builtin_ntform(form_name,&tmpForm)) {
6445 return WERR_INVALID_PARAM;
6448 count = get_ntforms(&list);
6449 if(!delete_a_form(&list, form_name, &count, &ret))
6450 return WERR_INVALID_PARAM;
6457 /****************************************************************************
6458 ****************************************************************************/
6460 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6462 POLICY_HND *handle = &q_u->handle;
6463 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6464 /* uint32 level = q_u->level; - notused. */
6465 FORM *form = &q_u->form;
6466 nt_forms_struct tmpForm;
6469 nt_forms_struct *list=NULL;
6470 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6472 DEBUG(5,("spoolss_setform\n"));
6475 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6478 /* can't set if builtin */
6479 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6480 return WERR_INVALID_PARAM;
6483 count=get_ntforms(&list);
6484 update_a_form(&list, form, count);
6485 write_ntforms(&list, count);
6492 /****************************************************************************
6493 enumprintprocessors level 1.
6494 ****************************************************************************/
6495 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6497 PRINTPROCESSOR_1 *info_1=NULL;
6499 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6504 init_unistr(&info_1->name, "winprint");
6506 *needed += spoolss_size_printprocessor_info_1(info_1);
6508 if (!alloc_buffer_size(buffer, *needed))
6509 return WERR_INSUFFICIENT_BUFFER;
6511 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6515 if (*needed > offered) {
6517 return WERR_INSUFFICIENT_BUFFER;
6523 /****************************************************************************
6524 ****************************************************************************/
6526 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6528 /* UNISTR2 *name = &q_u->name; - notused. */
6529 /* UNISTR2 *environment = &q_u->environment; - notused. */
6530 uint32 level = q_u->level;
6531 NEW_BUFFER *buffer = NULL;
6532 uint32 offered = q_u->offered;
6533 uint32 *needed = &r_u->needed;
6534 uint32 *returned = &r_u->returned;
6536 /* that's an [in out] buffer */
6537 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6538 buffer = r_u->buffer;
6540 DEBUG(5,("spoolss_enumprintprocessors\n"));
6543 * Enumerate the print processors ...
6545 * Just reply with "winprint", to keep NT happy
6546 * and I can use my nice printer checker.
6554 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6556 return WERR_UNKNOWN_LEVEL;
6560 /****************************************************************************
6561 enumprintprocdatatypes level 1.
6562 ****************************************************************************/
6563 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6565 PRINTPROCDATATYPE_1 *info_1=NULL;
6567 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6572 init_unistr(&info_1->name, "RAW");
6574 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6576 if (!alloc_buffer_size(buffer, *needed))
6577 return WERR_INSUFFICIENT_BUFFER;
6579 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6583 if (*needed > offered) {
6585 return WERR_INSUFFICIENT_BUFFER;
6591 /****************************************************************************
6592 ****************************************************************************/
6594 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6596 /* UNISTR2 *name = &q_u->name; - notused. */
6597 /* UNISTR2 *processor = &q_u->processor; - notused. */
6598 uint32 level = q_u->level;
6599 NEW_BUFFER *buffer = NULL;
6600 uint32 offered = q_u->offered;
6601 uint32 *needed = &r_u->needed;
6602 uint32 *returned = &r_u->returned;
6604 /* that's an [in out] buffer */
6605 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6606 buffer = r_u->buffer;
6608 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6615 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6617 return WERR_UNKNOWN_LEVEL;
6621 /****************************************************************************
6622 enumprintmonitors level 1.
6623 ****************************************************************************/
6625 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6627 PRINTMONITOR_1 *info_1=NULL;
6629 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6634 init_unistr(&info_1->name, "Local Port");
6636 *needed += spoolss_size_printmonitor_info_1(info_1);
6638 if (!alloc_buffer_size(buffer, *needed))
6639 return WERR_INSUFFICIENT_BUFFER;
6641 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6645 if (*needed > offered) {
6647 return WERR_INSUFFICIENT_BUFFER;
6653 /****************************************************************************
6654 enumprintmonitors level 2.
6655 ****************************************************************************/
6656 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6658 PRINTMONITOR_2 *info_2=NULL;
6660 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6665 init_unistr(&info_2->name, "Local Port");
6666 init_unistr(&info_2->environment, "Windows NT X86");
6667 init_unistr(&info_2->dll_name, "localmon.dll");
6669 *needed += spoolss_size_printmonitor_info_2(info_2);
6671 if (!alloc_buffer_size(buffer, *needed))
6672 return WERR_INSUFFICIENT_BUFFER;
6674 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6678 if (*needed > offered) {
6680 return WERR_INSUFFICIENT_BUFFER;
6686 /****************************************************************************
6687 ****************************************************************************/
6689 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6691 /* UNISTR2 *name = &q_u->name; - notused. */
6692 uint32 level = q_u->level;
6693 NEW_BUFFER *buffer = NULL;
6694 uint32 offered = q_u->offered;
6695 uint32 *needed = &r_u->needed;
6696 uint32 *returned = &r_u->returned;
6698 /* that's an [in out] buffer */
6699 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6700 buffer = r_u->buffer;
6702 DEBUG(5,("spoolss_enumprintmonitors\n"));
6705 * Enumerate the print monitors ...
6707 * Just reply with "Local Port", to keep NT happy
6708 * and I can use my nice printer checker.
6716 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6718 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6720 return WERR_UNKNOWN_LEVEL;
6724 /****************************************************************************
6725 ****************************************************************************/
6726 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6730 JOB_INFO_1 *info_1=NULL;
6732 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6734 if (info_1 == NULL) {
6739 for (i=0; i<count && found==False; i++) {
6740 if (queue[i].job==(int)jobid)
6747 /* NT treats not found as bad param... yet another bad choice */
6748 return WERR_INVALID_PARAM;
6751 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6755 *needed += spoolss_size_job_info_1(info_1);
6757 if (!alloc_buffer_size(buffer, *needed)) {
6759 return WERR_INSUFFICIENT_BUFFER;
6762 smb_io_job_info_1("", buffer, info_1, 0);
6766 if (*needed > offered)
6767 return WERR_INSUFFICIENT_BUFFER;
6773 /****************************************************************************
6774 ****************************************************************************/
6775 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6780 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6783 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6785 ZERO_STRUCTP(info_2);
6787 if (info_2 == NULL) {
6792 for (i=0; i<count && found==False; i++) {
6793 if (queue[i].job==(int)jobid)
6800 /* NT treats not found as bad param... yet another bad choice */
6801 return WERR_INVALID_PARAM;
6804 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6805 if (!W_ERROR_IS_OK(ret)) {
6810 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6812 free_a_printer(&ntprinter, 2);
6815 *needed += spoolss_size_job_info_2(info_2);
6817 if (!alloc_buffer_size(buffer, *needed)) {
6819 return WERR_INSUFFICIENT_BUFFER;
6822 smb_io_job_info_2("", buffer, info_2, 0);
6824 free_job_info_2(info_2);
6827 if (*needed > offered)
6828 return WERR_INSUFFICIENT_BUFFER;
6833 /****************************************************************************
6834 ****************************************************************************/
6836 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6838 POLICY_HND *handle = &q_u->handle;
6839 uint32 jobid = q_u->jobid;
6840 uint32 level = q_u->level;
6841 NEW_BUFFER *buffer = NULL;
6842 uint32 offered = q_u->offered;
6843 uint32 *needed = &r_u->needed;
6847 print_queue_struct *queue=NULL;
6848 print_status_struct prt_status;
6850 /* that's an [in out] buffer */
6851 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6852 buffer = r_u->buffer;
6854 DEBUG(5,("spoolss_getjob\n"));
6858 if (!get_printer_snum(p, handle, &snum))
6861 count = print_queue_status(snum, &queue, &prt_status);
6863 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6864 count, prt_status.status, prt_status.message));
6868 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6870 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6873 return WERR_UNKNOWN_LEVEL;
6877 /********************************************************************
6878 * spoolss_getprinterdataex
6879 ********************************************************************/
6881 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
6883 POLICY_HND *handle = &q_u->handle;
6884 uint32 in_size = q_u->size;
6885 uint32 *type = &r_u->type;
6886 uint32 *out_size = &r_u->size;
6887 uint8 **data = &r_u->data;
6888 uint32 *needed = &r_u->needed;
6891 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6894 DEBUG(4,("_spoolss_getprinterdataex\n"));
6896 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
6897 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
6899 /* in case of problem, return some default values */
6906 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
6908 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6913 /* Is the handle to a printer or to the server? */
6915 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6917 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
6918 return WERR_INVALID_PARAM;
6923 * From MSDN documentation of GetPrinterDataEx: pass request
6924 * to GetPrinterData if key is "PrinterDriverData". This is
6925 * the only key we really support. Other keys to implement:
6931 if (strcmp(key, "PrinterDriverData") != 0)
6932 return WERR_INVALID_PARAM;
6934 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
6935 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
6936 type, data, needed, in_size);
6941 DEBUG(5, ("value not found, allocating %d\n", *out_size));
6943 /* reply this param doesn't exist */
6945 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
6951 return WERR_INVALID_PARAM;
6954 if (*needed > *out_size)
6955 return WERR_MORE_DATA;
6960 /********************************************************************
6961 * spoolss_setprinterdata
6962 ********************************************************************/
6964 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
6966 SPOOL_Q_SETPRINTERDATA q_u_local;
6967 SPOOL_R_SETPRINTERDATA r_u_local;
6970 DEBUG(4,("_spoolss_setprinterdataex\n"));
6972 /* From MSDN documentation of SetPrinterDataEx: pass request to
6973 SetPrinterData if key is "PrinterDriverData" */
6975 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6977 if (strcmp(key, "PrinterDriverData") == 0)
6978 return WERR_INVALID_PARAM;
6980 ZERO_STRUCT(q_u_local);
6981 ZERO_STRUCT(r_u_local);
6983 /* make a copy to call _spoolss_setprinterdata() */
6985 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
6986 copy_unistr2(&q_u_local.value, &q_u->value);
6987 q_u_local.type = q_u->type;
6988 q_u_local.max_len = q_u->max_len;
6989 q_u_local.data = q_u->data;
6990 q_u_local.real_len = q_u->real_len;
6991 q_u_local.numeric_data = q_u->numeric_data;
6993 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
6996 /********************************************************************
6997 * spoolss_enumprinterkey
6998 ********************************************************************/
7000 /* constants for EnumPrinterKey() */
7001 #define ENUMERATED_KEY_SIZE 19
7003 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
7006 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
7009 char *PrinterKey = "PrinterDriverData";
7011 DEBUG(4,("_spoolss_enumprinterkey\n"));
7013 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7016 * we only support enumating all keys (key == "")
7017 * Of course, the only key we support is the "PrinterDriverData"
7020 if (strlen(key) == 0)
7022 r_u->needed = ENUMERATED_KEY_SIZE *2;
7023 if (q_u->size < r_u->needed)
7024 return WERR_MORE_DATA;
7027 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
7029 enumkeys[i] = (uint16)(*ptr);
7033 /* tag of with 2 '\0's */
7034 enumkeys[i++] = '\0';
7037 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
7038 return WERR_BADFILE;
7043 /* The "PrinterDriverData" key should have no subkeys */
7044 if (strcmp(key, PrinterKey) == 0)
7047 if (q_u->size < r_u->needed)
7048 return WERR_MORE_DATA;
7050 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
7051 return WERR_BADFILE;
7057 /* The return value for an unknown key is documented in MSDN
7058 EnumPrinterKey description */
7059 return WERR_BADFILE;
7062 /********************************************************************
7063 * spoolss_enumprinterdataex
7064 ********************************************************************/
7066 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
7068 POLICY_HND *handle = &q_u->handle;
7069 uint32 in_size = q_u->size;
7072 NT_PRINTER_INFO_LEVEL *printer = NULL;
7073 PRINTER_ENUM_VALUES *enum_values = NULL;
7075 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7084 DEBUG(4,("_spoolss_enumprinterdataex\n"));
7087 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
7093 * The only key we support is "PrinterDriverData". This should return
7094 > an array of all the key/value pairs returned by EnumPrinterDataSee
7095 * _spoolss_getprinterdataex() for details --jerry
7098 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7099 if (strcmp(key, "PrinterDriverData") != 0)
7101 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
7102 return WERR_INVALID_PARAM;
7106 if (!get_printer_snum(p,handle, &snum))
7109 ZERO_STRUCT(printer);
7110 result = get_a_printer(&printer, 2, lp_servicename(snum));
7111 if (!W_ERROR_IS_OK(result))
7116 * loop through all params and build the array to pass
7117 * back to the client
7124 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
7126 PRINTER_ENUM_VALUES *ptr;
7129 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7131 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7133 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7134 result = WERR_NOMEM;
7140 init_unistr(&enum_values[num_entries].valuename, value);
7141 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7142 enum_values[num_entries].type = type;
7145 * NULL terminate REG_SZ
7146 * FIXME!!! We should not be correctly problems in the way
7147 * we store PrinterData here. Need to investogate
7148 * SetPrinterData[Ex] --jerry
7151 if (type == REG_SZ) {
7152 /* fix alignment if the string was stored
7153 in a bizarre fashion */
7154 if ((data_len % 2) == 0)
7157 add_len = data_len % 2;
7160 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7161 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7162 result = WERR_NOMEM;
7165 memcpy(enum_values[num_entries].data, data, data_len);
7166 enum_values[num_entries].data_len = data_len + add_len;
7168 /* keep track of the size of the array in bytes */
7170 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7176 r_u->needed = needed;
7177 r_u->returned = num_entries;
7179 if (needed > in_size) {
7180 result = WERR_MORE_DATA;
7184 /* copy data into the reply */
7186 r_u->ctr.size = r_u->needed;
7187 r_u->ctr.size_of_array = r_u->returned;
7188 r_u->ctr.values = enum_values;
7193 free_a_printer(&printer, 2);
7198 /****************************************************************************
7199 ****************************************************************************/
7201 /* Disabled because it doesn't fix the bug I am looking at but it would be
7202 a shame to throw away the code. -tpot */
7206 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
7208 init_unistr(&info->name, name);
7211 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
7212 UNISTR2 *environment,
7219 pstring short_archi;
7220 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
7222 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
7224 if (get_short_archi(short_archi, long_archi)==False)
7225 return WERR_INVALID_ENVIRONMENT;
7227 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
7230 /* Not sure what to return here - are UNC names valid here?.
7231 Windows returns the string: C:\WINNT\System32\spool\PRTPROCS\W32X86
7232 which is pretty bogus for a RPC. */
7234 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7236 DEBUG(4,("print processor directory: [%s]\n", path));
7238 fill_printprocessordirectory_1(info, path);
7240 *needed += spoolss_size_printprocessordirectory_info_1(info);
7242 if (!alloc_buffer_size(buffer, *needed)) {
7244 return WERR_INSUFFICIENT_BUFFER;
7247 smb_io_printprocessordirectory_1("", buffer, info, 0);
7251 if (*needed > offered)
7252 return WERR_INSUFFICIENT_BUFFER;
7257 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
7259 uint32 level = q_u->level;
7260 NEW_BUFFER *buffer = NULL;
7261 uint32 offered = q_u->offered;
7262 uint32 *needed = &r_u->needed;
7264 /* that's an [in out] buffer */
7265 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7266 buffer = r_u->buffer;
7268 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7274 return getprintprocessordirectory_level_1
7275 (&q_u->name, &q_u->environment, buffer, offered, needed);
7277 return WERR_UNKNOWN_LEVEL;
7280 return WERR_ACCESS_DENIED;