2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000.
7 * Copyright (C) Jeremy Allison 2001.
8 * Copyright (C) Gerald Carter 2000-2001.
9 * Copyright (C) Tim Potter 2001.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 #ifndef MAX_OPEN_PRINTER_EXS
32 #define MAX_OPEN_PRINTER_EXS 50
35 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
36 #define PRINTER_HANDLE_IS_PRINTER 0
37 #define PRINTER_HANDLE_IS_PRINTSERVER 1
46 /* structure to store the printer handles */
47 /* and a reference to what it's pointing to */
48 /* and the notify info asked about */
49 /* that's the central struct */
50 typedef struct _Printer{
51 BOOL document_started;
53 int jobid; /* jobid in printing backend */
57 fstring printerservername;
66 SPOOL_NOTIFY_OPTION *option;
67 POLICY_HND client_hnd;
68 uint32 client_connected;
76 typedef struct _counter_printer_0 {
84 static ubi_dlList counter_list;
86 static struct cli_state cli;
87 static uint32 smb_connections=0;
89 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
91 /* translate between internal status numbers and NT status numbers */
92 static int nt_printj_status(int v)
98 return JOB_STATUS_PAUSED;
100 return JOB_STATUS_SPOOLING;
102 return JOB_STATUS_PRINTING;
104 return JOB_STATUS_ERROR;
106 return JOB_STATUS_DELETING;
108 return JOB_STATUS_OFFLINE;
110 return JOB_STATUS_PAPEROUT;
112 return JOB_STATUS_PRINTED;
114 return JOB_STATUS_DELETED;
116 return JOB_STATUS_BLOCKED;
117 case LPQ_USER_INTERVENTION:
118 return JOB_STATUS_USER_INTERVENTION;
123 static int nt_printq_status(int v)
127 return PRINTER_STATUS_PAUSED;
136 /****************************************************************************
137 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
138 ****************************************************************************/
140 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
145 SAFE_FREE((*pp)->ctr.type);
149 /***************************************************************************
150 Disconnect from the client
151 ****************************************************************************/
153 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
157 /* weird if the test succeds !!! */
158 if (smb_connections==0) {
159 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
163 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
164 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
166 /* if it's the last connection, deconnect the IPC$ share */
167 if (smb_connections==1) {
168 if(!spoolss_disconnect_from_client(&cli))
171 message_deregister(MSG_PRINTER_NOTIFY);
177 /****************************************************************************
178 Functions to free a printer entry datastruct.
179 ****************************************************************************/
181 static void free_printer_entry(void *ptr)
183 Printer_entry *Printer = (Printer_entry *)ptr;
185 if (Printer->notify.client_connected==True)
186 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
188 Printer->notify.flags=0;
189 Printer->notify.options=0;
190 Printer->notify.localmachine[0]='\0';
191 Printer->notify.printerlocal=0;
192 free_spool_notify_option(&Printer->notify.option);
193 Printer->notify.option=NULL;
194 Printer->notify.client_connected=False;
199 /****************************************************************************
200 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
201 ****************************************************************************/
203 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
205 SPOOL_NOTIFY_OPTION *new_sp = NULL;
210 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
217 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
219 if (!new_sp->ctr.type) {
228 /****************************************************************************
229 find printer index by handle
230 ****************************************************************************/
232 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
234 Printer_entry *find_printer = NULL;
236 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
237 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
244 /****************************************************************************
245 close printer index by handle
246 ****************************************************************************/
248 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
250 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
253 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
257 close_policy_hnd(p, hnd);
262 /****************************************************************************
263 delete a printer given a handle
264 ****************************************************************************/
265 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
267 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
270 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
274 if (del_a_printer(Printer->dev.handlename) != 0) {
275 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
279 /* Check calling user has permission to delete printer. Note that
280 since we set the snum parameter to -1 only administrators can
281 delete the printer. This stops people with the Full Control
282 permission from deleting the printer. */
284 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
285 DEBUG(3, ("printer delete denied by security descriptor\n"));
286 return WERR_ACCESS_DENIED;
289 if (*lp_deleteprinter_cmd()) {
291 char *cmd = lp_deleteprinter_cmd();
296 /* Printer->dev.handlename equals portname equals sharename */
297 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
298 Printer->dev.handlename);
300 DEBUG(10,("Running [%s]\n", command));
301 ret = smbrun(command, NULL);
303 return WERR_BADFID; /* What to return here? */
305 DEBUGADD(10,("returned [%d]\n", ret));
307 /* Send SIGHUP to process group... is there a better way? */
310 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
314 return WERR_ACCESS_DENIED;
320 /****************************************************************************
321 return the snum of a printer corresponding to an handle
322 ****************************************************************************/
323 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
325 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
328 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
332 switch (Printer->printer_type) {
333 case PRINTER_HANDLE_IS_PRINTER:
334 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
335 *number = print_queue_snum(Printer->dev.handlename);
336 return (*number != -1);
337 case PRINTER_HANDLE_IS_PRINTSERVER:
344 /****************************************************************************
345 set printer handle type.
346 ****************************************************************************/
347 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
349 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
352 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
356 DEBUG(4,("Setting printer access=%x\n", access_required));
357 Printer->access = access_required;
361 /****************************************************************************
362 Set printer handle type.
363 Check if it's \\server or \\server\printer
364 ****************************************************************************/
366 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
368 DEBUG(3,("Setting printer type=%s\n", handlename));
370 if ( strlen(handlename) < 3 ) {
371 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
375 /* it's a print server */
376 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
377 DEBUGADD(4,("Printer is a print server\n"));
378 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
382 DEBUGADD(4,("Printer is a printer\n"));
383 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
389 /****************************************************************************
390 Set printer handle name.
391 ****************************************************************************/
393 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
395 NT_PRINTER_INFO_LEVEL *printer = NULL;
397 int n_services=lp_numservices();
401 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
403 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
404 ZERO_STRUCT(Printer->dev.printerservername);
405 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
409 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
412 if (*handlename=='\\') {
413 aprinter=strchr_m(handlename+2, '\\');
420 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
423 * store the Samba share name in it
424 * in back we have the long printer name
425 * need to iterate all the snum and do a
426 * get_a_printer each time to find the printer
427 * faster to do it here than later.
430 for (snum=0;snum<n_services && found==False;snum++) {
433 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
436 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
438 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
441 printername=strchr_m(printer->info_2->printername+2, '\\');
444 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
445 printer->info_2->printername, aprinter ));
447 if ( strlen(printername) != strlen(aprinter) ) {
448 free_a_printer(&printer, 2);
452 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
453 free_a_printer(&printer, 2);
461 * if we haven't found a printer with the given handlename
462 * then it can be a share name as you can open both \\server\printer and
467 * we still check if the printer description file exists as NT won't be happy
468 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
472 DEBUGADD(5,("Printer not found, checking for share now\n"));
474 for (snum=0;snum<n_services && found==False;snum++) {
476 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
479 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
481 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
484 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
485 printer->info_2->printername, aprinter ));
487 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
488 free_a_printer(&printer, 2);
492 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
493 free_a_printer(&printer, 2);
502 DEBUGADD(4,("Printer not found\n"));
507 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
508 printer->info_2->printername, lp_servicename(snum),snum));
510 ZERO_STRUCT(Printer->dev.handlename);
511 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
513 free_a_printer(&printer, 2);
518 /****************************************************************************
519 find first available printer slot. creates a printer handle for you.
520 ****************************************************************************/
522 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
524 Printer_entry *new_printer;
526 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
528 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
531 ZERO_STRUCTP(new_printer);
533 new_printer->notify.option=NULL;
535 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
536 SAFE_FREE(new_printer);
540 if (!set_printer_hnd_printertype(new_printer, name)) {
541 close_printer_handle(p, hnd);
545 if (!set_printer_hnd_name(new_printer, name)) {
546 close_printer_handle(p, hnd);
550 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
555 /********************************************************************
556 Return True is the handle is a print server.
557 ********************************************************************/
559 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
561 Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
566 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
572 /****************************************************************************
573 allocate more memory for a BUFFER.
574 ****************************************************************************/
575 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
583 /* damn, I'm doing the reverse operation of prs_grow() :) */
584 if (buffer_size < prs_data_size(ps))
587 extra_space = buffer_size - prs_data_size(ps);
590 * save the offset and move to the end of the buffer
591 * prs_grow() checks the extra_space against the offset
593 old_offset=prs_offset(ps);
594 prs_set_offset(ps, prs_data_size(ps));
596 if (!prs_grow(ps, extra_space))
599 prs_set_offset(ps, old_offset);
601 buffer->string_at_end=prs_data_size(ps);
606 /***************************************************************************
607 receive the notify message
608 ****************************************************************************/
610 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
614 struct pipes_struct *p;
616 struct handle_list *hl;
619 fstrcpy(printer,buf);
622 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
626 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
629 * We need to enumerate all printers. The handle list is shared
630 * across pipes of the same name, so just find the first open
635 for ( p = get_first_internal_pipe(); p; get_next_internal_pipe(p)) {
636 if (strequal(p->name, "spoolss")) {
637 hl = p->pipe_handles;
643 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
647 /* Iterate the printer list on this pipe. */
648 for (pol = hl->Policy; pol; pol = pol->next ) {
649 Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
655 * if the entry is the given printer or if it's a printerserver
656 * we send the message
659 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
660 if (strcmp(find_printer->dev.handlename, printer))
663 if (find_printer->notify.client_connected==True)
664 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
668 /***************************************************************************
670 ****************************************************************************/
671 static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle)
675 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
678 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
682 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
683 fstrcpy(printer, Printer->dev.handlename);
685 fstrcpy(printer, "");
687 /*srv_spoolss_receive_message(printer);*/
688 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
690 broadcast_printer_notify(printer);
695 /********************************************************************
696 * spoolss_open_printer
698 * called from the spoolss dispatcher
699 ********************************************************************/
701 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
704 WERROR result = WERR_OK;
707 UNISTR2 *printername = NULL;
708 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
709 /* uint32 user_switch = q_u->user_switch; - notused */
710 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
711 POLICY_HND *handle = &r_u->handle;
715 struct current_user user;
717 if (q_u->printername_ptr != 0)
718 printername = &q_u->printername;
720 if (printername == NULL)
721 return WERR_INVALID_PRINTER_NAME;
723 /* some sanity check because you can open a printer or a print server */
724 /* aka: \\server\printer or \\server */
725 unistr2_to_ascii(name, printername, sizeof(name)-1);
727 DEBUGADD(3,("checking name: %s\n",name));
729 if (!open_printer_hnd(p, handle, name))
730 return WERR_INVALID_PRINTER_NAME;
733 if (printer_default->datatype_ptr != NULL)
735 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
736 set_printer_hnd_datatype(handle, datatype);
739 set_printer_hnd_datatype(handle, "");
742 if (!set_printer_hnd_accesstype(p, handle, printer_default->access_required)) {
743 close_printer_handle(p, handle);
744 return WERR_ACCESS_DENIED;
748 First case: the user is opening the print server:
750 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
751 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
753 Then both Win2k and WinNT clients try an OpenPrinterEx with
754 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
755 or if the user is listed in the smb.conf printer admin parameter.
757 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
758 client view printer folder, but does not show the MSAPW.
760 Note: this test needs code to check access rights here too. Jeremy
761 could you look at this?
764 Second case: the user is opening a printer:
765 NT doesn't let us connect to a printer if the connecting user
766 doesn't have print permission.
770 get_current_user(&user, p);
772 if (handle_is_printserver(p, handle)) {
773 if (printer_default->access_required == 0) {
776 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
778 /* Printserver handles use global struct... */
781 if (!lp_ms_add_printer_wizard()) {
782 close_printer_handle(p, handle);
783 return WERR_ACCESS_DENIED;
785 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
789 close_printer_handle(p, handle);
790 return WERR_ACCESS_DENIED;
796 /* NT doesn't let us connect to a printer if the connecting user
797 doesn't have print permission. */
799 if (!get_printer_snum(p, handle, &snum))
802 /* map an empty access mask to the minimum access mask */
803 if (printer_default->access_required == 0x0)
804 printer_default->access_required = PRINTER_ACCESS_USE;
808 * If we are not serving the printer driver for this printer,
809 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
810 * will keep NT clients happy --jerry
813 if (lp_use_client_driver(snum)
814 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
816 printer_default->access_required = PRINTER_ACCESS_USE;
819 if (!print_access_check(&user, snum, printer_default->access_required)) {
820 DEBUG(3, ("access DENIED for printer open\n"));
821 close_printer_handle(p, handle);
822 return WERR_ACCESS_DENIED;
826 * If we have a default device pointer in the
827 * printer_default struct, then we need to get
828 * the printer info from the tdb and if there is
829 * no default devicemode there then we do a *SET*
830 * here ! This is insanity.... JRA.
834 * If the openprinterex rpc call contains a devmode,
835 * it's a per-user one. This per-user devmode is derivated
836 * from the global devmode. Openprinterex() contains a per-user
837 * devmode for when you do EMF printing and spooling.
838 * In the EMF case, the NT workstation is only doing half the job
839 * of rendering the page. The other half is done by running the printer
840 * driver on the server.
841 * The EMF file doesn't contain the page description (paper size, orientation, ...).
842 * The EMF file only contains what is to be printed on the page.
843 * So in order for the server to know how to print, the NT client sends
844 * a devicemode attached to the openprinterex call.
845 * But this devicemode is short lived, it's only valid for the current print job.
847 * If Samba would have supported EMF spooling, this devicemode would
848 * have been attached to the handle, to sent it to the driver to correctly
849 * rasterize the EMF file.
851 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
852 * we just act as a pass-thru between windows and the printer.
854 * In order to know that Samba supports only RAW spooling, NT has to call
855 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
856 * and until NT sends a RAW job, we refuse it.
858 * But to call getprinter() or startdoc(), you first need a valid handle,
859 * and to get an handle you have to call openprintex(). Hence why you have
860 * a devicemode in the openprinterex() call.
863 * Differences between NT4 and NT 2000.
866 * On NT4, you only have a global devicemode. This global devicemode can be changed
867 * by the administrator (or by a user with enough privs). Everytime a user
868 * wants to print, the devicemode is resetted to the default. In Word, everytime
869 * you print, the printer's characteristics are always reset to the global devicemode.
873 * In W2K, there is the notion of per-user devicemode. The first time you use
874 * a printer, a per-user devicemode is build from the global devicemode.
875 * If you change your per-user devicemode, it is saved in the registry, under the
876 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
877 * printer preferences available.
879 * To change the per-user devicemode: it's the "Printing Preferences ..." button
880 * on the General Tab of the printer properties windows.
882 * To change the global devicemode: it's the "Printing Defaults..." button
883 * on the Advanced Tab of the printer properties window.
891 if (printer_default->devmode_cont.devmode != NULL) {
892 result = printer_write_default_dev( snum, printer_default);
894 close_printer_handle(p, handle);
904 /****************************************************************************
905 ****************************************************************************/
906 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
907 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
913 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
922 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
923 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
929 printer->info_3=NULL;
930 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
934 printer->info_6=NULL;
935 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
945 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
946 NT_DEVICEMODE **pp_nt_devmode)
948 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
951 * Ensure nt_devmode is a valid pointer
952 * as we will be overwriting it.
955 if (nt_devmode == NULL) {
956 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
957 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
961 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
962 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
964 nt_devmode->specversion=devmode->specversion;
965 nt_devmode->driverversion=devmode->driverversion;
966 nt_devmode->size=devmode->size;
967 nt_devmode->fields=devmode->fields;
968 nt_devmode->orientation=devmode->orientation;
969 nt_devmode->papersize=devmode->papersize;
970 nt_devmode->paperlength=devmode->paperlength;
971 nt_devmode->paperwidth=devmode->paperwidth;
972 nt_devmode->scale=devmode->scale;
973 nt_devmode->copies=devmode->copies;
974 nt_devmode->defaultsource=devmode->defaultsource;
975 nt_devmode->printquality=devmode->printquality;
976 nt_devmode->color=devmode->color;
977 nt_devmode->duplex=devmode->duplex;
978 nt_devmode->yresolution=devmode->yresolution;
979 nt_devmode->ttoption=devmode->ttoption;
980 nt_devmode->collate=devmode->collate;
982 nt_devmode->logpixels=devmode->logpixels;
983 nt_devmode->bitsperpel=devmode->bitsperpel;
984 nt_devmode->pelswidth=devmode->pelswidth;
985 nt_devmode->pelsheight=devmode->pelsheight;
986 nt_devmode->displayflags=devmode->displayflags;
987 nt_devmode->displayfrequency=devmode->displayfrequency;
988 nt_devmode->icmmethod=devmode->icmmethod;
989 nt_devmode->icmintent=devmode->icmintent;
990 nt_devmode->mediatype=devmode->mediatype;
991 nt_devmode->dithertype=devmode->dithertype;
992 nt_devmode->reserved1=devmode->reserved1;
993 nt_devmode->reserved2=devmode->reserved2;
994 nt_devmode->panningwidth=devmode->panningwidth;
995 nt_devmode->panningheight=devmode->panningheight;
998 * Only change private and driverextra if the incoming devmode
999 * has a new one. JRA.
1002 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1003 SAFE_FREE(nt_devmode->private);
1004 nt_devmode->driverextra=devmode->driverextra;
1005 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1007 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1010 *pp_nt_devmode = nt_devmode;
1015 /********************************************************************
1016 * _spoolss_enddocprinter_internal.
1017 ********************************************************************/
1019 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1021 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1024 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1028 Printer->document_started=False;
1029 print_job_end(Printer->jobid,True);
1030 /* error codes unhandled so far ... */
1035 /********************************************************************
1036 * api_spoolss_closeprinter
1037 ********************************************************************/
1039 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1041 POLICY_HND *handle = &q_u->handle;
1043 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1045 if (Printer && Printer->document_started)
1046 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1048 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1050 if (!close_printer_handle(p, handle))
1056 /********************************************************************
1057 * api_spoolss_deleteprinter
1059 ********************************************************************/
1061 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1063 POLICY_HND *handle = &q_u->handle;
1064 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1067 if (Printer && Printer->document_started)
1068 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1070 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1072 result = delete_printer_handle(p, handle);
1074 if (W_ERROR_IS_OK(result)) {
1075 srv_spoolss_sendnotify(p, handle);
1081 /*******************************************************************
1082 * static function to lookup the version id corresponding to an
1083 * long architecture string
1084 ******************************************************************/
1085 static int get_version_id (char * arch)
1088 struct table_node archi_table[]= {
1090 {"Windows 4.0", "WIN40", 0 },
1091 {"Windows NT x86", "W32X86", 2 },
1092 {"Windows NT R4000", "W32MIPS", 2 },
1093 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1094 {"Windows NT PowerPC", "W32PPC", 2 },
1098 for (i=0; archi_table[i].long_archi != NULL; i++)
1100 if (strcmp(arch, archi_table[i].long_archi) == 0)
1101 return (archi_table[i].version);
1107 /********************************************************************
1108 * _spoolss_deleteprinterdriver
1110 * We currently delete the driver for the architecture only.
1111 * This can leave the driver for other archtectures. However,
1112 * since every printer associates a "Windows NT x86" driver name
1113 * and we cannot delete that one while it is in use, **and** since
1114 * it is impossible to assign a driver to a Samba printer without
1115 * having the "Windows NT x86" driver installed,...
1117 * ....we should not get into trouble here.
1120 ********************************************************************/
1122 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
1123 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1127 NT_PRINTER_DRIVER_INFO_LEVEL info;
1130 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1131 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1133 /* check that we have a valid driver name first */
1134 if ((version=get_version_id(arch)) == -1) {
1135 /* this is what NT returns */
1136 return WERR_INVALID_ENVIRONMENT;
1140 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1141 return WERR_UNKNOWN_PRINTER_DRIVER;
1145 if (printer_driver_in_use(arch, driver))
1147 return WERR_PRINTER_DRIVER_IN_USE;
1150 return delete_printer_driver(info.info_3);
1154 /********************************************************************
1155 GetPrinterData on a printer server Handle.
1156 ********************************************************************/
1157 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1161 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1163 if (!strcmp(value, "BeepEnabled")) {
1165 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1167 SIVAL(*data, 0, 0x01);
1172 if (!strcmp(value, "EventLog")) {
1174 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1176 SIVAL(*data, 0, 0x1B);
1181 if (!strcmp(value, "NetPopup")) {
1183 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1185 SIVAL(*data, 0, 0x01);
1190 if (!strcmp(value, "MajorVersion")) {
1192 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1194 SIVAL(*data, 0, 0x02);
1199 if (!strcmp(value, "DefaultSpoolDirectory")) {
1200 pstring string="You are using a Samba server";
1202 *needed = 2*(strlen(string)+1);
1203 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1205 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1207 /* it's done by hand ready to go on the wire */
1208 for (i=0; i<strlen(string); i++) {
1209 (*data)[2*i]=string[i];
1210 (*data)[2*i+1]='\0';
1215 if (!strcmp(value, "Architecture")) {
1216 pstring string="Windows NT x86";
1218 *needed = 2*(strlen(string)+1);
1219 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1221 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1222 for (i=0; i<strlen(string); i++) {
1223 (*data)[2*i]=string[i];
1224 (*data)[2*i+1]='\0';
1232 /********************************************************************
1233 GetPrinterData on a printer Handle.
1234 ********************************************************************/
1235 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1236 fstring value, uint32 *type,
1237 uint8 **data, uint32 *needed, uint32 in_size )
1239 NT_PRINTER_INFO_LEVEL *printer = NULL;
1243 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1245 DEBUG(5,("getprinterdata_printer\n"));
1248 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1252 if(!get_printer_snum(p, handle, &snum))
1255 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1258 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1259 free_a_printer(&printer, 2);
1263 free_a_printer(&printer, 2);
1265 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1268 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1272 memset(*data, 0, in_size *sizeof(uint8));
1273 /* copy the min(in_size, len) */
1274 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1281 DEBUG(5,("getprinterdata_printer:copy done\n"));
1288 /********************************************************************
1289 * spoolss_getprinterdata
1290 ********************************************************************/
1292 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1294 POLICY_HND *handle = &q_u->handle;
1295 UNISTR2 *valuename = &q_u->valuename;
1296 uint32 in_size = q_u->size;
1297 uint32 *type = &r_u->type;
1298 uint32 *out_size = &r_u->size;
1299 uint8 **data = &r_u->data;
1300 uint32 *needed = &r_u->needed;
1304 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1307 * Reminder: when it's a string, the length is in BYTES
1308 * even if UNICODE is negociated.
1315 /* in case of problem, return some default values */
1319 DEBUG(4,("_spoolss_getprinterdata\n"));
1322 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1324 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1328 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1330 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1331 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1333 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1336 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1337 /* reply this param doesn't exist */
1339 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1345 return WERR_INVALID_PARAM;
1348 if (*needed > *out_size)
1349 return WERR_STATUS_MORE_ENTRIES;
1354 /***************************************************************************
1355 connect to the client
1356 ****************************************************************************/
1357 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1362 * If it's the first connection, contact the client
1363 * and connect to the IPC$ share anonumously
1365 if (smb_connections==0) {
1366 fstring unix_printer;
1368 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1370 if(!spoolss_connect_to_client(&cli, unix_printer))
1372 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1378 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1384 /********************************************************************
1386 * ReplyFindFirstPrinterChangeNotifyEx
1388 * jfmxxxx: before replying OK: status=0
1389 * should do a rpc call to the workstation asking ReplyOpenPrinter
1390 * have to code it, later.
1392 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1393 * called from api_spoolss_rffpcnex
1394 ********************************************************************/
1396 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1398 POLICY_HND *handle = &q_u->handle;
1399 uint32 flags = q_u->flags;
1400 uint32 options = q_u->options;
1401 UNISTR2 *localmachine = &q_u->localmachine;
1402 uint32 printerlocal = q_u->printerlocal;
1403 SPOOL_NOTIFY_OPTION *option = q_u->option;
1405 /* store the notify value in the printer struct */
1407 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1410 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1414 Printer->notify.flags=flags;
1415 Printer->notify.options=options;
1416 Printer->notify.printerlocal=printerlocal;
1418 if (Printer->notify.option)
1419 free_spool_notify_option(&Printer->notify.option);
1421 Printer->notify.option=dup_spool_notify_option(option);
1423 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1425 /* connect to the client machine and send a ReplyOpenPrinter */
1426 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1427 Printer->notify.printerlocal, 1,
1428 &Printer->notify.client_hnd))
1429 Printer->notify.client_connected=True;
1434 /*******************************************************************
1435 * fill a notify_info_data with the servername
1436 ********************************************************************/
1438 static void spoolss_notify_server_name(int snum,
1439 SPOOL_NOTIFY_INFO_DATA *data,
1440 print_queue_struct *queue,
1441 NT_PRINTER_INFO_LEVEL *printer,
1442 TALLOC_CTX *mem_ctx)
1444 pstring temp_name, temp;
1447 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
1449 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
1451 data->notify_data.data.length = len / 2;
1452 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1454 if (!data->notify_data.data.string) {
1455 data->notify_data.data.length = 0;
1459 memcpy(data->notify_data.data.string, temp, len);
1462 /*******************************************************************
1463 * fill a notify_info_data with the printername (not including the servername).
1464 ********************************************************************/
1465 static void spoolss_notify_printer_name(int snum,
1466 SPOOL_NOTIFY_INFO_DATA *data,
1467 print_queue_struct *queue,
1468 NT_PRINTER_INFO_LEVEL *printer,
1469 TALLOC_CTX *mem_ctx)
1474 /* the notify name should not contain the \\server\ part */
1475 char *p = strrchr_m(printer->info_2->printername, '\\');
1478 p = printer->info_2->printername;
1483 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
1484 data->notify_data.data.length = len / 2;
1485 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1487 if (!data->notify_data.data.string) {
1488 data->notify_data.data.length = 0;
1492 memcpy(data->notify_data.data.string, temp, len);
1495 /*******************************************************************
1496 * fill a notify_info_data with the servicename
1497 ********************************************************************/
1498 static void spoolss_notify_share_name(int snum,
1499 SPOOL_NOTIFY_INFO_DATA *data,
1500 print_queue_struct *queue,
1501 NT_PRINTER_INFO_LEVEL *printer,
1502 TALLOC_CTX *mem_ctx)
1507 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
1509 data->notify_data.data.length = len / 2;
1510 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1512 if (!data->notify_data.data.string) {
1513 data->notify_data.data.length = 0;
1517 memcpy(data->notify_data.data.string, temp, len);
1520 /*******************************************************************
1521 * fill a notify_info_data with the port name
1522 ********************************************************************/
1523 static void spoolss_notify_port_name(int snum,
1524 SPOOL_NOTIFY_INFO_DATA *data,
1525 print_queue_struct *queue,
1526 NT_PRINTER_INFO_LEVEL *printer,
1527 TALLOC_CTX *mem_ctx)
1532 /* even if it's strange, that's consistant in all the code */
1534 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
1536 data->notify_data.data.length = len / 2;
1537 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1539 if (!data->notify_data.data.string) {
1540 data->notify_data.data.length = 0;
1544 memcpy(data->notify_data.data.string, temp, len);
1547 /*******************************************************************
1548 * fill a notify_info_data with the printername
1549 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1550 * but it doesn't exist, have to see what to do
1551 ********************************************************************/
1552 static void spoolss_notify_driver_name(int snum,
1553 SPOOL_NOTIFY_INFO_DATA *data,
1554 print_queue_struct *queue,
1555 NT_PRINTER_INFO_LEVEL *printer,
1556 TALLOC_CTX *mem_ctx)
1561 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
1562 data->notify_data.data.length = len / 2;
1563 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1565 if (!data->notify_data.data.string) {
1566 data->notify_data.data.length = 0;
1570 memcpy(data->notify_data.data.string, temp, len);
1573 /*******************************************************************
1574 * fill a notify_info_data with the comment
1575 ********************************************************************/
1576 static void spoolss_notify_comment(int snum,
1577 SPOOL_NOTIFY_INFO_DATA *data,
1578 print_queue_struct *queue,
1579 NT_PRINTER_INFO_LEVEL *printer,
1580 TALLOC_CTX *mem_ctx)
1585 if (*printer->info_2->comment == '\0')
1586 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
1589 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
1591 data->notify_data.data.length = len / 2;
1592 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1594 if (!data->notify_data.data.string) {
1595 data->notify_data.data.length = 0;
1599 memcpy(data->notify_data.data.string, temp, len);
1602 /*******************************************************************
1603 * fill a notify_info_data with the comment
1604 * jfm:xxxx incorrect, have to create a new smb.conf option
1605 * location = "Room 1, floor 2, building 3"
1606 ********************************************************************/
1607 static void spoolss_notify_location(int snum,
1608 SPOOL_NOTIFY_INFO_DATA *data,
1609 print_queue_struct *queue,
1610 NT_PRINTER_INFO_LEVEL *printer,
1611 TALLOC_CTX *mem_ctx)
1616 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
1618 data->notify_data.data.length = len / 2;
1619 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1621 if (!data->notify_data.data.string) {
1622 data->notify_data.data.length = 0;
1626 memcpy(data->notify_data.data.string, temp, len);
1629 /*******************************************************************
1630 * fill a notify_info_data with the device mode
1631 * jfm:xxxx don't to it for know but that's a real problem !!!
1632 ********************************************************************/
1633 static void spoolss_notify_devmode(int snum,
1634 SPOOL_NOTIFY_INFO_DATA *data,
1635 print_queue_struct *queue,
1636 NT_PRINTER_INFO_LEVEL *printer,
1637 TALLOC_CTX *mem_ctx)
1641 /*******************************************************************
1642 * fill a notify_info_data with the separator file name
1643 * jfm:xxxx just return no file could add an option to smb.conf
1644 * separator file = "separator.txt"
1645 ********************************************************************/
1646 static void spoolss_notify_sepfile(int snum,
1647 SPOOL_NOTIFY_INFO_DATA *data,
1648 print_queue_struct *queue,
1649 NT_PRINTER_INFO_LEVEL *printer,
1650 TALLOC_CTX *mem_ctx)
1655 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
1657 data->notify_data.data.length = len / 2;
1658 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1660 if (!data->notify_data.data.string) {
1661 data->notify_data.data.length = 0;
1665 memcpy(data->notify_data.data.string, temp, len);
1668 /*******************************************************************
1669 * fill a notify_info_data with the print processor
1670 * jfm:xxxx return always winprint to indicate we don't do anything to it
1671 ********************************************************************/
1672 static void spoolss_notify_print_processor(int snum,
1673 SPOOL_NOTIFY_INFO_DATA *data,
1674 print_queue_struct *queue,
1675 NT_PRINTER_INFO_LEVEL *printer,
1676 TALLOC_CTX *mem_ctx)
1681 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
1683 data->notify_data.data.length = len / 2;
1684 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1686 if (!data->notify_data.data.string) {
1687 data->notify_data.data.length = 0;
1691 memcpy(data->notify_data.data.string, temp, len);
1694 /*******************************************************************
1695 * fill a notify_info_data with the print processor options
1696 * jfm:xxxx send an empty string
1697 ********************************************************************/
1698 static void spoolss_notify_parameters(int snum,
1699 SPOOL_NOTIFY_INFO_DATA *data,
1700 print_queue_struct *queue,
1701 NT_PRINTER_INFO_LEVEL *printer,
1702 TALLOC_CTX *mem_ctx)
1707 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
1709 data->notify_data.data.length = len / 2;
1710 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1712 if (!data->notify_data.data.string) {
1713 data->notify_data.data.length = 0;
1717 memcpy(data->notify_data.data.string, temp, len);
1720 /*******************************************************************
1721 * fill a notify_info_data with the data type
1722 * jfm:xxxx always send RAW as data type
1723 ********************************************************************/
1724 static void spoolss_notify_datatype(int snum,
1725 SPOOL_NOTIFY_INFO_DATA *data,
1726 print_queue_struct *queue,
1727 NT_PRINTER_INFO_LEVEL *printer,
1728 TALLOC_CTX *mem_ctx)
1733 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
1735 data->notify_data.data.length = len / 2;
1736 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1738 if (!data->notify_data.data.string) {
1739 data->notify_data.data.length = 0;
1743 memcpy(data->notify_data.data.string, temp, len);
1746 /*******************************************************************
1747 * fill a notify_info_data with the security descriptor
1748 * jfm:xxxx send an null pointer to say no security desc
1749 * have to implement security before !
1750 ********************************************************************/
1751 static void spoolss_notify_security_desc(int snum,
1752 SPOOL_NOTIFY_INFO_DATA *data,
1753 print_queue_struct *queue,
1754 NT_PRINTER_INFO_LEVEL *printer,
1755 TALLOC_CTX *mem_ctx)
1757 data->notify_data.data.length=0;
1758 data->notify_data.data.string = NULL;
1761 /*******************************************************************
1762 * fill a notify_info_data with the attributes
1763 * jfm:xxxx a samba printer is always shared
1764 ********************************************************************/
1765 static void spoolss_notify_attributes(int snum,
1766 SPOOL_NOTIFY_INFO_DATA *data,
1767 print_queue_struct *queue,
1768 NT_PRINTER_INFO_LEVEL *printer,
1769 TALLOC_CTX *mem_ctx)
1771 data->notify_data.value[0] = printer->info_2->attributes;
1772 data->notify_data.value[1] = 0;
1775 /*******************************************************************
1776 * fill a notify_info_data with the priority
1777 ********************************************************************/
1778 static void spoolss_notify_priority(int snum,
1779 SPOOL_NOTIFY_INFO_DATA *data,
1780 print_queue_struct *queue,
1781 NT_PRINTER_INFO_LEVEL *printer,
1782 TALLOC_CTX *mem_ctx)
1784 data->notify_data.value[0] = printer->info_2->priority;
1785 data->notify_data.value[1] = 0;
1788 /*******************************************************************
1789 * fill a notify_info_data with the default priority
1790 ********************************************************************/
1791 static void spoolss_notify_default_priority(int snum,
1792 SPOOL_NOTIFY_INFO_DATA *data,
1793 print_queue_struct *queue,
1794 NT_PRINTER_INFO_LEVEL *printer,
1795 TALLOC_CTX *mem_ctx)
1797 data->notify_data.value[0] = printer->info_2->default_priority;
1798 data->notify_data.value[1] = 0;
1801 /*******************************************************************
1802 * fill a notify_info_data with the start time
1803 ********************************************************************/
1804 static void spoolss_notify_start_time(int snum,
1805 SPOOL_NOTIFY_INFO_DATA *data,
1806 print_queue_struct *queue,
1807 NT_PRINTER_INFO_LEVEL *printer,
1808 TALLOC_CTX *mem_ctx)
1810 data->notify_data.value[0] = printer->info_2->starttime;
1811 data->notify_data.value[1] = 0;
1814 /*******************************************************************
1815 * fill a notify_info_data with the until time
1816 ********************************************************************/
1817 static void spoolss_notify_until_time(int snum,
1818 SPOOL_NOTIFY_INFO_DATA *data,
1819 print_queue_struct *queue,
1820 NT_PRINTER_INFO_LEVEL *printer,
1821 TALLOC_CTX *mem_ctx)
1823 data->notify_data.value[0] = printer->info_2->untiltime;
1824 data->notify_data.value[1] = 0;
1827 /*******************************************************************
1828 * fill a notify_info_data with the status
1829 ********************************************************************/
1830 static void spoolss_notify_status(int snum,
1831 SPOOL_NOTIFY_INFO_DATA *data,
1832 print_queue_struct *queue,
1833 NT_PRINTER_INFO_LEVEL *printer,
1834 TALLOC_CTX *mem_ctx)
1836 print_status_struct status;
1838 print_queue_length(snum, &status);
1839 data->notify_data.value[0]=(uint32) status.status;
1840 data->notify_data.value[1] = 0;
1843 /*******************************************************************
1844 * fill a notify_info_data with the number of jobs queued
1845 ********************************************************************/
1846 static void spoolss_notify_cjobs(int snum,
1847 SPOOL_NOTIFY_INFO_DATA *data,
1848 print_queue_struct *queue,
1849 NT_PRINTER_INFO_LEVEL *printer,
1850 TALLOC_CTX *mem_ctx)
1852 data->notify_data.value[0] = print_queue_length(snum, NULL);
1853 data->notify_data.value[1] = 0;
1856 /*******************************************************************
1857 * fill a notify_info_data with the average ppm
1858 ********************************************************************/
1859 static void spoolss_notify_average_ppm(int snum,
1860 SPOOL_NOTIFY_INFO_DATA *data,
1861 print_queue_struct *queue,
1862 NT_PRINTER_INFO_LEVEL *printer,
1863 TALLOC_CTX *mem_ctx)
1865 /* always respond 8 pages per minutes */
1866 /* a little hard ! */
1867 data->notify_data.value[0] = printer->info_2->averageppm;
1868 data->notify_data.value[1] = 0;
1871 /*******************************************************************
1872 * fill a notify_info_data with username
1873 ********************************************************************/
1874 static void spoolss_notify_username(int snum,
1875 SPOOL_NOTIFY_INFO_DATA *data,
1876 print_queue_struct *queue,
1877 NT_PRINTER_INFO_LEVEL *printer,
1878 TALLOC_CTX *mem_ctx)
1883 len = rpcstr_push(temp, queue->user, sizeof(temp)-2, STR_TERMINATE);
1886 data->notify_data.data.length = len / 2;
1887 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1889 if (!data->notify_data.data.string) {
1890 data->notify_data.data.length = 0;
1894 memcpy(data->notify_data.data.string, temp, len);
1897 /*******************************************************************
1898 * fill a notify_info_data with job status
1899 ********************************************************************/
1900 static void spoolss_notify_job_status(int snum,
1901 SPOOL_NOTIFY_INFO_DATA *data,
1902 print_queue_struct *queue,
1903 NT_PRINTER_INFO_LEVEL *printer,
1904 TALLOC_CTX *mem_ctx)
1906 data->notify_data.value[0]=nt_printj_status(queue->status);
1907 data->notify_data.value[1] = 0;
1910 /*******************************************************************
1911 * fill a notify_info_data with job name
1912 ********************************************************************/
1913 static void spoolss_notify_job_name(int snum,
1914 SPOOL_NOTIFY_INFO_DATA *data,
1915 print_queue_struct *queue,
1916 NT_PRINTER_INFO_LEVEL *printer,
1917 TALLOC_CTX *mem_ctx)
1922 len = rpcstr_push(temp, queue->file, sizeof(temp)-2, STR_TERMINATE);
1924 data->notify_data.data.length = len / 2;
1925 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1927 if (!data->notify_data.data.string) {
1928 data->notify_data.data.length = 0;
1932 memcpy(data->notify_data.data.string, temp, len);
1935 /*******************************************************************
1936 * fill a notify_info_data with job status
1937 ********************************************************************/
1938 static void spoolss_notify_job_status_string(int snum,
1939 SPOOL_NOTIFY_INFO_DATA *data,
1940 print_queue_struct *queue,
1941 NT_PRINTER_INFO_LEVEL *printer,
1942 TALLOC_CTX *mem_ctx)
1945 * Now we're returning job status codes we just return a "" here. JRA.
1952 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1955 switch (queue->status) {
1960 p = ""; /* NT provides the paused string */
1969 #endif /* NO LONGER NEEDED. */
1971 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
1973 data->notify_data.data.length = len / 2;
1974 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1976 if (!data->notify_data.data.string) {
1977 data->notify_data.data.length = 0;
1981 memcpy(data->notify_data.data.string, temp, len);
1984 /*******************************************************************
1985 * fill a notify_info_data with job time
1986 ********************************************************************/
1987 static void spoolss_notify_job_time(int snum,
1988 SPOOL_NOTIFY_INFO_DATA *data,
1989 print_queue_struct *queue,
1990 NT_PRINTER_INFO_LEVEL *printer,
1991 TALLOC_CTX *mem_ctx)
1993 data->notify_data.value[0]=0x0;
1994 data->notify_data.value[1]=0;
1997 /*******************************************************************
1998 * fill a notify_info_data with job size
1999 ********************************************************************/
2000 static void spoolss_notify_job_size(int snum,
2001 SPOOL_NOTIFY_INFO_DATA *data,
2002 print_queue_struct *queue,
2003 NT_PRINTER_INFO_LEVEL *printer,
2004 TALLOC_CTX *mem_ctx)
2006 data->notify_data.value[0]=queue->size;
2007 data->notify_data.value[1]=0;
2010 /*******************************************************************
2011 Fill a notify_info_data with job position.
2012 ********************************************************************/
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 ********************************************************************/
2028 static void spoolss_notify_submitted_time(int snum,
2029 SPOOL_NOTIFY_INFO_DATA *data,
2030 print_queue_struct *queue,
2031 NT_PRINTER_INFO_LEVEL *printer,
2032 TALLOC_CTX *mem_ctx)
2039 t=gmtime(&queue->time);
2041 len = sizeof(SYSTEMTIME);
2043 data->notify_data.data.length = len;
2044 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2046 if (!data->notify_data.data.string) {
2047 data->notify_data.data.length = 0;
2051 make_systemtime(&st, t);
2054 * Systemtime must be linearized as a set of UINT16's.
2055 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2058 p = (char *)data->notify_data.data.string;
2059 SSVAL(p, 0, st.year);
2060 SSVAL(p, 2, st.month);
2061 SSVAL(p, 4, st.dayofweek);
2062 SSVAL(p, 6, st.day);
2063 SSVAL(p, 8, st.hour);
2064 SSVAL(p, 10, st.minute);
2065 SSVAL(p, 12, st.second);
2066 SSVAL(p, 14, st.milliseconds);
2071 struct s_notify_info_data_table
2077 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2078 print_queue_struct *queue,
2079 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2082 struct s_notify_info_data_table notify_info_data_table[] =
2084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2090 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2091 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2092 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2093 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2094 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2095 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2096 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2097 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2098 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2099 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2100 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2101 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2102 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2103 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2104 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2105 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2106 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2107 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2108 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2109 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2110 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2111 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2112 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2113 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2114 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2115 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2116 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2117 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2118 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2119 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2120 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2121 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2122 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2123 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2124 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2125 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2126 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2127 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2128 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2129 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2130 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2131 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2132 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2133 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2134 { END, END, "", END, NULL }
2137 /*******************************************************************
2138 return the size of info_data structure
2139 ********************************************************************/
2140 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2144 while (notify_info_data_table[i].type != END)
2146 if ( (notify_info_data_table[i].type == type ) &&
2147 (notify_info_data_table[i].field == field ) )
2149 return (notify_info_data_table[i].size);
2156 /*******************************************************************
2157 return the type of notify_info_data
2158 ********************************************************************/
2159 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2163 while (notify_info_data_table[i].type != END)
2165 if ( (notify_info_data_table[i].type == type ) &&
2166 (notify_info_data_table[i].field == field ) )
2168 if (notify_info_data_table[i].size == POINTER)
2182 /****************************************************************************
2183 ****************************************************************************/
2184 static int search_notify(uint16 type, uint16 field, int *value)
2189 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2191 if ( (notify_info_data_table[j].type == type ) &&
2192 (notify_info_data_table[j].field == field ) )
2197 if ( found && (notify_info_data_table[j].fn != NULL) )
2203 /****************************************************************************
2204 ****************************************************************************/
2205 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2207 info_data->type = type;
2208 info_data->field = field;
2209 info_data->reserved = 0;
2211 info_data->size = size_of_notify_info_data(type, field);
2212 info_data->enc_type = type_of_notify_info_data(type, field);
2216 /*******************************************************************
2218 * fill a notify_info struct with info asked
2220 ********************************************************************/
2221 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2222 snum, SPOOL_NOTIFY_OPTION_TYPE
2223 *option_type, uint32 id,
2224 TALLOC_CTX *mem_ctx)
2230 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2231 NT_PRINTER_INFO_LEVEL *printer = NULL;
2232 print_queue_struct *queue=NULL;
2234 type=option_type->type;
2236 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2237 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2238 option_type->count, lp_servicename(snum)));
2240 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2243 for(field_num=0; field_num<option_type->count; field_num++) {
2244 field = option_type->fields[field_num];
2245 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2247 if (!search_notify(type, field, &j) )
2250 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2251 DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2254 else info->data = tid;
2256 current_data=&info->data[info->count];
2258 construct_info_data(current_data, type, field, id);
2260 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2261 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2263 notify_info_data_table[j].fn(snum, current_data, queue,
2269 free_a_printer(&printer, 2);
2273 /*******************************************************************
2275 * fill a notify_info struct with info asked
2277 ********************************************************************/
2278 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2279 SPOOL_NOTIFY_INFO *info,
2280 NT_PRINTER_INFO_LEVEL *printer,
2281 int snum, SPOOL_NOTIFY_OPTION_TYPE
2282 *option_type, uint32 id,
2283 TALLOC_CTX *mem_ctx)
2289 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2291 DEBUG(4,("construct_notify_jobs_info\n"));
2293 type = option_type->type;
2295 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2296 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2297 option_type->count));
2299 for(field_num=0; field_num<option_type->count; field_num++) {
2300 field = option_type->fields[field_num];
2302 if (!search_notify(type, field, &j) )
2305 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2306 DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2309 else info->data = tid;
2311 current_data=&(info->data[info->count]);
2313 construct_info_data(current_data, type, field, id);
2314 notify_info_data_table[j].fn(snum, current_data, queue,
2323 * JFM: The enumeration is not that simple, it's even non obvious.
2325 * let's take an example: I want to monitor the PRINTER SERVER for
2326 * the printer's name and the number of jobs currently queued.
2327 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2328 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2330 * I have 3 printers on the back of my server.
2332 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2335 * 1 printer 1 name 1
2336 * 2 printer 1 cjob 1
2337 * 3 printer 2 name 2
2338 * 4 printer 2 cjob 2
2339 * 5 printer 3 name 3
2340 * 6 printer 3 name 3
2342 * that's the print server case, the printer case is even worse.
2345 /*******************************************************************
2347 * enumerate all printers on the printserver
2348 * fill a notify_info struct with info asked
2350 ********************************************************************/
2352 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2353 SPOOL_NOTIFY_INFO *info,
2354 TALLOC_CTX *mem_ctx)
2357 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2358 int n_services=lp_numservices();
2361 SPOOL_NOTIFY_OPTION *option;
2362 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2364 DEBUG(4,("printserver_notify_info\n"));
2366 option=Printer->notify.option;
2372 for (i=0; i<option->count; i++) {
2373 option_type=&(option->ctr.type[i]);
2375 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2378 for (snum=0; snum<n_services; snum++)
2379 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2380 if (construct_notify_printer_info
2381 (info, snum, option_type, id, mem_ctx))
2386 * Debugging information, don't delete.
2389 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2390 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2391 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2393 for (i=0; i<info->count; i++) {
2394 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2395 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2396 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2403 /*******************************************************************
2405 * fill a notify_info struct with info asked
2407 ********************************************************************/
2408 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2409 TALLOC_CTX *mem_ctx)
2412 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2415 SPOOL_NOTIFY_OPTION *option;
2416 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2418 print_queue_struct *queue=NULL;
2419 print_status_struct status;
2421 DEBUG(4,("printer_notify_info\n"));
2423 option=Printer->notify.option;
2429 get_printer_snum(p, hnd, &snum);
2431 for (i=0; i<option->count; i++) {
2432 option_type=&option->ctr.type[i];
2434 switch ( option_type->type ) {
2435 case PRINTER_NOTIFY_TYPE:
2436 if(construct_notify_printer_info(info, snum,
2442 case JOB_NOTIFY_TYPE: {
2443 NT_PRINTER_INFO_LEVEL *printer = NULL;
2445 count = print_queue_status(snum, &queue, &status);
2447 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
2448 lp_servicename(snum))))
2451 for (j=0; j<count; j++) {
2452 construct_notify_jobs_info(&queue[j], info,
2459 free_a_printer(&printer, 2);
2469 * Debugging information, don't delete.
2472 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2473 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2474 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2476 for (i=0; i<info->count; i++) {
2477 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2478 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2479 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2485 /********************************************************************
2487 ********************************************************************/
2489 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2491 POLICY_HND *handle = &q_u->handle;
2492 /* uint32 change = q_u->change; - notused. */
2493 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2494 SPOOL_NOTIFY_INFO *info = &r_u->info;
2496 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2497 WERROR result = WERR_BADFID;
2499 /* we always have a NOTIFY_INFO struct */
2503 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2504 OUR_HANDLE(handle)));
2508 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2510 /* jfm: the change value isn't used right now.
2511 * we will honour it when
2512 * a) we'll be able to send notification to the client
2513 * b) we'll have a way to communicate between the spoolss process.
2515 * same thing for option->flags
2516 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2517 * I don't have a global notification system, I'm sending back all the
2518 * informations even when _NOTHING_ has changed.
2521 /* just ignore the SPOOL_NOTIFY_OPTION */
2523 switch (Printer->printer_type) {
2524 case PRINTER_HANDLE_IS_PRINTSERVER:
2525 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2528 case PRINTER_HANDLE_IS_PRINTER:
2529 result = printer_notify_info(p, handle, info, p->mem_ctx);
2537 /********************************************************************
2538 * construct_printer_info_0
2539 * fill a printer_info_0 struct
2540 ********************************************************************/
2541 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2545 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2546 counter_printer_0 *session_counter;
2547 uint32 global_counter;
2550 print_status_struct status;
2552 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2555 count = print_queue_length(snum, &status);
2557 /* check if we already have a counter for this printer */
2558 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2560 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2561 if (session_counter->snum == snum)
2565 /* it's the first time, add it to the list */
2566 if (session_counter==NULL) {
2567 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2568 free_a_printer(&ntprinter, 2);
2571 ZERO_STRUCTP(session_counter);
2572 session_counter->snum=snum;
2573 session_counter->counter=0;
2574 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2578 session_counter->counter++;
2581 * the global_counter should be stored in a TDB as it's common to all the clients
2582 * and should be zeroed on samba startup
2584 global_counter=session_counter->counter;
2586 pstrcpy(chaine,ntprinter->info_2->printername);
2588 init_unistr(&printer->printername, chaine);
2590 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
2591 init_unistr(&printer->servername, chaine);
2593 printer->cjobs = count;
2594 printer->total_jobs = 0;
2595 printer->total_bytes = 0;
2597 setuptime = (time_t)ntprinter->info_2->setuptime;
2598 t=gmtime(&setuptime);
2600 printer->year = t->tm_year+1900;
2601 printer->month = t->tm_mon+1;
2602 printer->dayofweek = t->tm_wday;
2603 printer->day = t->tm_mday;
2604 printer->hour = t->tm_hour;
2605 printer->minute = t->tm_min;
2606 printer->second = t->tm_sec;
2607 printer->milliseconds = 0;
2609 printer->global_counter = global_counter;
2610 printer->total_pages = 0;
2611 printer->major_version = 0x0004; /* NT 4 */
2612 printer->build_version = 0x0565; /* build 1381 */
2613 printer->unknown7 = 0x1;
2614 printer->unknown8 = 0x0;
2615 printer->unknown9 = 0x0;
2616 printer->session_counter = session_counter->counter;
2617 printer->unknown11 = 0x0;
2618 printer->printer_errors = 0x0; /* number of print failure */
2619 printer->unknown13 = 0x0;
2620 printer->unknown14 = 0x1;
2621 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2622 printer->unknown16 = 0x0;
2623 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2624 printer->unknown18 = 0x0;
2625 printer->status = nt_printq_status(status.status);
2626 printer->unknown20 = 0x0;
2627 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2628 printer->unknown22 = 0x0;
2629 printer->unknown23 = 0x6; /* 6 ???*/
2630 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2631 printer->unknown25 = 0;
2632 printer->unknown26 = 0;
2633 printer->unknown27 = 0;
2634 printer->unknown28 = 0;
2635 printer->unknown29 = 0;
2637 free_a_printer(&ntprinter,2);
2641 /********************************************************************
2642 * construct_printer_info_1
2643 * fill a printer_info_1 struct
2644 ********************************************************************/
2645 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2649 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2651 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2654 printer->flags=flags;
2656 if (*ntprinter->info_2->comment == '\0') {
2657 init_unistr(&printer->comment, lp_comment(snum));
2658 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
2659 ntprinter->info_2->drivername, lp_comment(snum));
2662 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2663 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
2664 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2667 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2669 init_unistr(&printer->description, chaine);
2670 init_unistr(&printer->name, chaine2);
2672 free_a_printer(&ntprinter,2);
2677 /****************************************************************************
2678 Free a DEVMODE struct.
2679 ****************************************************************************/
2681 static void free_dev_mode(DEVICEMODE *dev)
2686 SAFE_FREE(dev->private);
2690 /****************************************************************************
2691 Create a DEVMODE struct. Returns malloced memory.
2692 ****************************************************************************/
2694 static DEVICEMODE *construct_dev_mode(int snum)
2698 NT_PRINTER_INFO_LEVEL *printer = NULL;
2699 NT_DEVICEMODE *ntdevmode = NULL;
2700 DEVICEMODE *devmode = NULL;
2702 DEBUG(7,("construct_dev_mode\n"));
2704 DEBUGADD(8,("getting printer characteristics\n"));
2706 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2707 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2711 ZERO_STRUCTP(devmode);
2713 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2716 if (printer->info_2->devmode)
2717 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2719 if (ntdevmode == NULL)
2722 DEBUGADD(8,("loading DEVICEMODE\n"));
2724 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2725 init_unistr(&devmode->devicename, adevice);
2727 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2728 init_unistr(&devmode->formname, aform);
2730 devmode->specversion = ntdevmode->specversion;
2731 devmode->driverversion = ntdevmode->driverversion;
2732 devmode->size = ntdevmode->size;
2733 devmode->driverextra = ntdevmode->driverextra;
2734 devmode->fields = ntdevmode->fields;
2736 devmode->orientation = ntdevmode->orientation;
2737 devmode->papersize = ntdevmode->papersize;
2738 devmode->paperlength = ntdevmode->paperlength;
2739 devmode->paperwidth = ntdevmode->paperwidth;
2740 devmode->scale = ntdevmode->scale;
2741 devmode->copies = ntdevmode->copies;
2742 devmode->defaultsource = ntdevmode->defaultsource;
2743 devmode->printquality = ntdevmode->printquality;
2744 devmode->color = ntdevmode->color;
2745 devmode->duplex = ntdevmode->duplex;
2746 devmode->yresolution = ntdevmode->yresolution;
2747 devmode->ttoption = ntdevmode->ttoption;
2748 devmode->collate = ntdevmode->collate;
2749 devmode->icmmethod = ntdevmode->icmmethod;
2750 devmode->icmintent = ntdevmode->icmintent;
2751 devmode->mediatype = ntdevmode->mediatype;
2752 devmode->dithertype = ntdevmode->dithertype;
2754 if (ntdevmode->private != NULL) {
2755 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2759 free_nt_devicemode(&ntdevmode);
2760 free_a_printer(&printer,2);
2767 free_nt_devicemode(&ntdevmode);
2769 free_a_printer(&printer,2);
2770 free_dev_mode(devmode);
2775 /********************************************************************
2776 * construct_printer_info_2
2777 * fill a printer_info_2 struct
2778 ********************************************************************/
2780 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2783 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2785 print_status_struct status;
2787 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2790 count = print_queue_length(snum, &status);
2792 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2793 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2794 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2795 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2796 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2798 if (*ntprinter->info_2->comment == '\0')
2799 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2801 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2803 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2804 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2805 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2806 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2807 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2809 printer->attributes = ntprinter->info_2->attributes;
2811 printer->priority = ntprinter->info_2->priority; /* priority */
2812 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2813 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2814 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2815 printer->status = nt_printq_status(status.status); /* status */
2816 printer->cjobs = count; /* jobs */
2817 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2819 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2820 DEBUG(8, ("Returning NULL Devicemode!\n"));
2823 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2824 /* steal the printer info sec_desc structure. [badly done]. */
2825 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2826 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2827 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2828 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2831 printer->secdesc = NULL;
2834 free_a_printer(&ntprinter, 2);
2838 /********************************************************************
2839 * construct_printer_info_3
2840 * fill a printer_info_3 struct
2841 ********************************************************************/
2842 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2844 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2845 PRINTER_INFO_3 *printer = NULL;
2847 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2851 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2852 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2856 ZERO_STRUCTP(printer);
2858 printer->flags = 4; /* These are the components of the SD we are returning. */
2859 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2860 /* steal the printer info sec_desc structure. [badly done]. */
2861 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2865 * Set the flags for the components we are returning.
2868 if (printer->secdesc->owner_sid)
2869 printer->flags |= OWNER_SECURITY_INFORMATION;
2871 if (printer->secdesc->grp_sid)
2872 printer->flags |= GROUP_SECURITY_INFORMATION;
2874 if (printer->secdesc->dacl)
2875 printer->flags |= DACL_SECURITY_INFORMATION;
2877 if (printer->secdesc->sacl)
2878 printer->flags |= SACL_SECURITY_INFORMATION;
2881 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2882 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2883 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2886 free_a_printer(&ntprinter, 2);
2888 *pp_printer = printer;
2892 /********************************************************************
2893 * construct_printer_info_4
2894 * fill a printer_info_4 struct
2895 ********************************************************************/
2897 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
2899 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2901 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2904 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2905 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2906 printer->attributes = ntprinter->info_2->attributes;
2908 free_a_printer(&ntprinter, 2);
2912 /********************************************************************
2913 * construct_printer_info_5
2914 * fill a printer_info_5 struct
2915 ********************************************************************/
2917 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
2919 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2921 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2924 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2925 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
2926 printer->attributes = ntprinter->info_2->attributes;
2927 printer->device_not_selected_timeout = 0x3a98;
2928 printer->transmission_retry_timeout = 0xafc8;
2930 free_a_printer(&ntprinter, 2);
2935 /********************************************************************
2936 Spoolss_enumprinters.
2937 ********************************************************************/
2938 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2942 int n_services=lp_numservices();
2943 PRINTER_INFO_1 *tp, *printers=NULL;
2944 PRINTER_INFO_1 current_prt;
2946 DEBUG(4,("enum_all_printers_info_1\n"));
2948 for (snum=0; snum<n_services; snum++) {
2949 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2950 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2952 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2953 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2954 DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2955 SAFE_FREE(printers);
2960 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2961 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
2967 /* check the required size. */
2968 for (i=0; i<*returned; i++)
2969 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2971 if (!alloc_buffer_size(buffer, *needed))
2972 return WERR_INSUFFICIENT_BUFFER;
2974 /* fill the buffer with the structures */
2975 for (i=0; i<*returned; i++)
2976 smb_io_printer_info_1("", buffer, &printers[i], 0);
2979 SAFE_FREE(printers);
2981 if (*needed > offered) {
2983 return WERR_INSUFFICIENT_BUFFER;
2989 /********************************************************************
2990 enum_all_printers_info_1_local.
2991 *********************************************************************/
2992 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2994 DEBUG(4,("enum_all_printers_info_1_local\n"));
2996 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2999 /********************************************************************
3000 enum_all_printers_info_1_name.
3001 *********************************************************************/
3002 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3006 DEBUG(4,("enum_all_printers_info_1_name\n"));
3008 if ((name[0] == '\\') && (name[1] == '\\'))
3011 if (is_myname_or_ipaddr(s)) {
3012 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3015 return WERR_INVALID_NAME;
3018 /********************************************************************
3019 enum_all_printers_info_1_remote.
3020 *********************************************************************/
3021 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3023 PRINTER_INFO_1 *printer;
3024 fstring printername;
3027 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3029 /* JFM: currently it's more a place holder than anything else.
3030 * In the spooler world there is a notion of server registration.
3031 * the print servers are registring (sp ?) on the PDC (in the same domain)
3033 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3036 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3041 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3042 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3043 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3045 init_unistr(&printer->description, desc);
3046 init_unistr(&printer->name, printername);
3047 init_unistr(&printer->comment, comment);
3048 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3050 /* check the required size. */
3051 *needed += spoolss_size_printer_info_1(printer);
3053 if (!alloc_buffer_size(buffer, *needed)) {
3055 return WERR_INSUFFICIENT_BUFFER;
3058 /* fill the buffer with the structures */
3059 smb_io_printer_info_1("", buffer, printer, 0);
3064 if (*needed > offered) {
3066 return WERR_INSUFFICIENT_BUFFER;
3072 /********************************************************************
3073 enum_all_printers_info_1_network.
3074 *********************************************************************/
3076 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3078 DEBUG(4,("enum_all_printers_info_1_network\n"));
3080 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3083 /********************************************************************
3084 * api_spoolss_enumprinters
3086 * called from api_spoolss_enumprinters (see this to understand)
3087 ********************************************************************/
3089 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3093 int n_services=lp_numservices();
3094 PRINTER_INFO_2 *tp, *printers=NULL;
3095 PRINTER_INFO_2 current_prt;
3097 for (snum=0; snum<n_services; snum++) {
3098 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3099 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3101 if (construct_printer_info_2(¤t_prt, snum)) {
3102 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3103 DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3104 SAFE_FREE(printers);
3109 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3110 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
3116 /* check the required size. */
3117 for (i=0; i<*returned; i++)
3118 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3120 if (!alloc_buffer_size(buffer, *needed)) {
3121 for (i=0; i<*returned; i++) {
3122 free_devmode(printers[i].devmode);
3124 SAFE_FREE(printers);
3125 return WERR_INSUFFICIENT_BUFFER;
3128 /* fill the buffer with the structures */
3129 for (i=0; i<*returned; i++)
3130 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3133 for (i=0; i<*returned; i++) {
3134 free_devmode(printers[i].devmode);
3136 SAFE_FREE(printers);
3138 if (*needed > offered) {
3140 return WERR_INSUFFICIENT_BUFFER;
3146 /********************************************************************
3147 * handle enumeration of printers at level 1
3148 ********************************************************************/
3149 static WERROR enumprinters_level1( uint32 flags, fstring name,
3150 NEW_BUFFER *buffer, uint32 offered,
3151 uint32 *needed, uint32 *returned)
3153 /* Not all the flags are equals */
3155 if (flags & PRINTER_ENUM_LOCAL)
3156 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3158 if (flags & PRINTER_ENUM_NAME)
3159 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3161 if (flags & PRINTER_ENUM_REMOTE)
3162 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3164 if (flags & PRINTER_ENUM_NETWORK)
3165 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3167 return WERR_OK; /* NT4sp5 does that */
3170 /********************************************************************
3171 * handle enumeration of printers at level 2
3172 ********************************************************************/
3173 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3174 NEW_BUFFER *buffer, uint32 offered,
3175 uint32 *needed, uint32 *returned)
3177 char *s = servername;
3179 if (flags & PRINTER_ENUM_LOCAL) {
3180 return enum_all_printers_info_2(buffer, offered, needed, returned);
3183 if (flags & PRINTER_ENUM_NAME) {
3184 if ((servername[0] == '\\') && (servername[1] == '\\'))
3186 if (is_myname_or_ipaddr(s))
3187 return enum_all_printers_info_2(buffer, offered, needed, returned);
3189 return WERR_INVALID_NAME;
3192 if (flags & PRINTER_ENUM_REMOTE)
3193 return WERR_UNKNOWN_LEVEL;
3198 /********************************************************************
3199 * handle enumeration of printers at level 5
3200 ********************************************************************/
3201 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3202 NEW_BUFFER *buffer, uint32 offered,
3203 uint32 *needed, uint32 *returned)
3205 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3209 /********************************************************************
3210 * api_spoolss_enumprinters
3212 * called from api_spoolss_enumprinters (see this to understand)
3213 ********************************************************************/
3215 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3217 uint32 flags = q_u->flags;
3218 UNISTR2 *servername = &q_u->servername;
3219 uint32 level = q_u->level;
3220 NEW_BUFFER *buffer = NULL;
3221 uint32 offered = q_u->offered;
3222 uint32 *needed = &r_u->needed;
3223 uint32 *returned = &r_u->returned;
3227 /* that's an [in out] buffer */
3228 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3229 buffer = r_u->buffer;
3231 DEBUG(4,("_spoolss_enumprinters\n"));
3238 * flags==PRINTER_ENUM_NAME
3239 * if name=="" then enumerates all printers
3240 * if name!="" then enumerate the printer
3241 * flags==PRINTER_ENUM_REMOTE
3242 * name is NULL, enumerate printers
3243 * Level 2: name!="" enumerates printers, name can't be NULL
3244 * Level 3: doesn't exist
3245 * Level 4: does a local registry lookup
3246 * Level 5: same as Level 2
3249 unistr2_to_ascii(name, servername, sizeof(name)-1);
3254 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3256 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3258 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3263 return WERR_UNKNOWN_LEVEL;
3266 /****************************************************************************
3267 ****************************************************************************/
3268 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3270 PRINTER_INFO_0 *printer=NULL;
3272 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3275 construct_printer_info_0(printer, snum);
3277 /* check the required size. */
3278 *needed += spoolss_size_printer_info_0(printer);
3280 if (!alloc_buffer_size(buffer, *needed)) {
3282 return WERR_INSUFFICIENT_BUFFER;
3285 /* fill the buffer with the structures */
3286 smb_io_printer_info_0("", buffer, printer, 0);
3291 if (*needed > offered) {
3292 return WERR_INSUFFICIENT_BUFFER;
3298 /****************************************************************************
3299 ****************************************************************************/
3300 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3302 PRINTER_INFO_1 *printer=NULL;
3304 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3307 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3309 /* check the required size. */
3310 *needed += spoolss_size_printer_info_1(printer);
3312 if (!alloc_buffer_size(buffer, *needed)) {
3314 return WERR_INSUFFICIENT_BUFFER;
3317 /* fill the buffer with the structures */
3318 smb_io_printer_info_1("", buffer, printer, 0);
3323 if (*needed > offered) {
3324 return WERR_INSUFFICIENT_BUFFER;
3330 /****************************************************************************
3331 ****************************************************************************/
3332 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3334 PRINTER_INFO_2 *printer=NULL;
3336 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3339 construct_printer_info_2(printer, snum);
3341 /* check the required size. */
3342 *needed += spoolss_size_printer_info_2(printer);
3344 if (!alloc_buffer_size(buffer, *needed)) {
3345 free_printer_info_2(printer);
3346 return WERR_INSUFFICIENT_BUFFER;
3349 /* fill the buffer with the structures */
3350 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3351 free_printer_info_2(printer);
3356 free_printer_info_2(printer);
3358 if (*needed > offered) {
3359 return WERR_INSUFFICIENT_BUFFER;
3365 /****************************************************************************
3366 ****************************************************************************/
3367 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3369 PRINTER_INFO_3 *printer=NULL;
3371 if (!construct_printer_info_3(&printer, snum))
3374 /* check the required size. */
3375 *needed += spoolss_size_printer_info_3(printer);
3377 if (!alloc_buffer_size(buffer, *needed)) {
3378 free_printer_info_3(printer);
3379 return WERR_INSUFFICIENT_BUFFER;
3382 /* fill the buffer with the structures */
3383 smb_io_printer_info_3("", buffer, printer, 0);
3386 free_printer_info_3(printer);
3388 if (*needed > offered) {
3389 return WERR_INSUFFICIENT_BUFFER;
3395 /****************************************************************************
3396 ****************************************************************************/
3397 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3399 PRINTER_INFO_4 *printer=NULL;
3401 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
3404 if (!construct_printer_info_4(printer, snum))
3407 /* check the required size. */
3408 *needed += spoolss_size_printer_info_4(printer);
3410 if (!alloc_buffer_size(buffer, *needed)) {
3411 free_printer_info_4(printer);
3412 return WERR_INSUFFICIENT_BUFFER;
3415 /* fill the buffer with the structures */
3416 smb_io_printer_info_4("", buffer, printer, 0);
3419 free_printer_info_4(printer);
3421 if (*needed > offered) {
3422 return WERR_INSUFFICIENT_BUFFER;
3428 /****************************************************************************
3429 ****************************************************************************/
3430 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3432 PRINTER_INFO_5 *printer=NULL;
3434 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
3437 if (!construct_printer_info_5(printer, snum))
3440 /* check the required size. */
3441 *needed += spoolss_size_printer_info_5(printer);
3443 if (!alloc_buffer_size(buffer, *needed)) {
3444 free_printer_info_5(printer);
3445 return WERR_INSUFFICIENT_BUFFER;
3448 /* fill the buffer with the structures */
3449 smb_io_printer_info_5("", buffer, printer, 0);
3452 free_printer_info_5(printer);
3454 if (*needed > offered) {
3455 return WERR_INSUFFICIENT_BUFFER;
3461 /****************************************************************************
3462 ****************************************************************************/
3464 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3466 POLICY_HND *handle = &q_u->handle;
3467 uint32 level = q_u->level;
3468 NEW_BUFFER *buffer = NULL;
3469 uint32 offered = q_u->offered;
3470 uint32 *needed = &r_u->needed;
3474 /* that's an [in out] buffer */
3475 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3476 buffer = r_u->buffer;
3480 if (!get_printer_snum(p, handle, &snum))
3485 return getprinter_level_0(snum, buffer, offered, needed);
3487 return getprinter_level_1(snum, buffer, offered, needed);
3489 return getprinter_level_2(snum, buffer, offered, needed);
3491 return getprinter_level_3(snum, buffer, offered, needed);
3493 return getprinter_level_4(snum, buffer, offered, needed);
3495 return getprinter_level_5(snum, buffer, offered, needed);
3497 return WERR_UNKNOWN_LEVEL;
3500 /********************************************************************
3501 * fill a DRIVER_INFO_1 struct
3502 ********************************************************************/
3503 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3505 init_unistr( &info->name, driver.info_3->name);
3508 /********************************************************************
3509 * construct_printer_driver_info_1
3510 ********************************************************************/
3511 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3513 NT_PRINTER_INFO_LEVEL *printer = NULL;
3514 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3516 ZERO_STRUCT(driver);
3518 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3519 return WERR_INVALID_PRINTER_NAME;
3521 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3522 return WERR_UNKNOWN_PRINTER_DRIVER;
3524 fill_printer_driver_info_1(info, driver, servername, architecture);
3526 free_a_printer(&printer,2);
3531 /********************************************************************
3532 * construct_printer_driver_info_2
3533 * fill a printer_info_2 struct
3534 ********************************************************************/
3535 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3539 info->version=driver.info_3->cversion;
3541 init_unistr( &info->name, driver.info_3->name );
3542 init_unistr( &info->architecture, driver.info_3->environment );
3545 if (strlen(driver.info_3->driverpath)) {
3546 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3547 init_unistr( &info->driverpath, temp );
3549 init_unistr( &info->driverpath, "" );
3551 if (strlen(driver.info_3->datafile)) {
3552 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3553 init_unistr( &info->datafile, temp );
3555 init_unistr( &info->datafile, "" );
3557 if (strlen(driver.info_3->configfile)) {
3558 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3559 init_unistr( &info->configfile, temp );
3561 init_unistr( &info->configfile, "" );
3564 /********************************************************************
3565 * construct_printer_driver_info_2
3566 * fill a printer_info_2 struct
3567 ********************************************************************/
3568 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3570 NT_PRINTER_INFO_LEVEL *printer = NULL;
3571 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3573 ZERO_STRUCT(printer);
3574 ZERO_STRUCT(driver);
3576 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3577 return WERR_INVALID_PRINTER_NAME;
3579 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3580 return WERR_UNKNOWN_PRINTER_DRIVER;
3582 fill_printer_driver_info_2(info, driver, servername);
3584 free_a_printer(&printer,2);
3589 /********************************************************************
3590 * copy a strings array and convert to UNICODE
3592 * convert an array of ascii string to a UNICODE string
3593 ********************************************************************/
3594 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3602 DEBUG(6,("init_unistr_array\n"));
3606 if (char_array == NULL)
3610 if (!v) v = ""; /* hack to handle null lists */
3612 if (strlen(v) == 0) break;
3613 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3614 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3615 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3616 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3619 else *uni_array = tuary;
3620 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3625 (*uni_array)[j]=0x0000;
3628 DEBUGADD(6,("last one:done\n"));
3631 /********************************************************************
3632 * construct_printer_info_3
3633 * fill a printer_info_3 struct
3634 ********************************************************************/
3635 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3641 info->version=driver.info_3->cversion;
3643 init_unistr( &info->name, driver.info_3->name );
3644 init_unistr( &info->architecture, driver.info_3->environment );
3646 if (strlen(driver.info_3->driverpath)) {
3647 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3648 init_unistr( &info->driverpath, temp );
3650 init_unistr( &info->driverpath, "" );
3652 if (strlen(driver.info_3->datafile)) {
3653 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3654 init_unistr( &info->datafile, temp );
3656 init_unistr( &info->datafile, "" );
3658 if (strlen(driver.info_3->configfile)) {
3659 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3660 init_unistr( &info->configfile, temp );
3662 init_unistr( &info->configfile, "" );
3664 if (strlen(driver.info_3->helpfile)) {
3665 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3666 init_unistr( &info->helpfile, temp );
3668 init_unistr( &info->helpfile, "" );
3670 init_unistr( &info->monitorname, driver.info_3->monitorname );
3671 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3673 info->dependentfiles=NULL;
3674 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3677 /********************************************************************
3678 * construct_printer_info_3
3679 * fill a printer_info_3 struct
3680 ********************************************************************/
3681 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3683 NT_PRINTER_INFO_LEVEL *printer = NULL;
3684 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3686 ZERO_STRUCT(driver);
3688 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3689 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3690 if (!W_ERROR_IS_OK(status))
3691 return WERR_INVALID_PRINTER_NAME;
3693 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3694 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3695 if (!W_ERROR_IS_OK(status)) {
3696 free_a_printer(&printer,2);
3697 return WERR_UNKNOWN_PRINTER_DRIVER;
3700 fill_printer_driver_info_3(info, driver, servername);
3702 free_a_printer(&printer,2);
3707 /********************************************************************
3708 * construct_printer_info_6
3709 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3710 ********************************************************************/
3712 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3718 memset(&nullstr, '\0', sizeof(fstring));
3720 info->version=driver.info_3->cversion;
3722 init_unistr( &info->name, driver.info_3->name );
3723 init_unistr( &info->architecture, driver.info_3->environment );
3725 if (strlen(driver.info_3->driverpath)) {
3726 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3727 init_unistr( &info->driverpath, temp );
3729 init_unistr( &info->driverpath, "" );
3731 if (strlen(driver.info_3->datafile)) {
3732 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3733 init_unistr( &info->datafile, temp );
3735 init_unistr( &info->datafile, "" );
3737 if (strlen(driver.info_3->configfile)) {
3738 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3739 init_unistr( &info->configfile, temp );
3741 init_unistr( &info->configfile, "" );
3743 if (strlen(driver.info_3->helpfile)) {
3744 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3745 init_unistr( &info->helpfile, temp );
3747 init_unistr( &info->helpfile, "" );
3749 init_unistr( &info->monitorname, driver.info_3->monitorname );
3750 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3752 info->dependentfiles=NULL;
3753 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3755 info->previousdrivernames=NULL;
3756 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3758 info->driver_date.low=0;
3759 info->driver_date.high=0;
3762 info->driver_version_low=0;
3763 info->driver_version_high=0;
3765 init_unistr( &info->mfgname, "");
3766 init_unistr( &info->oem_url, "");
3767 init_unistr( &info->hardware_id, "");
3768 init_unistr( &info->provider, "");
3771 /********************************************************************
3772 * construct_printer_info_6
3773 * fill a printer_info_6 struct
3774 ********************************************************************/
3775 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3777 NT_PRINTER_INFO_LEVEL *printer = NULL;
3778 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3780 ZERO_STRUCT(driver);
3782 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3783 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3784 if (!W_ERROR_IS_OK(status))
3785 return WERR_INVALID_PRINTER_NAME;
3787 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3788 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3789 if (!W_ERROR_IS_OK(status)) {
3791 * Is this a W2k client ?
3795 free_a_printer(&printer,2);
3796 return WERR_UNKNOWN_PRINTER_DRIVER;
3799 /* Yes - try again with a WinNT driver. */
3801 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3802 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3803 if (!W_ERROR_IS_OK(status)) {
3804 free_a_printer(&printer,2);
3805 return WERR_UNKNOWN_PRINTER_DRIVER;
3809 fill_printer_driver_info_6(info, driver, servername);
3811 free_a_printer(&printer,2);
3816 /****************************************************************************
3817 ****************************************************************************/
3819 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3821 SAFE_FREE(info->dependentfiles);
3824 /****************************************************************************
3825 ****************************************************************************/
3827 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3829 SAFE_FREE(info->dependentfiles);
3833 /****************************************************************************
3834 ****************************************************************************/
3835 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3837 DRIVER_INFO_1 *info=NULL;
3840 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3843 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3844 if (!W_ERROR_IS_OK(status)) {
3849 /* check the required size. */
3850 *needed += spoolss_size_printer_driver_info_1(info);
3852 if (!alloc_buffer_size(buffer, *needed)) {
3854 return WERR_INSUFFICIENT_BUFFER;
3857 /* fill the buffer with the structures */
3858 smb_io_printer_driver_info_1("", buffer, info, 0);
3863 if (*needed > offered)
3864 return WERR_INSUFFICIENT_BUFFER;
3869 /****************************************************************************
3870 ****************************************************************************/
3871 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3873 DRIVER_INFO_2 *info=NULL;
3876 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3879 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3880 if (!W_ERROR_IS_OK(status)) {
3885 /* check the required size. */
3886 *needed += spoolss_size_printer_driver_info_2(info);
3888 if (!alloc_buffer_size(buffer, *needed)) {
3890 return WERR_INSUFFICIENT_BUFFER;
3893 /* fill the buffer with the structures */
3894 smb_io_printer_driver_info_2("", buffer, info, 0);
3899 if (*needed > offered)
3900 return WERR_INSUFFICIENT_BUFFER;
3905 /****************************************************************************
3906 ****************************************************************************/
3907 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3914 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3915 if (!W_ERROR_IS_OK(status)) {
3919 /* check the required size. */
3920 *needed += spoolss_size_printer_driver_info_3(&info);
3922 if (!alloc_buffer_size(buffer, *needed)) {
3923 free_printer_driver_info_3(&info);
3924 return WERR_INSUFFICIENT_BUFFER;
3927 /* fill the buffer with the structures */
3928 smb_io_printer_driver_info_3("", buffer, &info, 0);
3930 free_printer_driver_info_3(&info);
3932 if (*needed > offered)
3933 return WERR_INSUFFICIENT_BUFFER;
3938 /****************************************************************************
3939 ****************************************************************************/
3940 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3947 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3948 if (!W_ERROR_IS_OK(status)) {
3952 /* check the required size. */
3953 *needed += spoolss_size_printer_driver_info_6(&info);
3955 if (!alloc_buffer_size(buffer, *needed)) {
3956 free_printer_driver_info_6(&info);
3957 return WERR_INSUFFICIENT_BUFFER;
3960 /* fill the buffer with the structures */
3961 smb_io_printer_driver_info_6("", buffer, &info, 0);
3963 free_printer_driver_info_6(&info);
3965 if (*needed > offered)
3966 return WERR_INSUFFICIENT_BUFFER;
3971 /****************************************************************************
3972 ****************************************************************************/
3974 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3976 POLICY_HND *handle = &q_u->handle;
3977 UNISTR2 *uni_arch = &q_u->architecture;
3978 uint32 level = q_u->level;
3979 uint32 clientmajorversion = q_u->clientmajorversion;
3980 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3981 NEW_BUFFER *buffer = NULL;
3982 uint32 offered = q_u->offered;
3983 uint32 *needed = &r_u->needed;
3984 uint32 *servermajorversion = &r_u->servermajorversion;
3985 uint32 *serverminorversion = &r_u->serverminorversion;
3988 fstring architecture;
3991 /* that's an [in out] buffer */
3992 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3993 buffer = r_u->buffer;
3995 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3998 *servermajorversion=0;
3999 *serverminorversion=0;
4001 pstrcpy(servername, get_called_name());
4002 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4004 if (!get_printer_snum(p, handle, &snum))
4009 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4011 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4013 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4015 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4018 return WERR_UNKNOWN_LEVEL;
4021 /****************************************************************************
4022 ****************************************************************************/
4024 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4026 POLICY_HND *handle = &q_u->handle;
4028 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4031 DEBUG(3,("Error in startpageprinter printer handle\n"));
4035 Printer->page_started=True;
4039 /****************************************************************************
4040 ****************************************************************************/
4042 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4044 POLICY_HND *handle = &q_u->handle;
4046 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4049 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
4053 Printer->page_started=False;
4058 /********************************************************************
4059 * api_spoolss_getprinter
4060 * called from the spoolss dispatcher
4062 ********************************************************************/
4064 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4066 POLICY_HND *handle = &q_u->handle;
4067 /* uint32 level = q_u->doc_info_container.level; - notused. */
4068 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4069 uint32 *jobid = &r_u->jobid;
4071 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4075 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4076 struct current_user user;
4079 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4083 get_current_user(&user, p);
4086 * a nice thing with NT is it doesn't listen to what you tell it.
4087 * when asked to send _only_ RAW datas, it tries to send datas
4090 * So I add checks like in NT Server ...
4092 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4093 * there's a bug in NT client-side code, so we'll fix it in the
4094 * server-side code. *nnnnnggggh!*
4097 if (info_1->p_datatype != 0) {
4098 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4099 if (strcmp(datatype, "RAW") != 0) {
4101 return WERR_INVALID_DATATYPE;
4105 /* get the share number of the printer */
4106 if (!get_printer_snum(p, handle, &snum)) {
4110 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4112 Printer->jobid = print_job_start(&user, snum, jobname);
4114 /* An error occured in print_job_start() so return an appropriate
4117 if (Printer->jobid == -1) {
4118 return map_werror_from_unix(errno);
4121 Printer->document_started=True;
4122 (*jobid) = Printer->jobid;
4127 /********************************************************************
4128 * api_spoolss_getprinter
4129 * called from the spoolss dispatcher
4131 ********************************************************************/
4133 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4135 POLICY_HND *handle = &q_u->handle;
4137 return _spoolss_enddocprinter_internal(p, handle);
4140 /****************************************************************************
4141 ****************************************************************************/
4143 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4145 POLICY_HND *handle = &q_u->handle;
4146 uint32 buffer_size = q_u->buffer_size;
4147 uint8 *buffer = q_u->buffer;
4148 uint32 *buffer_written = &q_u->buffer_size2;
4150 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4153 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
4154 r_u->buffer_written = q_u->buffer_size2;
4158 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4161 r_u->buffer_written = q_u->buffer_size2;
4166 /********************************************************************
4167 * api_spoolss_getprinter
4168 * called from the spoolss dispatcher
4170 ********************************************************************/
4171 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4174 struct current_user user;
4176 WERROR errcode = WERR_BADFUNC;
4177 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4179 get_current_user(&user, p);
4182 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4186 if (!get_printer_snum(p, handle, &snum))
4190 case PRINTER_CONTROL_PAUSE:
4191 if (print_queue_pause(&user, snum, &errcode)) {
4195 case PRINTER_CONTROL_RESUME:
4196 case PRINTER_CONTROL_UNPAUSE:
4197 if (print_queue_resume(&user, snum, &errcode)) {
4201 case PRINTER_CONTROL_PURGE:
4202 if (print_queue_purge(&user, snum, &errcode)) {
4207 return WERR_UNKNOWN_LEVEL;
4213 /********************************************************************
4214 * api_spoolss_abortprinter
4215 ********************************************************************/
4217 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4219 POLICY_HND *handle = &q_u->handle;
4221 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4224 /********************************************************************
4225 * called by spoolss_api_setprinter
4226 * when updating a printer description
4227 ********************************************************************/
4228 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4229 const SPOOL_PRINTER_INFO_LEVEL *info,
4230 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4232 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4233 struct current_user user;
4237 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4239 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4240 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4241 OUR_HANDLE(handle)));
4243 result = WERR_BADFID;
4247 /* NT seems to like setting the security descriptor even though
4248 nothing may have actually changed. This causes annoying
4249 dialog boxes when the user doesn't have permission to change
4250 the security descriptor. */
4252 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4254 if (DEBUGLEVEL >= 10) {
4258 the_acl = old_secdesc_ctr->sec->dacl;
4259 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4260 PRINTERNAME(snum), the_acl->num_aces));
4262 for (i = 0; i < the_acl->num_aces; i++) {
4265 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4267 DEBUG(10, ("%s 0x%08x\n", sid_str,
4268 the_acl->ace[i].info.mask));
4271 the_acl = secdesc_ctr->sec->dacl;
4274 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4275 PRINTERNAME(snum), the_acl->num_aces));
4277 for (i = 0; i < the_acl->num_aces; i++) {
4280 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4282 DEBUG(10, ("%s 0x%08x\n", sid_str,
4283 the_acl->ace[i].info.mask));
4286 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4290 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4292 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4297 /* Work out which user is performing the operation */
4299 get_current_user(&user, p);
4301 /* Check the user has permissions to change the security
4302 descriptor. By experimentation with two NT machines, the user
4303 requires Full Access to the printer to change security
4306 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4307 result = WERR_ACCESS_DENIED;
4311 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4318 /********************************************************************
4319 Do Samba sanity checks on a printer info struct.
4320 this has changed purpose: it now "canonicalises" printer
4321 info from a client rather than just checking it is correct
4322 ********************************************************************/
4324 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4326 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4327 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4329 /* we force some elements to "correct" values */
4330 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
4331 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4332 get_called_name(), lp_servicename(snum));
4333 fstrcpy(info->sharename, lp_servicename(snum));
4334 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4335 | PRINTER_ATTRIBUTE_LOCAL \
4336 | PRINTER_ATTRIBUTE_RAW_ONLY \
4337 | PRINTER_ATTRIBUTE_QUEUED ;
4342 /****************************************************************************
4343 ****************************************************************************/
4344 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4346 char *cmd = lp_addprinter_cmd();
4349 pstring driverlocation;
4354 /* build driver path... only 9X architecture is needed for legacy reasons */
4355 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4357 /* change \ to \\ for the shell */
4358 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4360 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4361 cmd, printer->info_2->printername, printer->info_2->sharename,
4362 printer->info_2->portname, printer->info_2->drivername,
4363 printer->info_2->location, driverlocation);
4365 DEBUG(10,("Running [%s]\n", command));
4366 ret = smbrun(command, &fd);
4367 DEBUGADD(10,("returned [%d]\n", ret));
4376 /* Get lines and convert them back to dos-codepage */
4377 qlines = fd_lines_load(fd, &numlines);
4378 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4382 /* Set the portname to what the script says the portname should be. */
4383 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4384 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4386 /* Send SIGHUP to process group... is there a better way? */
4391 file_lines_free(qlines);
4395 /* Return true if two devicemodes are equal */
4397 #define DEVMODE_CHECK_INT(field) \
4398 if (d1->field != d2->field) { \
4399 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4400 d1->field, d2->field)); \
4404 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4406 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4409 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4410 return False; /* if either is exclusively NULL are not equal */
4413 if (!strequal(d1->devicename, d2->devicename)) {
4414 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4418 if (!strequal(d1->formname, d2->formname)) {
4419 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4423 DEVMODE_CHECK_INT(specversion);
4424 DEVMODE_CHECK_INT(driverversion);
4425 DEVMODE_CHECK_INT(driverextra);
4426 DEVMODE_CHECK_INT(orientation);
4427 DEVMODE_CHECK_INT(papersize);
4428 DEVMODE_CHECK_INT(paperlength);
4429 DEVMODE_CHECK_INT(paperwidth);
4430 DEVMODE_CHECK_INT(scale);
4431 DEVMODE_CHECK_INT(copies);
4432 DEVMODE_CHECK_INT(defaultsource);
4433 DEVMODE_CHECK_INT(printquality);
4434 DEVMODE_CHECK_INT(color);
4435 DEVMODE_CHECK_INT(duplex);
4436 DEVMODE_CHECK_INT(yresolution);
4437 DEVMODE_CHECK_INT(ttoption);
4438 DEVMODE_CHECK_INT(collate);
4439 DEVMODE_CHECK_INT(logpixels);
4441 DEVMODE_CHECK_INT(fields);
4442 DEVMODE_CHECK_INT(bitsperpel);
4443 DEVMODE_CHECK_INT(pelswidth);
4444 DEVMODE_CHECK_INT(pelsheight);
4445 DEVMODE_CHECK_INT(displayflags);
4446 DEVMODE_CHECK_INT(displayfrequency);
4447 DEVMODE_CHECK_INT(icmmethod);
4448 DEVMODE_CHECK_INT(icmintent);
4449 DEVMODE_CHECK_INT(mediatype);
4450 DEVMODE_CHECK_INT(dithertype);
4451 DEVMODE_CHECK_INT(reserved1);
4452 DEVMODE_CHECK_INT(reserved2);
4453 DEVMODE_CHECK_INT(panningwidth);
4454 DEVMODE_CHECK_INT(panningheight);
4456 /* compare the private data if it exists */
4457 if (!d1->driverextra && !d2->driverextra) goto equal;
4460 DEVMODE_CHECK_INT(driverextra);
4462 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4463 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4468 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4472 /* Return true if two NT_PRINTER_PARAM structures are equal */
4474 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4475 NT_PRINTER_PARAM *p2)
4477 if (!p1 && !p2) goto equal;
4479 if ((!p1 && p2) || (p1 && !p2)) {
4480 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4484 /* Compare lists of printer parameters */
4488 NT_PRINTER_PARAM *q = p1;
4490 /* Find the parameter in the second structure */
4494 if (strequal(p1->value, q->value)) {
4496 if (p1->type != q->type) {
4497 DEBUG(10, ("nt_printer_param_equal():"
4498 "types for %s differ (%d != %d)\n",
4499 p1->value, p1->type,
4504 if (p1->data_len != q->data_len) {
4505 DEBUG(10, ("nt_printer_param_equal():"
4506 "len for %s differs (%d != %d)\n",
4507 p1->value, p1->data_len,
4512 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4515 DEBUG(10, ("nt_printer_param_equal():"
4516 "data for %s differs\n", p1->value));
4526 DEBUG(10, ("nt_printer_param_equal(): param %s "
4527 "does not exist\n", p1->value));
4536 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4540 /********************************************************************
4541 * Called by update_printer when trying to work out whether to
4542 * actually update printer info.
4543 ********************************************************************/
4545 #define PI_CHECK_INT(field) \
4546 if (pi1->field != pi2->field) { \
4547 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4548 pi1->field, pi2->field)); \
4552 #define PI_CHECK_STR(field) \
4553 if (!strequal(pi1->field, pi2->field)) { \
4554 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4555 pi1->field, pi2->field)); \
4559 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4560 NT_PRINTER_INFO_LEVEL *p2)
4562 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4564 /* Trivial conditions */
4566 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4570 if ((!p1 && p2) || (p1 && !p2) ||
4571 (!p1->info_2 && p2->info_2) ||
4572 (p1->info_2 && !p2->info_2)) {
4573 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4578 /* Compare two nt_printer_info_level structures. Don't compare
4579 status or cjobs as they seem to have something to do with the
4585 /* Don't check the attributes as we stomp on the value in
4586 check_printer_ok() anyway. */
4589 PI_CHECK_INT(attributes);
4592 PI_CHECK_INT(priority);
4593 PI_CHECK_INT(default_priority);
4594 PI_CHECK_INT(starttime);
4595 PI_CHECK_INT(untiltime);
4596 PI_CHECK_INT(averageppm);
4598 /* Yuck - don't check the printername or servername as the
4599 mod_a_printer() code plays games with them. You can't
4600 change the printername or the sharename through this interface
4603 PI_CHECK_STR(sharename);
4604 PI_CHECK_STR(portname);
4605 PI_CHECK_STR(drivername);
4606 PI_CHECK_STR(comment);
4607 PI_CHECK_STR(location);
4609 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4613 PI_CHECK_STR(sepfile);
4614 PI_CHECK_STR(printprocessor);
4615 PI_CHECK_STR(datatype);
4616 PI_CHECK_STR(parameters);
4618 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4622 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4626 PI_CHECK_INT(changeid);
4627 PI_CHECK_INT(c_setprinter);
4628 PI_CHECK_INT(setuptime);
4631 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4635 /********************************************************************
4636 * called by spoolss_api_setprinter
4637 * when updating a printer description
4638 ********************************************************************/
4640 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4641 const SPOOL_PRINTER_INFO_LEVEL *info,
4642 DEVICEMODE *devmode)
4645 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4646 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4649 DEBUG(8,("update_printer\n"));
4654 DEBUG(0,("Send a mail to samba@samba.org\n"));
4655 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4656 result = WERR_UNKNOWN_LEVEL;
4661 result = WERR_BADFID;
4665 if (!get_printer_snum(p, handle, &snum)) {
4666 result = WERR_BADFID;
4670 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
4671 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
4672 result = WERR_BADFID;
4676 DEBUGADD(8,("Converting info_2 struct\n"));
4679 * convert_printer_info converts the incoming
4680 * info from the client and overwrites the info
4681 * just read from the tdb in the pointer 'printer'.
4684 if (!convert_printer_info(info, printer, level)) {
4685 result = WERR_NOMEM;
4689 if (info->info_2->devmode_ptr != 0) {
4690 /* we have a valid devmode
4691 convert it and link it*/
4693 DEBUGADD(8,("Converting the devicemode struct\n"));
4694 if (!convert_devicemode(printer->info_2->printername, devmode,
4695 &printer->info_2->devmode)) {
4696 result = WERR_NOMEM;
4701 /* Do sanity check on the requested changes for Samba */
4703 if (!check_printer_ok(printer->info_2, snum)) {
4704 result = WERR_INVALID_PARAM;
4708 /* NT likes to call this function even though nothing has actually
4709 changed. Check this so the user doesn't end up with an
4710 annoying permission denied dialog box. */
4712 if (nt_printer_info_level_equal(printer, old_printer)) {
4713 DEBUG(3, ("printer info has not changed\n"));
4718 /* Check calling user has permission to update printer description */
4720 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4721 DEBUG(3, ("printer property change denied by security "
4723 result = WERR_ACCESS_DENIED;
4727 /* Call addprinter hook */
4729 if (*lp_addprinter_cmd()) {
4730 if (!add_printer_hook(printer)) {
4731 result = WERR_ACCESS_DENIED;
4736 /* Update printer info */
4737 result = mod_a_printer(*printer, 2);
4740 free_a_printer(&printer, 2);
4741 free_a_printer(&old_printer, 2);
4743 srv_spoolss_sendnotify(p, handle);
4748 /****************************************************************************
4749 ****************************************************************************/
4751 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4753 POLICY_HND *handle = &q_u->handle;
4754 uint32 level = q_u->level;
4755 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4756 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4757 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4758 uint32 command = q_u->command;
4760 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4763 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4767 /* check the level */
4770 return control_printer(handle, command, p);
4772 return update_printer(p, handle, level, info, devmode_ctr.devmode);
4774 return update_printer_sec(handle, level, info, p,
4777 return WERR_UNKNOWN_LEVEL;
4781 /****************************************************************************
4782 ****************************************************************************/
4784 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4786 POLICY_HND *handle = &q_u->handle;
4788 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4791 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4795 if (Printer->notify.client_connected==True)
4796 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4798 Printer->notify.flags=0;
4799 Printer->notify.options=0;
4800 Printer->notify.localmachine[0]='\0';
4801 Printer->notify.printerlocal=0;
4802 if (Printer->notify.option)
4803 free_spool_notify_option(&Printer->notify.option);
4804 Printer->notify.client_connected=False;
4809 /****************************************************************************
4810 ****************************************************************************/
4812 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4814 /* that's an [in out] buffer (despite appearences to the contrary) */
4815 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4818 return WERR_INVALID_PARAM; /* this is what a NT server
4819 returns for AddJob. AddJob
4820 must fail on non-local
4824 /****************************************************************************
4825 ****************************************************************************/
4826 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4827 int position, int snum)
4833 t=gmtime(&queue->time);
4834 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
4836 job_info->jobid=queue->job;
4837 init_unistr(&job_info->printername, lp_servicename(snum));
4838 init_unistr(&job_info->machinename, temp_name);
4839 init_unistr(&job_info->username, queue->user);
4840 init_unistr(&job_info->document, queue->file);
4841 init_unistr(&job_info->datatype, "RAW");
4842 init_unistr(&job_info->text_status, "");
4843 job_info->status=nt_printj_status(queue->status);
4844 job_info->priority=queue->priority;
4845 job_info->position=position;
4846 job_info->totalpages=0;
4847 job_info->pagesprinted=0;
4849 make_systemtime(&job_info->submitted, t);
4852 /****************************************************************************
4853 ****************************************************************************/
4854 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4855 int position, int snum,
4856 NT_PRINTER_INFO_LEVEL *ntprinter)
4862 t=gmtime(&queue->time);
4863 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
4865 job_info->jobid=queue->job;
4867 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
4869 init_unistr(&job_info->printername, chaine);
4871 init_unistr(&job_info->machinename, temp_name);
4872 init_unistr(&job_info->username, queue->user);
4873 init_unistr(&job_info->document, queue->file);
4874 init_unistr(&job_info->notifyname, queue->user);
4875 init_unistr(&job_info->datatype, "RAW");
4876 init_unistr(&job_info->printprocessor, "winprint");
4877 init_unistr(&job_info->parameters, "");
4878 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4879 init_unistr(&job_info->text_status, "");
4881 /* and here the security descriptor */
4883 job_info->status=nt_printj_status(queue->status);
4884 job_info->priority=queue->priority;
4885 job_info->position=position;
4886 job_info->starttime=0;
4887 job_info->untiltime=0;
4888 job_info->totalpages=0;
4889 job_info->size=queue->size;
4890 make_systemtime(&(job_info->submitted), t);
4891 job_info->timeelapsed=0;
4892 job_info->pagesprinted=0;
4894 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4901 /****************************************************************************
4902 Enumjobs at level 1.
4903 ****************************************************************************/
4904 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
4905 NEW_BUFFER *buffer, uint32 offered,
4906 uint32 *needed, uint32 *returned)
4911 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4918 for (i=0; i<*returned; i++)
4919 fill_job_info_1(&info[i], &queue[i], i, snum);
4923 /* check the required size. */
4924 for (i=0; i<*returned; i++)
4925 (*needed) += spoolss_size_job_info_1(&info[i]);
4927 if (!alloc_buffer_size(buffer, *needed)) {
4929 return WERR_INSUFFICIENT_BUFFER;
4932 /* fill the buffer with the structures */
4933 for (i=0; i<*returned; i++)
4934 smb_io_job_info_1("", buffer, &info[i], 0);
4939 if (*needed > offered) {
4941 return WERR_INSUFFICIENT_BUFFER;
4947 /****************************************************************************
4948 Enumjobs at level 2.
4949 ****************************************************************************/
4950 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
4951 NEW_BUFFER *buffer, uint32 offered,
4952 uint32 *needed, uint32 *returned)
4954 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4959 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4965 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
4966 if (!W_ERROR_IS_OK(result)) {
4971 for (i=0; i<*returned; i++)
4972 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4974 free_a_printer(&ntprinter, 2);
4977 /* check the required size. */
4978 for (i=0; i<*returned; i++)
4979 (*needed) += spoolss_size_job_info_2(&info[i]);
4981 if (!alloc_buffer_size(buffer, *needed)) {
4983 return WERR_INSUFFICIENT_BUFFER;
4986 /* fill the buffer with the structures */
4987 for (i=0; i<*returned; i++)
4988 smb_io_job_info_2("", buffer, &info[i], 0);
4991 for (i = 0; i < *returned; i++)
4992 free_job_info_2(&info[i]);
4996 if (*needed > offered) {
4998 return WERR_INSUFFICIENT_BUFFER;
5004 /****************************************************************************
5006 ****************************************************************************/
5008 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5010 POLICY_HND *handle = &q_u->handle;
5011 /* uint32 firstjob = q_u->firstjob; - notused. */
5012 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5013 uint32 level = q_u->level;
5014 NEW_BUFFER *buffer = NULL;
5015 uint32 offered = q_u->offered;
5016 uint32 *needed = &r_u->needed;
5017 uint32 *returned = &r_u->returned;
5020 print_status_struct prt_status;
5021 print_queue_struct *queue=NULL;
5023 /* that's an [in out] buffer */
5024 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5025 buffer = r_u->buffer;
5027 DEBUG(4,("_spoolss_enumjobs\n"));
5032 if (!get_printer_snum(p, handle, &snum))
5035 *returned = print_queue_status(snum, &queue, &prt_status);
5036 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5038 if (*returned == 0) {
5045 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5047 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5051 return WERR_UNKNOWN_LEVEL;
5055 /****************************************************************************
5056 ****************************************************************************/
5058 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5063 /****************************************************************************
5064 ****************************************************************************/
5066 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5068 POLICY_HND *handle = &q_u->handle;
5069 uint32 jobid = q_u->jobid;
5070 /* uint32 level = q_u->level; - notused. */
5071 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5072 uint32 command = q_u->command;
5074 struct current_user user;
5076 WERROR errcode = WERR_BADFUNC;
5078 if (!get_printer_snum(p, handle, &snum)) {
5082 if (!print_job_exists(jobid)) {
5083 return WERR_INVALID_PRINTER_NAME;
5086 get_current_user(&user, p);
5089 case JOB_CONTROL_CANCEL:
5090 case JOB_CONTROL_DELETE:
5091 if (print_job_delete(&user, jobid, &errcode)) {
5095 case JOB_CONTROL_PAUSE:
5096 if (print_job_pause(&user, jobid, &errcode)) {
5100 case JOB_CONTROL_RESTART:
5101 case JOB_CONTROL_RESUME:
5102 if (print_job_resume(&user, jobid, &errcode)) {
5107 return WERR_UNKNOWN_LEVEL;
5113 /****************************************************************************
5114 Enumerates all printer drivers at level 1.
5115 ****************************************************************************/
5116 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5121 fstring *list = NULL;
5123 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5124 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5128 #define MAX_VERSION 4
5130 for (version=0; version<MAX_VERSION; version++) {
5132 ndrivers=get_ntdrivers(&list, architecture, version);
5133 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5139 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5140 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5141 SAFE_FREE(driver_info_1);
5145 else driver_info_1 = tdi1;
5148 for (i=0; i<ndrivers; i++) {
5150 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5151 ZERO_STRUCT(driver);
5152 status = get_a_printer_driver(&driver, 3, list[i],
5153 architecture, version);
5154 if (!W_ERROR_IS_OK(status)) {
5158 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5159 free_a_printer_driver(driver, 3);
5162 *returned+=ndrivers;
5166 /* check the required size. */
5167 for (i=0; i<*returned; i++) {
5168 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5169 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5172 if (!alloc_buffer_size(buffer, *needed)) {
5173 SAFE_FREE(driver_info_1);
5174 return WERR_INSUFFICIENT_BUFFER;
5177 /* fill the buffer with the driver structures */
5178 for (i=0; i<*returned; i++) {
5179 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5180 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5183 SAFE_FREE(driver_info_1);
5185 if (*needed > offered) {
5187 return WERR_INSUFFICIENT_BUFFER;
5193 /****************************************************************************
5194 Enumerates all printer drivers at level 2.
5195 ****************************************************************************/
5196 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5201 fstring *list = NULL;
5203 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5204 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5208 #define MAX_VERSION 4
5210 for (version=0; version<MAX_VERSION; version++) {
5212 ndrivers=get_ntdrivers(&list, architecture, version);
5213 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5219 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5220 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5221 SAFE_FREE(driver_info_2);
5225 else driver_info_2 = tdi2;
5228 for (i=0; i<ndrivers; i++) {
5231 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5232 ZERO_STRUCT(driver);
5233 status = get_a_printer_driver(&driver, 3, list[i],
5234 architecture, version);
5235 if (!W_ERROR_IS_OK(status)) {
5239 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5240 free_a_printer_driver(driver, 3);
5243 *returned+=ndrivers;
5247 /* check the required size. */
5248 for (i=0; i<*returned; i++) {
5249 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5250 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5253 if (!alloc_buffer_size(buffer, *needed)) {
5254 SAFE_FREE(driver_info_2);
5255 return WERR_INSUFFICIENT_BUFFER;
5258 /* fill the buffer with the form structures */
5259 for (i=0; i<*returned; i++) {
5260 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5261 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5264 SAFE_FREE(driver_info_2);
5266 if (*needed > offered) {
5268 return WERR_INSUFFICIENT_BUFFER;
5274 /****************************************************************************
5275 Enumerates all printer drivers at level 3.
5276 ****************************************************************************/
5277 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5282 fstring *list = NULL;
5284 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5285 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5289 #define MAX_VERSION 4
5291 for (version=0; version<MAX_VERSION; version++) {
5293 ndrivers=get_ntdrivers(&list, architecture, version);
5294 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5300 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5301 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5302 SAFE_FREE(driver_info_3);
5306 else driver_info_3 = tdi3;
5309 for (i=0; i<ndrivers; i++) {
5312 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5313 ZERO_STRUCT(driver);
5314 status = get_a_printer_driver(&driver, 3, list[i],
5315 architecture, version);
5316 if (!W_ERROR_IS_OK(status)) {
5320 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5321 free_a_printer_driver(driver, 3);
5324 *returned+=ndrivers;
5328 /* check the required size. */
5329 for (i=0; i<*returned; i++) {
5330 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5331 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5334 if (!alloc_buffer_size(buffer, *needed)) {
5335 SAFE_FREE(driver_info_3);
5336 return WERR_INSUFFICIENT_BUFFER;
5339 /* fill the buffer with the driver structures */
5340 for (i=0; i<*returned; i++) {
5341 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5342 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5345 for (i=0; i<*returned; i++)
5346 SAFE_FREE(driver_info_3[i].dependentfiles);
5348 SAFE_FREE(driver_info_3);
5350 if (*needed > offered) {
5352 return WERR_INSUFFICIENT_BUFFER;
5358 /****************************************************************************
5359 Enumerates all printer drivers.
5360 ****************************************************************************/
5362 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5364 /* UNISTR2 *name = &q_u->name; - notused. */
5365 UNISTR2 *environment = &q_u->environment;
5366 uint32 level = q_u->level;
5367 NEW_BUFFER *buffer = NULL;
5368 uint32 offered = q_u->offered;
5369 uint32 *needed = &r_u->needed;
5370 uint32 *returned = &r_u->returned;
5372 fstring *list = NULL;
5374 fstring architecture;
5376 /* that's an [in out] buffer */
5377 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5378 buffer = r_u->buffer;
5380 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5381 fstrcpy(servername, get_called_name());
5385 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5389 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5391 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5393 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5397 return WERR_UNKNOWN_LEVEL;
5401 /****************************************************************************
5402 ****************************************************************************/
5404 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5406 form->flag=list->flag;
5407 init_unistr(&form->name, list->name);
5408 form->width=list->width;
5409 form->length=list->length;
5410 form->left=list->left;
5411 form->top=list->top;
5412 form->right=list->right;
5413 form->bottom=list->bottom;
5416 /****************************************************************************
5417 ****************************************************************************/
5419 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5421 /* POLICY_HND *handle = &q_u->handle; - notused. */
5422 uint32 level = q_u->level;
5423 NEW_BUFFER *buffer = NULL;
5424 uint32 offered = q_u->offered;
5425 uint32 *needed = &r_u->needed;
5426 uint32 *numofforms = &r_u->numofforms;
5427 uint32 numbuiltinforms;
5429 nt_forms_struct *list=NULL;
5430 nt_forms_struct *builtinlist=NULL;
5435 /* that's an [in out] buffer */
5436 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5437 buffer = r_u->buffer;
5439 DEBUG(4,("_spoolss_enumforms\n"));
5440 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5441 DEBUGADD(5,("Info level [%d]\n", level));
5443 numbuiltinforms = get_builtin_ntforms(&builtinlist);
5444 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
5445 *numofforms = get_ntforms(&list);
5446 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
5447 *numofforms += numbuiltinforms;
5449 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
5453 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5458 /* construct the list of form structures */
5459 for (i=0; i<numbuiltinforms; i++) {
5460 DEBUGADD(6,("Filling form number [%d]\n",i));
5461 fill_form_1(&forms_1[i], &builtinlist[i]);
5464 SAFE_FREE(builtinlist);
5466 for (; i<*numofforms; i++) {
5467 DEBUGADD(6,("Filling form number [%d]\n",i));
5468 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5473 /* check the required size. */
5474 for (i=0; i<numbuiltinforms; i++) {
5475 DEBUGADD(6,("adding form [%d]'s size\n",i));
5476 buffer_size += spoolss_size_form_1(&forms_1[i]);
5478 for (; i<*numofforms; i++) {
5479 DEBUGADD(6,("adding form [%d]'s size\n",i));
5480 buffer_size += spoolss_size_form_1(&forms_1[i]);
5483 *needed=buffer_size;
5485 if (!alloc_buffer_size(buffer, buffer_size)){
5487 return WERR_INSUFFICIENT_BUFFER;
5490 /* fill the buffer with the form structures */
5491 for (i=0; i<numbuiltinforms; i++) {
5492 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5493 smb_io_form_1("", buffer, &forms_1[i], 0);
5495 for (; i<*numofforms; i++) {
5496 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5497 smb_io_form_1("", buffer, &forms_1[i], 0);
5502 if (*needed > offered) {
5504 return WERR_INSUFFICIENT_BUFFER;
5511 SAFE_FREE(builtinlist);
5512 return WERR_UNKNOWN_LEVEL;
5517 /****************************************************************************
5518 ****************************************************************************/
5520 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5522 /* POLICY_HND *handle = &q_u->handle; - notused. */
5523 uint32 level = q_u->level;
5524 UNISTR2 *uni_formname = &q_u->formname;
5525 NEW_BUFFER *buffer = NULL;
5526 uint32 offered = q_u->offered;
5527 uint32 *needed = &r_u->needed;
5529 nt_forms_struct *list=NULL;
5530 nt_forms_struct builtin_form;
5535 int numofforms=0, i=0;
5537 /* that's an [in out] buffer */
5538 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5539 buffer = r_u->buffer;
5541 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5543 DEBUG(4,("_spoolss_getform\n"));
5544 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5545 DEBUGADD(5,("Info level [%d]\n", level));
5547 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5548 if (!foundBuiltin) {
5549 numofforms = get_ntforms(&list);
5550 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5552 if (numofforms == 0)
5559 fill_form_1(&form_1, &builtin_form);
5562 /* Check if the requested name is in the list of form structures */
5563 for (i=0; i<numofforms; i++) {
5565 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5567 if (strequal(form_name, list[i].name)) {
5568 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5569 fill_form_1(&form_1, &list[i]);
5575 if (i == numofforms) {
5579 /* check the required size. */
5581 *needed=spoolss_size_form_1(&form_1);
5583 if (!alloc_buffer_size(buffer, buffer_size)){
5584 return WERR_INSUFFICIENT_BUFFER;
5587 if (*needed > offered) {
5588 return WERR_INSUFFICIENT_BUFFER;
5591 /* fill the buffer with the form structures */
5592 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5593 smb_io_form_1("", buffer, &form_1, 0);
5599 return WERR_UNKNOWN_LEVEL;
5603 /****************************************************************************
5604 ****************************************************************************/
5605 static void fill_port_1(PORT_INFO_1 *port, char *name)
5607 init_unistr(&port->port_name, name);
5610 /****************************************************************************
5611 ****************************************************************************/
5612 static void fill_port_2(PORT_INFO_2 *port, char *name)
5614 init_unistr(&port->port_name, name);
5615 init_unistr(&port->monitor_name, "Local Monitor");
5616 init_unistr(&port->description, "Local Port");
5617 #define PORT_TYPE_WRITE 1
5618 port->port_type=PORT_TYPE_WRITE;
5622 /****************************************************************************
5624 ****************************************************************************/
5625 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5627 PORT_INFO_1 *ports=NULL;
5630 if (*lp_enumports_cmd()) {
5631 char *cmd = lp_enumports_cmd();
5638 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5640 DEBUG(10,("Running [%s]\n", command));
5641 ret = smbrun(command, &fd);
5642 DEBUG(10,("Returned [%d]\n", ret));
5646 /* Is this the best error to return here? */
5647 return WERR_ACCESS_DENIED;
5651 qlines = fd_lines_load(fd, &numlines);
5652 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5656 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5657 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
5658 werror_str(WERR_NOMEM)));
5659 file_lines_free(qlines);
5663 for (i=0; i<numlines; i++) {
5664 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5665 fill_port_1(&ports[i], qlines[i]);
5668 file_lines_free(qlines);
5671 *returned = numlines;
5674 *returned = 1; /* Sole Samba port returned. */
5676 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5679 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5681 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5684 /* check the required size. */
5685 for (i=0; i<*returned; i++) {
5686 DEBUGADD(6,("adding port [%d]'s size\n", i));
5687 *needed += spoolss_size_port_info_1(&ports[i]);
5690 if (!alloc_buffer_size(buffer, *needed)) {
5692 return WERR_INSUFFICIENT_BUFFER;
5695 /* fill the buffer with the ports structures */
5696 for (i=0; i<*returned; i++) {
5697 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5698 smb_io_port_1("", buffer, &ports[i], 0);
5703 if (*needed > offered) {
5705 return WERR_INSUFFICIENT_BUFFER;
5711 /****************************************************************************
5713 ****************************************************************************/
5715 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5717 PORT_INFO_2 *ports=NULL;
5720 if (*lp_enumports_cmd()) {
5721 char *cmd = lp_enumports_cmd();
5730 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5731 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5733 path = lp_lockdir();
5735 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
5736 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5739 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5740 ret = smbrun(command, &fd);
5741 DEBUGADD(10,("returned [%d]\n", ret));
5745 /* Is this the best error to return here? */
5746 return WERR_ACCESS_DENIED;
5750 qlines = fd_lines_load(fd, &numlines);
5751 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5755 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5756 file_lines_free(qlines);
5760 for (i=0; i<numlines; i++) {
5761 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5762 fill_port_2(&(ports[i]), qlines[i]);
5765 file_lines_free(qlines);
5768 *returned = numlines;
5774 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5777 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5779 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5782 /* check the required size. */
5783 for (i=0; i<*returned; i++) {
5784 DEBUGADD(6,("adding port [%d]'s size\n", i));
5785 *needed += spoolss_size_port_info_2(&ports[i]);
5788 if (!alloc_buffer_size(buffer, *needed)) {
5790 return WERR_INSUFFICIENT_BUFFER;
5793 /* fill the buffer with the ports structures */
5794 for (i=0; i<*returned; i++) {
5795 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5796 smb_io_port_2("", buffer, &ports[i], 0);
5801 if (*needed > offered) {
5803 return WERR_INSUFFICIENT_BUFFER;
5809 /****************************************************************************
5811 ****************************************************************************/
5813 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5815 /* UNISTR2 *name = &q_u->name; - notused. */
5816 uint32 level = q_u->level;
5817 NEW_BUFFER *buffer = NULL;
5818 uint32 offered = q_u->offered;
5819 uint32 *needed = &r_u->needed;
5820 uint32 *returned = &r_u->returned;
5822 /* that's an [in out] buffer */
5823 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5824 buffer = r_u->buffer;
5826 DEBUG(4,("_spoolss_enumports\n"));
5833 return enumports_level_1(buffer, offered, needed, returned);
5835 return enumports_level_2(buffer, offered, needed, returned);
5837 return WERR_UNKNOWN_LEVEL;
5841 /****************************************************************************
5842 ****************************************************************************/
5843 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5844 const SPOOL_PRINTER_INFO_LEVEL *info,
5845 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
5846 uint32 user_switch, const SPOOL_USER_CTR *user,
5849 NT_PRINTER_INFO_LEVEL *printer = NULL;
5852 WERROR err = WERR_OK;
5854 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5855 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5859 ZERO_STRUCTP(printer);
5861 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5862 if (!convert_printer_info(info, printer, 2)) {
5863 free_a_printer(&printer, 2);
5867 /* check to see if the printer already exists */
5869 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
5870 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
5871 printer->info_2->sharename));
5872 free_a_printer(&printer, 2);
5873 return WERR_PRINTER_ALREADY_EXISTS;
5876 if (*lp_addprinter_cmd() )
5877 if ( !add_printer_hook(printer) ) {
5878 free_a_printer(&printer,2);
5879 return WERR_ACCESS_DENIED;
5882 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
5883 printer->info_2->sharename);
5885 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5886 free_a_printer(&printer,2);
5887 return WERR_ACCESS_DENIED;
5890 /* you must be a printer admin to add a new printer */
5891 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5892 free_a_printer(&printer,2);
5893 return WERR_ACCESS_DENIED;
5897 * Do sanity check on the requested changes for Samba.
5900 if (!check_printer_ok(printer->info_2, snum)) {
5901 free_a_printer(&printer,2);
5902 return WERR_INVALID_PARAM;
5906 * When a printer is created, the drivername bound to the printer is used
5907 * to lookup previously saved driver initialization info, which is then
5908 * bound to the new printer, simulating what happens in the Windows arch.
5910 set_driver_init(printer, 2);
5912 /* write the ASCII on disk */
5913 err = mod_a_printer(*printer, 2);
5914 if (!W_ERROR_IS_OK(err)) {
5915 free_a_printer(&printer,2);
5919 if (!open_printer_hnd(p, handle, name)) {
5920 /* Handle open failed - remove addition. */
5921 del_a_printer(printer->info_2->sharename);
5922 free_a_printer(&printer,2);
5923 return WERR_ACCESS_DENIED;
5926 free_a_printer(&printer,2);
5928 srv_spoolss_sendnotify(p, handle);
5933 /****************************************************************************
5934 ****************************************************************************/
5936 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5938 UNISTR2 *uni_srv_name = &q_u->server_name;
5939 uint32 level = q_u->level;
5940 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5941 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
5942 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
5943 uint32 user_switch = q_u->user_switch;
5944 SPOOL_USER_CTR *user = &q_u->user_ctr;
5945 POLICY_HND *handle = &r_u->handle;
5949 /* we don't handle yet */
5950 /* but I know what to do ... */
5951 return WERR_UNKNOWN_LEVEL;
5953 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5955 user_switch, user, handle);
5957 return WERR_UNKNOWN_LEVEL;
5961 /****************************************************************************
5962 ****************************************************************************/
5964 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5966 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5967 uint32 level = q_u->level;
5968 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5969 WERROR err = WERR_OK;
5970 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5971 struct current_user user;
5973 ZERO_STRUCT(driver);
5975 get_current_user(&user, p);
5977 if (!convert_printer_driver_info(info, &driver, level)) {
5982 DEBUG(5,("Cleaning driver's information\n"));
5983 err = clean_up_driver_struct(driver, level, &user);
5984 if (!W_ERROR_IS_OK(err))
5987 DEBUG(5,("Moving driver to final destination\n"));
5988 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5989 if (W_ERROR_IS_OK(err))
5990 err = WERR_ACCESS_DENIED;
5994 if (add_a_printer_driver(driver, level)!=0) {
5995 err = WERR_ACCESS_DENIED;
6000 free_a_printer_driver(driver, level);
6004 /****************************************************************************
6005 ****************************************************************************/
6006 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6008 init_unistr(&info->name, name);
6011 /****************************************************************************
6012 ****************************************************************************/
6013 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6017 pstring short_archi;
6018 DRIVER_DIRECTORY_1 *info=NULL;
6020 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6022 if (get_short_archi(short_archi, long_archi)==False)
6023 return WERR_INVALID_ENVIRONMENT;
6025 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6028 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6030 DEBUG(4,("printer driver directory: [%s]\n", path));
6032 fill_driverdir_1(info, path);
6034 *needed += spoolss_size_driverdir_info_1(info);
6036 if (!alloc_buffer_size(buffer, *needed)) {
6038 return WERR_INSUFFICIENT_BUFFER;
6041 smb_io_driverdir_1("", buffer, info, 0);
6045 if (*needed > offered)
6046 return WERR_INSUFFICIENT_BUFFER;
6051 /****************************************************************************
6052 ****************************************************************************/
6054 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6056 UNISTR2 *name = &q_u->name;
6057 UNISTR2 *uni_environment = &q_u->environment;
6058 uint32 level = q_u->level;
6059 NEW_BUFFER *buffer = NULL;
6060 uint32 offered = q_u->offered;
6061 uint32 *needed = &r_u->needed;
6063 /* that's an [in out] buffer */
6064 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6065 buffer = r_u->buffer;
6067 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6073 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6075 return WERR_UNKNOWN_LEVEL;
6079 /****************************************************************************
6080 ****************************************************************************/
6082 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6084 POLICY_HND *handle = &q_u->handle;
6085 uint32 idx = q_u->index;
6086 uint32 in_value_len = q_u->valuesize;
6087 uint32 in_data_len = q_u->datasize;
6088 uint32 *out_max_value_len = &r_u->valuesize;
6089 uint16 **out_value = &r_u->value;
6090 uint32 *out_value_len = &r_u->realvaluesize;
6091 uint32 *out_type = &r_u->type;
6092 uint32 *out_max_data_len = &r_u->datasize;
6093 uint8 **data_out = &r_u->data;
6094 uint32 *out_data_len = &r_u->realdatasize;
6096 NT_PRINTER_INFO_LEVEL *printer = NULL;
6101 uint32 biggest_valuesize;
6102 uint32 biggest_datasize;
6104 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6110 ZERO_STRUCT(printer);
6114 *out_max_data_len=0;
6118 DEBUG(5,("spoolss_enumprinterdata\n"));
6121 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6125 if (!get_printer_snum(p,handle, &snum))
6128 result = get_a_printer(&printer, 2, lp_servicename(snum));
6129 if (!W_ERROR_IS_OK(result))
6133 * The NT machine wants to know the biggest size of value and data
6135 * cf: MSDN EnumPrinterData remark section
6137 if ( (in_value_len==0) && (in_data_len==0) ) {
6138 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6142 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6143 * if this parameter size doesn't exist.
6144 * Ok - my opinion here is that the client is not asking for the greatest
6145 * possible size of all the parameters, but is asking specifically for the size needed
6146 * for this specific parameter. In that case we can remove the loop below and
6147 * simplify this lookup code considerably. JF - comments welcome. JRA.
6150 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6152 free_a_printer(&printer, 2);
6153 return WERR_NO_MORE_ITEMS;
6160 biggest_valuesize=0;
6163 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6164 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6165 if (data_len > biggest_datasize) biggest_datasize=data_len;
6167 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6173 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6174 *out_value_len=2*(1+biggest_valuesize);
6175 *out_data_len=biggest_datasize;
6177 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6179 free_a_printer(&printer, 2);
6184 * the value len is wrong in NT sp3
6185 * that's the number of bytes not the number of unicode chars
6188 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6191 free_a_printer(&printer, 2);
6193 /* out_value should default to "" or else NT4 has
6194 problems unmarshalling the response */
6196 *out_max_value_len=(in_value_len/sizeof(uint16));
6197 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL)
6200 ZERO_STRUCTP(*out_value);
6201 *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
6203 /* the data is counted in bytes */
6204 *out_max_data_len = in_data_len;
6205 *out_data_len = in_data_len;
6206 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL)
6209 memset(*data_out,'\0',in_data_len);
6211 return WERR_NO_MORE_ITEMS;
6214 free_a_printer(&printer, 2);
6218 * - counted in bytes in the request
6219 * - counted in UNICODE chars in the max reply
6220 * - counted in bytes in the real size
6222 * take a pause *before* coding not *during* coding
6225 *out_max_value_len=(in_value_len/sizeof(uint16));
6226 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6231 *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6235 /* the data is counted in bytes */
6236 *out_max_data_len=in_data_len;
6237 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6242 memcpy(*data_out, data, (size_t)data_len);
6243 *out_data_len=data_len;
6250 /****************************************************************************
6251 ****************************************************************************/
6253 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6255 POLICY_HND *handle = &q_u->handle;
6256 UNISTR2 *value = &q_u->value;
6257 uint32 type = q_u->type;
6258 /* uint32 max_len = q_u->max_len; - notused. */
6259 uint8 *data = q_u->data;
6260 uint32 real_len = q_u->real_len;
6261 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6263 NT_PRINTER_INFO_LEVEL *printer = NULL;
6264 NT_PRINTER_PARAM *param = NULL, old_param;
6266 WERROR status = WERR_OK;
6267 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6269 DEBUG(5,("spoolss_setprinterdata\n"));
6272 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6276 if (!get_printer_snum(p,handle, &snum))
6279 ZERO_STRUCT(old_param);
6282 * Access check : NT returns "access denied" if you make a
6283 * SetPrinterData call without the necessary privildge.
6284 * we were originally returning OK if nothing changed
6285 * which made Win2k issue **a lot** of SetPrinterData
6286 * when connecting to a printer --jerry
6289 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6290 DEBUG(3, ("security descriptor change denied by existing "
6291 "security descriptor\n"));
6292 status = WERR_ACCESS_DENIED;
6296 /* Check if we are making any changes or not. Return true if
6297 nothing is actually changing. This is not needed anymore but
6298 has been left in as an optimization to keep from from
6299 writing to disk as often --jerry */
6301 status = get_a_printer(&printer, 2, lp_servicename(snum));
6302 if (!W_ERROR_IS_OK(status))
6305 convert_specific_param(¶m, value , type, data, real_len);
6308 if (get_specific_param(*printer, 2, param->value, &old_param.data,
6309 &old_param.type, (uint32 *)&old_param.data_len)) {
6311 if (param->type == old_param.type &&
6312 param->data_len == old_param.data_len &&
6313 memcmp(param->data, old_param.data,
6314 old_param.data_len) == 0) {
6316 DEBUG(3, ("setprinterdata hasn't changed\n"));
6323 unlink_specific_param_if_exist(printer->info_2, param);
6326 * When client side code sets a magic printer data key, detect it and save
6327 * the current printer data and the magic key's data (its the DEVMODE) for
6328 * future printer/driver initializations.
6330 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6332 * Set devmode and printer initialization info
6334 status = save_driver_init(printer, 2, param);
6337 add_a_specific_param(printer->info_2, ¶m);
6338 status = mod_a_printer(*printer, 2);
6342 free_a_printer(&printer, 2);
6344 free_nt_printer_param(¶m);
6345 SAFE_FREE(old_param.data);
6350 /****************************************************************************
6351 ****************************************************************************/
6353 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6355 POLICY_HND *handle = &q_u->handle;
6356 UNISTR2 *value = &q_u->valuename;
6358 NT_PRINTER_INFO_LEVEL *printer = NULL;
6359 NT_PRINTER_PARAM param;
6361 WERROR status = WERR_OK;
6362 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6364 DEBUG(5,("spoolss_deleteprinterdata\n"));
6367 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6371 if (!get_printer_snum(p, handle, &snum))
6374 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6375 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6376 "change denied by existing security descriptor\n"));
6377 return WERR_ACCESS_DENIED;
6380 status = get_a_printer(&printer, 2, lp_servicename(snum));
6381 if (!W_ERROR_IS_OK(status))
6384 ZERO_STRUCTP(¶m);
6385 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6387 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
6388 status = WERR_INVALID_PARAM;
6390 status = mod_a_printer(*printer, 2);
6392 free_a_printer(&printer, 2);
6396 /****************************************************************************
6397 ****************************************************************************/
6399 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6401 POLICY_HND *handle = &q_u->handle;
6402 /* uint32 level = q_u->level; - notused. */
6403 FORM *form = &q_u->form;
6404 nt_forms_struct tmpForm;
6407 nt_forms_struct *list=NULL;
6408 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6410 DEBUG(5,("spoolss_addform\n"));
6413 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6418 * FIXME!! Feels like there should be an access check here, but haven't
6419 * had time to verify. --jerry
6422 /* can't add if builtin */
6423 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6424 return WERR_INVALID_PARAM;
6427 count=get_ntforms(&list);
6428 if(!add_a_form(&list, form, &count))
6430 write_ntforms(&list, count);
6437 /****************************************************************************
6438 ****************************************************************************/
6440 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6442 POLICY_HND *handle = &q_u->handle;
6443 UNISTR2 *form_name = &q_u->name;
6444 nt_forms_struct tmpForm;
6446 WERROR ret = WERR_OK;
6447 nt_forms_struct *list=NULL;
6448 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6450 DEBUG(5,("spoolss_deleteform\n"));
6453 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6457 /* can't delete if builtin */
6458 if (get_a_builtin_ntform(form_name,&tmpForm)) {
6459 return WERR_INVALID_PARAM;
6462 count = get_ntforms(&list);
6463 if(!delete_a_form(&list, form_name, &count, &ret))
6464 return WERR_INVALID_PARAM;
6471 /****************************************************************************
6472 ****************************************************************************/
6474 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6476 POLICY_HND *handle = &q_u->handle;
6477 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6478 /* uint32 level = q_u->level; - notused. */
6479 FORM *form = &q_u->form;
6480 nt_forms_struct tmpForm;
6483 nt_forms_struct *list=NULL;
6484 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6486 DEBUG(5,("spoolss_setform\n"));
6489 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6492 /* can't set if builtin */
6493 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6494 return WERR_INVALID_PARAM;
6497 count=get_ntforms(&list);
6498 update_a_form(&list, form, count);
6499 write_ntforms(&list, count);
6506 /****************************************************************************
6507 enumprintprocessors level 1.
6508 ****************************************************************************/
6509 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6511 PRINTPROCESSOR_1 *info_1=NULL;
6513 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6518 init_unistr(&info_1->name, "winprint");
6520 *needed += spoolss_size_printprocessor_info_1(info_1);
6522 if (!alloc_buffer_size(buffer, *needed))
6523 return WERR_INSUFFICIENT_BUFFER;
6525 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6529 if (*needed > offered) {
6531 return WERR_INSUFFICIENT_BUFFER;
6537 /****************************************************************************
6538 ****************************************************************************/
6540 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6542 /* UNISTR2 *name = &q_u->name; - notused. */
6543 /* UNISTR2 *environment = &q_u->environment; - notused. */
6544 uint32 level = q_u->level;
6545 NEW_BUFFER *buffer = NULL;
6546 uint32 offered = q_u->offered;
6547 uint32 *needed = &r_u->needed;
6548 uint32 *returned = &r_u->returned;
6550 /* that's an [in out] buffer */
6551 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6552 buffer = r_u->buffer;
6554 DEBUG(5,("spoolss_enumprintprocessors\n"));
6557 * Enumerate the print processors ...
6559 * Just reply with "winprint", to keep NT happy
6560 * and I can use my nice printer checker.
6568 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6570 return WERR_UNKNOWN_LEVEL;
6574 /****************************************************************************
6575 enumprintprocdatatypes level 1.
6576 ****************************************************************************/
6577 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6579 PRINTPROCDATATYPE_1 *info_1=NULL;
6581 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6586 init_unistr(&info_1->name, "RAW");
6588 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6590 if (!alloc_buffer_size(buffer, *needed))
6591 return WERR_INSUFFICIENT_BUFFER;
6593 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6597 if (*needed > offered) {
6599 return WERR_INSUFFICIENT_BUFFER;
6605 /****************************************************************************
6606 ****************************************************************************/
6608 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6610 /* UNISTR2 *name = &q_u->name; - notused. */
6611 /* UNISTR2 *processor = &q_u->processor; - notused. */
6612 uint32 level = q_u->level;
6613 NEW_BUFFER *buffer = NULL;
6614 uint32 offered = q_u->offered;
6615 uint32 *needed = &r_u->needed;
6616 uint32 *returned = &r_u->returned;
6618 /* that's an [in out] buffer */
6619 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6620 buffer = r_u->buffer;
6622 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6629 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6631 return WERR_UNKNOWN_LEVEL;
6635 /****************************************************************************
6636 enumprintmonitors level 1.
6637 ****************************************************************************/
6639 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6641 PRINTMONITOR_1 *info_1=NULL;
6643 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6648 init_unistr(&info_1->name, "Local Port");
6650 *needed += spoolss_size_printmonitor_info_1(info_1);
6652 if (!alloc_buffer_size(buffer, *needed))
6653 return WERR_INSUFFICIENT_BUFFER;
6655 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6659 if (*needed > offered) {
6661 return WERR_INSUFFICIENT_BUFFER;
6667 /****************************************************************************
6668 enumprintmonitors level 2.
6669 ****************************************************************************/
6670 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6672 PRINTMONITOR_2 *info_2=NULL;
6674 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6679 init_unistr(&info_2->name, "Local Port");
6680 init_unistr(&info_2->environment, "Windows NT X86");
6681 init_unistr(&info_2->dll_name, "localmon.dll");
6683 *needed += spoolss_size_printmonitor_info_2(info_2);
6685 if (!alloc_buffer_size(buffer, *needed))
6686 return WERR_INSUFFICIENT_BUFFER;
6688 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6692 if (*needed > offered) {
6694 return WERR_INSUFFICIENT_BUFFER;
6700 /****************************************************************************
6701 ****************************************************************************/
6703 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6705 /* UNISTR2 *name = &q_u->name; - notused. */
6706 uint32 level = q_u->level;
6707 NEW_BUFFER *buffer = NULL;
6708 uint32 offered = q_u->offered;
6709 uint32 *needed = &r_u->needed;
6710 uint32 *returned = &r_u->returned;
6712 /* that's an [in out] buffer */
6713 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6714 buffer = r_u->buffer;
6716 DEBUG(5,("spoolss_enumprintmonitors\n"));
6719 * Enumerate the print monitors ...
6721 * Just reply with "Local Port", to keep NT happy
6722 * and I can use my nice printer checker.
6730 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6732 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6734 return WERR_UNKNOWN_LEVEL;
6738 /****************************************************************************
6739 ****************************************************************************/
6740 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6744 JOB_INFO_1 *info_1=NULL;
6746 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6748 if (info_1 == NULL) {
6753 for (i=0; i<count && found==False; i++) {
6754 if (queue[i].job==(int)jobid)
6761 /* NT treats not found as bad param... yet another bad choice */
6762 return WERR_INVALID_PARAM;
6765 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6769 *needed += spoolss_size_job_info_1(info_1);
6771 if (!alloc_buffer_size(buffer, *needed)) {
6773 return WERR_INSUFFICIENT_BUFFER;
6776 smb_io_job_info_1("", buffer, info_1, 0);
6780 if (*needed > offered)
6781 return WERR_INSUFFICIENT_BUFFER;
6787 /****************************************************************************
6788 ****************************************************************************/
6789 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6794 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6797 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6799 ZERO_STRUCTP(info_2);
6801 if (info_2 == NULL) {
6806 for (i=0; i<count && found==False; i++) {
6807 if (queue[i].job==(int)jobid)
6814 /* NT treats not found as bad param... yet another bad choice */
6815 return WERR_INVALID_PARAM;
6818 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6819 if (!W_ERROR_IS_OK(ret)) {
6824 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6826 free_a_printer(&ntprinter, 2);
6829 *needed += spoolss_size_job_info_2(info_2);
6831 if (!alloc_buffer_size(buffer, *needed)) {
6833 return WERR_INSUFFICIENT_BUFFER;
6836 smb_io_job_info_2("", buffer, info_2, 0);
6838 free_job_info_2(info_2);
6841 if (*needed > offered)
6842 return WERR_INSUFFICIENT_BUFFER;
6847 /****************************************************************************
6848 ****************************************************************************/
6850 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6852 POLICY_HND *handle = &q_u->handle;
6853 uint32 jobid = q_u->jobid;
6854 uint32 level = q_u->level;
6855 NEW_BUFFER *buffer = NULL;
6856 uint32 offered = q_u->offered;
6857 uint32 *needed = &r_u->needed;
6861 print_queue_struct *queue=NULL;
6862 print_status_struct prt_status;
6864 /* that's an [in out] buffer */
6865 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6866 buffer = r_u->buffer;
6868 DEBUG(5,("spoolss_getjob\n"));
6872 if (!get_printer_snum(p, handle, &snum))
6875 count = print_queue_status(snum, &queue, &prt_status);
6877 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6878 count, prt_status.status, prt_status.message));
6882 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6884 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6887 return WERR_UNKNOWN_LEVEL;
6891 /********************************************************************
6892 * spoolss_getprinterdataex
6893 ********************************************************************/
6895 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
6897 POLICY_HND *handle = &q_u->handle;
6898 uint32 in_size = q_u->size;
6899 uint32 *type = &r_u->type;
6900 uint32 *out_size = &r_u->size;
6901 uint8 **data = &r_u->data;
6902 uint32 *needed = &r_u->needed;
6905 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6908 DEBUG(4,("_spoolss_getprinterdataex\n"));
6910 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
6911 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
6913 /* in case of problem, return some default values */
6920 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
6922 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6927 /* Is the handle to a printer or to the server? */
6929 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6931 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
6932 return WERR_INVALID_PARAM;
6937 * From MSDN documentation of GetPrinterDataEx: pass request
6938 * to GetPrinterData if key is "PrinterDriverData". This is
6939 * the only key we really support. Other keys to implement:
6945 if (strcmp(key, "PrinterDriverData") != 0)
6946 return WERR_INVALID_PARAM;
6948 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
6949 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
6950 type, data, needed, in_size);
6955 DEBUG(5, ("value not found, allocating %d\n", *out_size));
6957 /* reply this param doesn't exist */
6959 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
6965 return WERR_INVALID_PARAM;
6968 if (*needed > *out_size)
6969 return WERR_MORE_DATA;
6974 /********************************************************************
6975 * spoolss_setprinterdata
6976 ********************************************************************/
6978 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
6980 SPOOL_Q_SETPRINTERDATA q_u_local;
6981 SPOOL_R_SETPRINTERDATA r_u_local;
6984 DEBUG(4,("_spoolss_setprinterdataex\n"));
6986 /* From MSDN documentation of SetPrinterDataEx: pass request to
6987 SetPrinterData if key is "PrinterDriverData" */
6989 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6991 if (strcmp(key, "PrinterDriverData") == 0)
6992 return WERR_INVALID_PARAM;
6994 ZERO_STRUCT(q_u_local);
6995 ZERO_STRUCT(r_u_local);
6997 /* make a copy to call _spoolss_setprinterdata() */
6999 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7000 copy_unistr2(&q_u_local.value, &q_u->value);
7001 q_u_local.type = q_u->type;
7002 q_u_local.max_len = q_u->max_len;
7003 q_u_local.data = q_u->data;
7004 q_u_local.real_len = q_u->real_len;
7005 q_u_local.numeric_data = q_u->numeric_data;
7007 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
7010 /********************************************************************
7011 * spoolss_enumprinterkey
7012 ********************************************************************/
7014 /* constants for EnumPrinterKey() */
7015 #define ENUMERATED_KEY_SIZE 19
7017 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
7020 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
7023 char *PrinterKey = "PrinterDriverData";
7025 DEBUG(4,("_spoolss_enumprinterkey\n"));
7027 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7030 * we only support enumating all keys (key == "")
7031 * Of course, the only key we support is the "PrinterDriverData"
7034 if (strlen(key) == 0)
7036 r_u->needed = ENUMERATED_KEY_SIZE *2;
7037 if (q_u->size < r_u->needed)
7038 return WERR_MORE_DATA;
7041 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
7043 enumkeys[i] = (uint16)(*ptr);
7047 /* tag of with 2 '\0's */
7048 enumkeys[i++] = '\0';
7051 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
7052 return WERR_BADFILE;
7057 /* The "PrinterDriverData" key should have no subkeys */
7058 if (strcmp(key, PrinterKey) == 0)
7061 if (q_u->size < r_u->needed)
7062 return WERR_MORE_DATA;
7064 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
7065 return WERR_BADFILE;
7071 /* The return value for an unknown key is documented in MSDN
7072 EnumPrinterKey description */
7073 return WERR_BADFILE;
7076 /********************************************************************
7077 * spoolss_enumprinterdataex
7078 ********************************************************************/
7080 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
7082 POLICY_HND *handle = &q_u->handle;
7083 uint32 in_size = q_u->size;
7086 NT_PRINTER_INFO_LEVEL *printer = NULL;
7087 PRINTER_ENUM_VALUES *enum_values = NULL;
7089 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7098 DEBUG(4,("_spoolss_enumprinterdataex\n"));
7101 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
7107 * The only key we support is "PrinterDriverData". This should return
7108 > an array of all the key/value pairs returned by EnumPrinterDataSee
7109 * _spoolss_getprinterdataex() for details --jerry
7112 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7113 if (strcmp(key, "PrinterDriverData") != 0)
7115 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
7116 return WERR_INVALID_PARAM;
7120 if (!get_printer_snum(p,handle, &snum))
7123 ZERO_STRUCT(printer);
7124 result = get_a_printer(&printer, 2, lp_servicename(snum));
7125 if (!W_ERROR_IS_OK(result))
7130 * loop through all params and build the array to pass
7131 * back to the client
7138 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
7140 PRINTER_ENUM_VALUES *ptr;
7143 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7145 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7147 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7148 result = WERR_NOMEM;
7154 init_unistr(&enum_values[num_entries].valuename, value);
7155 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7156 enum_values[num_entries].type = type;
7159 * NULL terminate REG_SZ
7160 * FIXME!!! We should not be correctly problems in the way
7161 * we store PrinterData here. Need to investogate
7162 * SetPrinterData[Ex] --jerry
7165 if (type == REG_SZ) {
7166 /* fix alignment if the string was stored
7167 in a bizarre fashion */
7168 if ((data_len % 2) == 0)
7171 add_len = data_len % 2;
7174 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7175 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7176 result = WERR_NOMEM;
7179 memcpy(enum_values[num_entries].data, data, data_len);
7180 enum_values[num_entries].data_len = data_len + add_len;
7182 /* keep track of the size of the array in bytes */
7184 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7190 r_u->needed = needed;
7191 r_u->returned = num_entries;
7193 if (needed > in_size) {
7194 result = WERR_MORE_DATA;
7198 /* copy data into the reply */
7200 r_u->ctr.size = r_u->needed;
7201 r_u->ctr.size_of_array = r_u->returned;
7202 r_u->ctr.values = enum_values;
7207 free_a_printer(&printer, 2);
7212 /****************************************************************************
7213 ****************************************************************************/
7215 /* Disabled because it doesn't fix the bug I am looking at but it would be
7216 a shame to throw away the code. -tpot */
7220 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
7222 init_unistr(&info->name, name);
7225 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
7226 UNISTR2 *environment,
7233 pstring short_archi;
7234 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
7236 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
7238 if (get_short_archi(short_archi, long_archi)==False)
7239 return WERR_INVALID_ENVIRONMENT;
7241 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
7244 /* Not sure what to return here - are UNC names valid here?.
7245 Windows returns the string: C:\WINNT\System32\spool\PRTPROCS\W32X86
7246 which is pretty bogus for a RPC. */
7248 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7250 DEBUG(4,("print processor directory: [%s]\n", path));
7252 fill_printprocessordirectory_1(info, path);
7254 *needed += spoolss_size_printprocessordirectory_info_1(info);
7256 if (!alloc_buffer_size(buffer, *needed)) {
7258 return WERR_INSUFFICIENT_BUFFER;
7261 smb_io_printprocessordirectory_1("", buffer, info, 0);
7265 if (*needed > offered)
7266 return WERR_INSUFFICIENT_BUFFER;
7271 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
7273 uint32 level = q_u->level;
7274 NEW_BUFFER *buffer = NULL;
7275 uint32 offered = q_u->offered;
7276 uint32 *needed = &r_u->needed;
7278 /* that's an [in out] buffer */
7279 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7280 buffer = r_u->buffer;
7282 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7288 return getprintprocessordirectory_level_1
7289 (&q_u->name, &q_u->environment, buffer, offered, needed);
7291 return WERR_UNKNOWN_LEVEL;
7294 return WERR_ACCESS_DENIED;