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; 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 Spoolss_enumprinters.
2878 ********************************************************************/
2879 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2883 int n_services=lp_numservices();
2884 PRINTER_INFO_1 *tp, *printers=NULL;
2885 PRINTER_INFO_1 current_prt;
2887 DEBUG(4,("enum_all_printers_info_1\n"));
2889 for (snum=0; snum<n_services; snum++) {
2890 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2891 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2893 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2894 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2895 DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2896 SAFE_FREE(printers);
2901 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2902 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
2908 /* check the required size. */
2909 for (i=0; i<*returned; i++)
2910 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2912 if (!alloc_buffer_size(buffer, *needed))
2913 return WERR_INSUFFICIENT_BUFFER;
2915 /* fill the buffer with the structures */
2916 for (i=0; i<*returned; i++)
2917 smb_io_printer_info_1("", buffer, &printers[i], 0);
2920 SAFE_FREE(printers);
2922 if (*needed > offered) {
2924 return WERR_INSUFFICIENT_BUFFER;
2930 /********************************************************************
2931 enum_all_printers_info_1_local.
2932 *********************************************************************/
2933 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2935 DEBUG(4,("enum_all_printers_info_1_local\n"));
2937 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2940 /********************************************************************
2941 enum_all_printers_info_1_name.
2942 *********************************************************************/
2943 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2947 DEBUG(4,("enum_all_printers_info_1_name\n"));
2949 if ((name[0] == '\\') && (name[1] == '\\'))
2952 if (is_myname_or_ipaddr(s)) {
2953 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2956 return WERR_INVALID_NAME;
2959 /********************************************************************
2960 enum_all_printers_info_1_remote.
2961 *********************************************************************/
2962 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2964 PRINTER_INFO_1 *printer;
2965 fstring printername;
2968 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2970 /* JFM: currently it's more a place holder than anything else.
2971 * In the spooler world there is a notion of server registration.
2972 * the print servers are registring (sp ?) on the PDC (in the same domain)
2974 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2977 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2982 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
2983 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
2984 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2986 init_unistr(&printer->description, desc);
2987 init_unistr(&printer->name, printername);
2988 init_unistr(&printer->comment, comment);
2989 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2991 /* check the required size. */
2992 *needed += spoolss_size_printer_info_1(printer);
2994 if (!alloc_buffer_size(buffer, *needed)) {
2996 return WERR_INSUFFICIENT_BUFFER;
2999 /* fill the buffer with the structures */
3000 smb_io_printer_info_1("", buffer, printer, 0);
3005 if (*needed > offered) {
3007 return WERR_INSUFFICIENT_BUFFER;
3013 /********************************************************************
3014 enum_all_printers_info_1_network.
3015 *********************************************************************/
3017 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3019 DEBUG(4,("enum_all_printers_info_1_network\n"));
3021 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3024 /********************************************************************
3025 * api_spoolss_enumprinters
3027 * called from api_spoolss_enumprinters (see this to understand)
3028 ********************************************************************/
3030 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3034 int n_services=lp_numservices();
3035 PRINTER_INFO_2 *tp, *printers=NULL;
3036 PRINTER_INFO_2 current_prt;
3038 for (snum=0; snum<n_services; snum++) {
3039 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3040 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3042 if (construct_printer_info_2(¤t_prt, snum)) {
3043 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3044 DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3045 SAFE_FREE(printers);
3050 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3051 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
3057 /* check the required size. */
3058 for (i=0; i<*returned; i++)
3059 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3061 if (!alloc_buffer_size(buffer, *needed)) {
3062 for (i=0; i<*returned; i++) {
3063 free_devmode(printers[i].devmode);
3065 SAFE_FREE(printers);
3066 return WERR_INSUFFICIENT_BUFFER;
3069 /* fill the buffer with the structures */
3070 for (i=0; i<*returned; i++)
3071 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3074 for (i=0; i<*returned; i++) {
3075 free_devmode(printers[i].devmode);
3077 SAFE_FREE(printers);
3079 if (*needed > offered) {
3081 return WERR_INSUFFICIENT_BUFFER;
3087 /********************************************************************
3088 * handle enumeration of printers at level 1
3089 ********************************************************************/
3090 static WERROR enumprinters_level1( uint32 flags, fstring name,
3091 NEW_BUFFER *buffer, uint32 offered,
3092 uint32 *needed, uint32 *returned)
3094 /* Not all the flags are equals */
3096 if (flags & PRINTER_ENUM_LOCAL)
3097 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3099 if (flags & PRINTER_ENUM_NAME)
3100 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3102 if (flags & PRINTER_ENUM_REMOTE)
3103 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3105 if (flags & PRINTER_ENUM_NETWORK)
3106 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3108 return WERR_OK; /* NT4sp5 does that */
3111 /********************************************************************
3112 * handle enumeration of printers at level 2
3113 ********************************************************************/
3114 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3115 NEW_BUFFER *buffer, uint32 offered,
3116 uint32 *needed, uint32 *returned)
3118 char *s = servername;
3120 if (flags & PRINTER_ENUM_LOCAL) {
3121 return enum_all_printers_info_2(buffer, offered, needed, returned);
3124 if (flags & PRINTER_ENUM_NAME) {
3125 if ((servername[0] == '\\') && (servername[1] == '\\'))
3127 if (is_myname_or_ipaddr(s))
3128 return enum_all_printers_info_2(buffer, offered, needed, returned);
3130 return WERR_INVALID_NAME;
3133 if (flags & PRINTER_ENUM_REMOTE)
3134 return WERR_UNKNOWN_LEVEL;
3139 /********************************************************************
3140 * handle enumeration of printers at level 5
3141 ********************************************************************/
3142 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3143 NEW_BUFFER *buffer, uint32 offered,
3144 uint32 *needed, uint32 *returned)
3146 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3150 /********************************************************************
3151 * api_spoolss_enumprinters
3153 * called from api_spoolss_enumprinters (see this to understand)
3154 ********************************************************************/
3156 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3158 uint32 flags = q_u->flags;
3159 UNISTR2 *servername = &q_u->servername;
3160 uint32 level = q_u->level;
3161 NEW_BUFFER *buffer = NULL;
3162 uint32 offered = q_u->offered;
3163 uint32 *needed = &r_u->needed;
3164 uint32 *returned = &r_u->returned;
3168 /* that's an [in out] buffer */
3169 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3170 buffer = r_u->buffer;
3172 DEBUG(4,("_spoolss_enumprinters\n"));
3179 * flags==PRINTER_ENUM_NAME
3180 * if name=="" then enumerates all printers
3181 * if name!="" then enumerate the printer
3182 * flags==PRINTER_ENUM_REMOTE
3183 * name is NULL, enumerate printers
3184 * Level 2: name!="" enumerates printers, name can't be NULL
3185 * Level 3: doesn't exist
3186 * Level 4: does a local registry lookup
3187 * Level 5: same as Level 2
3190 unistr2_to_ascii(name, servername, sizeof(name)-1);
3195 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3197 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3199 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3204 return WERR_UNKNOWN_LEVEL;
3207 /****************************************************************************
3208 ****************************************************************************/
3209 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3211 PRINTER_INFO_0 *printer=NULL;
3213 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3216 construct_printer_info_0(printer, snum);
3218 /* check the required size. */
3219 *needed += spoolss_size_printer_info_0(printer);
3221 if (!alloc_buffer_size(buffer, *needed)) {
3223 return WERR_INSUFFICIENT_BUFFER;
3226 /* fill the buffer with the structures */
3227 smb_io_printer_info_0("", buffer, printer, 0);
3232 if (*needed > offered) {
3233 return WERR_INSUFFICIENT_BUFFER;
3239 /****************************************************************************
3240 ****************************************************************************/
3241 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3243 PRINTER_INFO_1 *printer=NULL;
3245 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3248 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3250 /* check the required size. */
3251 *needed += spoolss_size_printer_info_1(printer);
3253 if (!alloc_buffer_size(buffer, *needed)) {
3255 return WERR_INSUFFICIENT_BUFFER;
3258 /* fill the buffer with the structures */
3259 smb_io_printer_info_1("", buffer, printer, 0);
3264 if (*needed > offered) {
3265 return WERR_INSUFFICIENT_BUFFER;
3271 /****************************************************************************
3272 ****************************************************************************/
3273 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3275 PRINTER_INFO_2 *printer=NULL;
3277 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3280 construct_printer_info_2(printer, snum);
3282 /* check the required size. */
3283 *needed += spoolss_size_printer_info_2(printer);
3285 if (!alloc_buffer_size(buffer, *needed)) {
3286 free_printer_info_2(printer);
3287 return WERR_INSUFFICIENT_BUFFER;
3290 /* fill the buffer with the structures */
3291 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3292 free_printer_info_2(printer);
3297 free_printer_info_2(printer);
3299 if (*needed > offered) {
3300 return WERR_INSUFFICIENT_BUFFER;
3306 /****************************************************************************
3307 ****************************************************************************/
3308 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3310 PRINTER_INFO_3 *printer=NULL;
3312 if (!construct_printer_info_3(&printer, snum))
3315 /* check the required size. */
3316 *needed += spoolss_size_printer_info_3(printer);
3318 if (!alloc_buffer_size(buffer, *needed)) {
3319 free_printer_info_3(printer);
3320 return WERR_INSUFFICIENT_BUFFER;
3323 /* fill the buffer with the structures */
3324 smb_io_printer_info_3("", buffer, printer, 0);
3327 free_printer_info_3(printer);
3329 if (*needed > offered) {
3330 return WERR_INSUFFICIENT_BUFFER;
3336 /****************************************************************************
3337 ****************************************************************************/
3339 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3341 POLICY_HND *handle = &q_u->handle;
3342 uint32 level = q_u->level;
3343 NEW_BUFFER *buffer = NULL;
3344 uint32 offered = q_u->offered;
3345 uint32 *needed = &r_u->needed;
3349 /* that's an [in out] buffer */
3350 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3351 buffer = r_u->buffer;
3355 if (!get_printer_snum(p, handle, &snum))
3360 return getprinter_level_0(snum, buffer, offered, needed);
3362 return getprinter_level_1(snum, buffer, offered, needed);
3364 return getprinter_level_2(snum, buffer, offered, needed);
3366 return getprinter_level_3(snum, buffer, offered, needed);
3368 return WERR_UNKNOWN_LEVEL;
3371 /********************************************************************
3372 * fill a DRIVER_INFO_1 struct
3373 ********************************************************************/
3374 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3376 init_unistr( &info->name, driver.info_3->name);
3379 /********************************************************************
3380 * construct_printer_driver_info_1
3381 ********************************************************************/
3382 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3384 NT_PRINTER_INFO_LEVEL *printer = NULL;
3385 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3387 ZERO_STRUCT(driver);
3389 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3390 return WERR_INVALID_PRINTER_NAME;
3392 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3393 return WERR_UNKNOWN_PRINTER_DRIVER;
3395 fill_printer_driver_info_1(info, driver, servername, architecture);
3397 free_a_printer(&printer,2);
3402 /********************************************************************
3403 * construct_printer_driver_info_2
3404 * fill a printer_info_2 struct
3405 ********************************************************************/
3406 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3410 info->version=driver.info_3->cversion;
3412 init_unistr( &info->name, driver.info_3->name );
3413 init_unistr( &info->architecture, driver.info_3->environment );
3416 if (strlen(driver.info_3->driverpath)) {
3417 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3418 init_unistr( &info->driverpath, temp );
3420 init_unistr( &info->driverpath, "" );
3422 if (strlen(driver.info_3->datafile)) {
3423 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3424 init_unistr( &info->datafile, temp );
3426 init_unistr( &info->datafile, "" );
3428 if (strlen(driver.info_3->configfile)) {
3429 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3430 init_unistr( &info->configfile, temp );
3432 init_unistr( &info->configfile, "" );
3435 /********************************************************************
3436 * construct_printer_driver_info_2
3437 * fill a printer_info_2 struct
3438 ********************************************************************/
3439 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3441 NT_PRINTER_INFO_LEVEL *printer = NULL;
3442 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3444 ZERO_STRUCT(printer);
3445 ZERO_STRUCT(driver);
3447 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3448 return WERR_INVALID_PRINTER_NAME;
3450 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3451 return WERR_UNKNOWN_PRINTER_DRIVER;
3453 fill_printer_driver_info_2(info, driver, servername);
3455 free_a_printer(&printer,2);
3460 /********************************************************************
3461 * copy a strings array and convert to UNICODE
3463 * convert an array of ascii string to a UNICODE string
3464 ********************************************************************/
3465 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3473 DEBUG(6,("init_unistr_array\n"));
3477 if (char_array == NULL)
3481 if (!v) v = ""; /* hack to handle null lists */
3483 if (strlen(v) == 0) break;
3484 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3485 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3486 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3487 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3490 else *uni_array = tuary;
3491 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3496 (*uni_array)[j]=0x0000;
3499 DEBUGADD(6,("last one:done\n"));
3502 /********************************************************************
3503 * construct_printer_info_3
3504 * fill a printer_info_3 struct
3505 ********************************************************************/
3506 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3512 info->version=driver.info_3->cversion;
3514 init_unistr( &info->name, driver.info_3->name );
3515 init_unistr( &info->architecture, driver.info_3->environment );
3517 if (strlen(driver.info_3->driverpath)) {
3518 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3519 init_unistr( &info->driverpath, temp );
3521 init_unistr( &info->driverpath, "" );
3523 if (strlen(driver.info_3->datafile)) {
3524 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3525 init_unistr( &info->datafile, temp );
3527 init_unistr( &info->datafile, "" );
3529 if (strlen(driver.info_3->configfile)) {
3530 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3531 init_unistr( &info->configfile, temp );
3533 init_unistr( &info->configfile, "" );
3535 if (strlen(driver.info_3->helpfile)) {
3536 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3537 init_unistr( &info->helpfile, temp );
3539 init_unistr( &info->helpfile, "" );
3541 init_unistr( &info->monitorname, driver.info_3->monitorname );
3542 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3544 info->dependentfiles=NULL;
3545 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3548 /********************************************************************
3549 * construct_printer_info_3
3550 * fill a printer_info_3 struct
3551 ********************************************************************/
3552 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *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(driver);
3559 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3560 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3561 if (!W_ERROR_IS_OK(status))
3562 return WERR_INVALID_PRINTER_NAME;
3564 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3565 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3566 if (!W_ERROR_IS_OK(status)) {
3567 free_a_printer(&printer,2);
3568 return WERR_UNKNOWN_PRINTER_DRIVER;
3571 fill_printer_driver_info_3(info, driver, servername);
3573 free_a_printer(&printer,2);
3578 /********************************************************************
3579 * construct_printer_info_6
3580 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3581 ********************************************************************/
3583 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3589 memset(&nullstr, '\0', sizeof(fstring));
3591 info->version=driver.info_3->cversion;
3593 init_unistr( &info->name, driver.info_3->name );
3594 init_unistr( &info->architecture, driver.info_3->environment );
3596 if (strlen(driver.info_3->driverpath)) {
3597 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3598 init_unistr( &info->driverpath, temp );
3600 init_unistr( &info->driverpath, "" );
3602 if (strlen(driver.info_3->datafile)) {
3603 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3604 init_unistr( &info->datafile, temp );
3606 init_unistr( &info->datafile, "" );
3608 if (strlen(driver.info_3->configfile)) {
3609 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3610 init_unistr( &info->configfile, temp );
3612 init_unistr( &info->configfile, "" );
3614 if (strlen(driver.info_3->helpfile)) {
3615 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3616 init_unistr( &info->helpfile, temp );
3618 init_unistr( &info->helpfile, "" );
3620 init_unistr( &info->monitorname, driver.info_3->monitorname );
3621 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3623 info->dependentfiles=NULL;
3624 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3626 info->previousdrivernames=NULL;
3627 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3629 info->driver_date.low=0;
3630 info->driver_date.high=0;
3633 info->driver_version_low=0;
3634 info->driver_version_high=0;
3636 init_unistr( &info->mfgname, "");
3637 init_unistr( &info->oem_url, "");
3638 init_unistr( &info->hardware_id, "");
3639 init_unistr( &info->provider, "");
3642 /********************************************************************
3643 * construct_printer_info_6
3644 * fill a printer_info_6 struct
3645 ********************************************************************/
3646 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3648 NT_PRINTER_INFO_LEVEL *printer = NULL;
3649 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3651 ZERO_STRUCT(driver);
3653 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3654 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3655 if (!W_ERROR_IS_OK(status))
3656 return WERR_INVALID_PRINTER_NAME;
3658 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3659 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));