3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-2000,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
8 * Copyright (C) Jean François Micouleau 1998-2000.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int DEBUGLEVEL;
28 extern pstring global_myname;
30 #ifndef MAX_OPEN_PRINTER_EXS
31 #define MAX_OPEN_PRINTER_EXS 50
34 #define PRINTER_HANDLE_IS_PRINTER 0
35 #define PRINTER_HANDLE_IS_PRINTSERVER 1
37 /* structure to store the printer handles */
38 /* and a reference to what it's pointing to */
39 /* and the notify info asked about */
40 /* that's the central struct */
41 typedef struct _Printer{
46 BOOL document_started;
48 int jobid; /* jobid in printing backend */
49 POLICY_HND printer_hnd;
53 fstring printerservername;
62 SPOOL_NOTIFY_OPTION *option;
63 POLICY_HND client_hnd;
64 uint32 client_connected;
72 typedef struct _counter_printer_0 {
80 static ubi_dlList Printer_list;
81 static ubi_dlList counter_list;
83 static struct cli_state cli;
84 static uint32 smb_connections=0;
86 #define OPEN_HANDLE(pnum) ((pnum!=NULL) && (pnum->open!=False) && (IVAL(pnum->printer_hnd.data,16)==(uint32)sys_getpid()))
87 #define OUR_HANDLE(pnum) ((pnum==NULL)?"NULL":(IVAL(pnum->data,16)==sys_getpid()?"OURS":"OTHER"))
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
96 return JOB_STATUS_PAUSED;
98 return JOB_STATUS_SPOOLING;
100 return JOB_STATUS_PRINTING;
102 return JOB_STATUS_ERROR;
104 return JOB_STATUS_DELETING;
106 return JOB_STATUS_OFFLINE;
108 return JOB_STATUS_PAPEROUT;
110 return JOB_STATUS_PRINTED;
112 return JOB_STATUS_DELETED;
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
121 static int nt_printq_status(int v)
125 return PRINTER_STATUS_PAUSED;
134 /****************************************************************************
135 initialise printer handle states...
136 ****************************************************************************/
137 void init_printer_hnd(void)
139 ubi_dlInitList(&Printer_list);
140 ubi_dlInitList(&counter_list);
143 /****************************************************************************
144 Return a user struct for a pipe user.
145 ****************************************************************************/
147 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
149 if (p->ntlmssp_auth_validated) {
150 memcpy(user, &p->pipe_user, sizeof(struct current_user));
152 extern struct current_user current_user;
153 memcpy(user, ¤t_user, sizeof(struct current_user));
159 /****************************************************************************
160 create a unique printer handle
161 ****************************************************************************/
162 static void create_printer_hnd(POLICY_HND *hnd)
164 static uint32 prt_hnd_low = 0;
165 static uint32 prt_hnd_high = 0;
167 if (hnd == NULL) return;
169 /* i severely doubt that prt_hnd_high will ever be non-zero... */
171 if (prt_hnd_low == 0) prt_hnd_high++;
173 SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */
174 SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */
175 SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */
176 SIVAL(hnd->data, 12, time(NULL)); /* something random */
177 SIVAL(hnd->data, 16, sys_getpid()); /* something more random */
180 /****************************************************************************
181 find printer index by handle
182 ****************************************************************************/
183 static Printer_entry *find_printer_index_by_hnd(const POLICY_HND *hnd)
185 Printer_entry *find_printer;
187 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
189 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
191 if (memcmp(&(find_printer->printer_hnd), hnd, sizeof(*hnd)) == 0) {
192 DEBUG(4,("Found printer handle \n"));
193 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
198 DEBUG(3,("Whoops, Printer handle not found: "));
199 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
203 /****************************************************************************
205 ****************************************************************************/
206 static void clear_handle(POLICY_HND *hnd)
211 /***************************************************************************
212 Disconnect from the client
213 ****************************************************************************/
214 static BOOL srv_spoolss_replycloseprinter(POLICY_HND *handle)
218 /* weird if the test succeds !!! */
219 if (smb_connections==0) {
220 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
224 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
227 /* if it's the last connection, deconnect the IPC$ share */
228 if (smb_connections==1) {
229 if(!spoolss_disconnect_from_client(&cli))
232 message_deregister(MSG_PRINTER_NOTIFY);
240 /****************************************************************************
241 close printer index by handle
242 ****************************************************************************/
243 static BOOL close_printer_handle(POLICY_HND *hnd)
245 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
247 if (!OPEN_HANDLE(Printer)) {
248 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
252 if (Printer->notify.client_connected==True)
253 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
254 return ERROR_INVALID_HANDLE;
257 Printer->notify.flags=0;
258 Printer->notify.options=0;
259 Printer->notify.localmachine[0]='\0';
260 Printer->notify.printerlocal=0;
261 safe_free(Printer->notify.option);
262 Printer->notify.option=NULL;
263 Printer->notify.client_connected=False;
267 ubi_dlRemThis(&Printer_list, Printer);
274 /****************************************************************************
275 delete a printer given a handle
276 ****************************************************************************/
277 static uint32 delete_printer_handle(POLICY_HND *hnd)
279 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
281 if (!OPEN_HANDLE(Printer)) {
282 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
283 return ERROR_INVALID_HANDLE;
286 if (del_a_printer(Printer->dev.handlename) != 0) {
287 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
288 return ERROR_INVALID_HANDLE;
291 /* Check calling user has permission to delete printer. Note that
292 since we set the snum parameter to -1 only administrators can
293 delete the printer. This stops people with the Full Control
294 permission from deleting the printer. */
296 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
297 DEBUG(3, ("printer delete denied by security descriptor\n"));
298 return ERROR_ACCESS_DENIED;
301 if (*lp_deleteprinter_cmd()) {
303 pid_t local_pid = sys_getpid();
304 char *cmd = lp_deleteprinter_cmd();
311 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
312 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
316 /* Printer->dev.handlename equals portname equals sharename */
317 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
318 Printer->dev.handlename);
319 dos_to_unix(command, True); /* Convert printername to unix-codepage */
320 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
323 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
324 ret = smbrun(command, tmp_file, False);
327 return ERROR_INVALID_HANDLE; /* What to return here? */
329 DEBUGADD(10,("returned [%d]\n", ret));
330 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
333 /* Send SIGHUP to process group... is there a better way? */
336 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
338 return ERROR_SUCCESS;
340 return ERROR_ACCESS_DENIED;
343 return ERROR_SUCCESS;
346 /****************************************************************************
347 return the snum of a printer corresponding to an handle
348 ****************************************************************************/
349 static BOOL get_printer_snum(POLICY_HND *hnd, int *number)
351 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
353 if (!OPEN_HANDLE(Printer)) {
354 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
358 switch (Printer->printer_type) {
359 case PRINTER_HANDLE_IS_PRINTER:
360 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
361 *number = print_queue_snum(Printer->dev.handlename);
362 return (*number != -1);
363 case PRINTER_HANDLE_IS_PRINTSERVER:
370 /****************************************************************************
371 set printer handle type.
372 ****************************************************************************/
373 static BOOL set_printer_hnd_accesstype(POLICY_HND *hnd, uint32 access_required)
375 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
377 if (!OPEN_HANDLE(Printer)) {
378 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
382 DEBUG(4,("Setting printer access=%x\n", access_required));
383 Printer->access = access_required;
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
392 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
394 DEBUG(3,("Setting printer type=%s\n", handlename));
396 if ( strlen(handlename) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
401 /* it's a print server */
402 if (!strchr(handlename+2, '\\')) {
403 DEBUGADD(4,("Printer is a print server\n"));
404 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
408 DEBUGADD(4,("Printer is a printer\n"));
409 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
415 /****************************************************************************
416 Set printer handle name.
417 ****************************************************************************/
419 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
421 NT_PRINTER_INFO_LEVEL *printer = NULL;
423 int n_services=lp_numservices();
427 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
429 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
430 ZERO_STRUCT(Printer->dev.printerservername);
431 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
435 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
438 aprinter=strchr(handlename+2, '\\');
441 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
444 * store the Samba share name in it
445 * in back we have the long printer name
446 * need to iterate all the snum and do a
447 * get_a_printer each time to find the printer
448 * faster to do it here than later.
451 for (snum=0;snum<n_services && found==False;snum++) {
454 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
457 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
459 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
462 printername=strchr(printer->info_2->printername+2, '\\');
465 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
466 printer->info_2->printername, aprinter ));
468 if ( strlen(printername) != strlen(aprinter) ) {
469 free_a_printer(&printer, 2);
473 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
474 free_a_printer(&printer, 2);
482 * if we haven't found a printer with the given handlename
483 * then it can be a share name as you can open both \\server\printer and
488 * we still check if the printer description file exists as NT won't be happy
489 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
493 DEBUGADD(5,("Printer not found, checking for share now\n"));
495 for (snum=0;snum<n_services && found==False;snum++) {
497 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
500 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
502 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
505 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
506 printer->info_2->printername, aprinter ));
508 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
509 free_a_printer(&printer, 2);
513 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
514 free_a_printer(&printer, 2);
523 DEBUGADD(4,("Printer not found\n"));
528 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
529 printer->info_2->printername, lp_servicename(snum),snum));
531 ZERO_STRUCT(Printer->dev.handlename);
532 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
534 free_a_printer(&printer, 2);
539 /****************************************************************************
540 find first available printer slot. creates a printer handle for you.
541 ****************************************************************************/
543 static BOOL open_printer_hnd(POLICY_HND *hnd, char *name)
545 Printer_entry *new_printer;
547 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
549 create_printer_hnd(hnd);
551 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
554 ZERO_STRUCTP(new_printer);
556 new_printer->open = True;
557 new_printer->notify.option=NULL;
559 memcpy(&new_printer->printer_hnd, hnd, sizeof(*hnd));
561 ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
563 if (!set_printer_hnd_printertype(new_printer, name)) {
564 close_printer_handle(hnd);
568 if (!set_printer_hnd_name(new_printer, name)) {
569 close_printer_handle(hnd);
573 DEBUG(5, ("%d printer handles active\n",
574 (int)ubi_dlCount(&Printer_list)));
579 /********************************************************************
580 Return True is the handle is a print server.
581 ********************************************************************/
582 static BOOL handle_is_printserver(const POLICY_HND *handle)
584 Printer_entry *Printer=find_printer_index_by_hnd(handle);
586 if (!OPEN_HANDLE(Printer))
589 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
595 /****************************************************************************
596 allocate more memory for a BUFFER.
597 ****************************************************************************/
598 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
606 /* damn, I'm doing the reverse operation of prs_grow() :) */
607 if (buffer_size < prs_data_size(ps))
610 extra_space = buffer_size - prs_data_size(ps);
613 * save the offset and move to the end of the buffer
614 * prs_grow() checks the extra_space against the offset
616 old_offset=prs_offset(ps);
617 prs_set_offset(ps, prs_data_size(ps));
619 if (!prs_grow(ps, extra_space))
622 prs_set_offset(ps, old_offset);
624 buffer->string_at_end=prs_data_size(ps);
629 /***************************************************************************
630 receive the notify message
631 ****************************************************************************/
632 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
636 Printer_entry *find_printer;
639 fstrcpy(printer,buf);
642 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
646 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
648 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
650 /* Iterate the printer list. */
651 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
654 * if the entry is the given printer or if it's a printerserver
655 * we send the message
658 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
659 if (strcmp(find_printer->dev.handlename, printer))
662 if (find_printer->notify.client_connected==True)
663 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
668 /***************************************************************************
670 ****************************************************************************/
671 static BOOL srv_spoolss_sendnotify(POLICY_HND *handle)
675 Printer_entry *Printer=find_printer_index_by_hnd(handle);
677 if (!OPEN_HANDLE(Printer)) {
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 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
695 /********************************************************************
696 * spoolss_open_printer
698 * called from the spoolss dispatcher
699 ********************************************************************/
701 uint32 _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
704 uint32 result = NT_STATUS_NO_PROBLEMO;
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 ERROR_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(handle, name))
730 return ERROR_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(handle, printer_default->access_required)) {
743 close_printer_handle(handle);
744 return ERROR_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(handle)) {
773 if (printer_default->access_required == 0) {
774 return NT_STATUS_NO_PROBLEMO;
776 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
778 if (!lp_ms_add_printer_wizard()) {
779 close_printer_handle(handle);
780 return ERROR_ACCESS_DENIED;
782 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
783 return NT_STATUS_NO_PROBLEMO;
786 close_printer_handle(handle);
787 return ERROR_ACCESS_DENIED;
793 /* NT doesn't let us connect to a printer if the connecting user
794 doesn't have print permission. */
796 if (!get_printer_snum(handle, &snum))
797 return ERROR_INVALID_HANDLE;
799 /* map an empty access mask to the minimum access mask */
800 if (printer_default->access_required == 0x0)
801 printer_default->access_required = PRINTER_ACCESS_USE;
803 if (!print_access_check(&user, snum, printer_default->access_required)) {
804 DEBUG(3, ("access DENIED for printer open\n"));
805 close_printer_handle(handle);
806 return ERROR_ACCESS_DENIED;
810 * If we have a default device pointer in the
811 * printer_default struct, then we need to get
812 * the printer info from the tdb and if there is
813 * no default devicemode there then we do a *SET*
814 * here ! This is insanity.... JRA.
818 * If the openprinterex rpc call contains a devmode,
819 * it's a per-user one. This per-user devmode is derivated
820 * from the global devmode. Openprinterex() contains a per-user
821 * devmode for when you do EMF printing and spooling.
822 * In the EMF case, the NT workstation is only doing half the job
823 * of rendering the page. The other half is done by running the printer
824 * driver on the server.
825 * The EMF file doesn't contain the page description (paper size, orientation, ...).
826 * The EMF file only contains what is to be printed on the page.
827 * So in order for the server to know how to print, the NT client sends
828 * a devicemode attached to the openprinterex call.
829 * But this devicemode is short lived, it's only valid for the current print job.
831 * If Samba would have supported EMF spooling, this devicemode would
832 * have been attached to the handle, to sent it to the driver to correctly
833 * rasterize the EMF file.
835 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
836 * we just act as a pass-thru between windows and the printer.
838 * In order to know that Samba supports only RAW spooling, NT has to call
839 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
840 * and until NT sends a RAW job, we refuse it.
842 * But to call getprinter() or startdoc(), you first need a valid handle,
843 * and to get an handle you have to call openprintex(). Hence why you have
844 * a devicemode in the openprinterex() call.
847 * Differences between NT4 and NT 2000.
850 * On NT4, you only have a global devicemode. This global devicemode can be changed
851 * by the administrator (or by a user with enough privs). Everytime a user
852 * wants to print, the devicemode is resetted to the default. In Word, everytime
853 * you print, the printer's characteristics are always reset to the global devicemode.
857 * In W2K, there is the notion of per-user devicemode. The first time you use
858 * a printer, a per-user devicemode is build from the global devicemode.
859 * If you change your per-user devicemode, it is saved in the registry, under the
860 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
861 * printer preferences available.
863 * To change the per-user devicemode: it's the "Printing Preferences ..." button
864 * on the General Tab of the printer properties windows.
866 * To change the global devicemode: it's the "Printing Defaults..." button
867 * on the Advanced Tab of the printer properties window.
875 if (printer_default->devmode_cont.devmode != NULL) {
876 result = printer_write_default_dev( snum, printer_default);
878 close_printer_handle(handle);
885 return NT_STATUS_NO_PROBLEMO;
888 /****************************************************************************
889 ****************************************************************************/
890 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
891 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
895 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
904 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
905 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
909 printer->info_3=NULL;
910 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
913 printer->info_6=NULL;
914 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
923 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
924 NT_DEVICEMODE **pp_nt_devmode)
926 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
929 * Ensure nt_devmode is a valid pointer
930 * as we will be overwriting it.
933 if (nt_devmode == NULL) {
934 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
935 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
939 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
940 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
942 nt_devmode->specversion=devmode->specversion;
943 nt_devmode->driverversion=devmode->driverversion;
944 nt_devmode->size=devmode->size;
945 nt_devmode->fields=devmode->fields;
946 nt_devmode->orientation=devmode->orientation;
947 nt_devmode->papersize=devmode->papersize;
948 nt_devmode->paperlength=devmode->paperlength;
949 nt_devmode->paperwidth=devmode->paperwidth;
950 nt_devmode->scale=devmode->scale;
951 nt_devmode->copies=devmode->copies;
952 nt_devmode->defaultsource=devmode->defaultsource;
953 nt_devmode->printquality=devmode->printquality;
954 nt_devmode->color=devmode->color;
955 nt_devmode->duplex=devmode->duplex;
956 nt_devmode->yresolution=devmode->yresolution;
957 nt_devmode->ttoption=devmode->ttoption;
958 nt_devmode->collate=devmode->collate;
960 nt_devmode->logpixels=devmode->logpixels;
961 nt_devmode->bitsperpel=devmode->bitsperpel;
962 nt_devmode->pelswidth=devmode->pelswidth;
963 nt_devmode->pelsheight=devmode->pelsheight;
964 nt_devmode->displayflags=devmode->displayflags;
965 nt_devmode->displayfrequency=devmode->displayfrequency;
966 nt_devmode->icmmethod=devmode->icmmethod;
967 nt_devmode->icmintent=devmode->icmintent;
968 nt_devmode->mediatype=devmode->mediatype;
969 nt_devmode->dithertype=devmode->dithertype;
970 nt_devmode->reserved1=devmode->reserved1;
971 nt_devmode->reserved2=devmode->reserved2;
972 nt_devmode->panningwidth=devmode->panningwidth;
973 nt_devmode->panningheight=devmode->panningheight;
976 * Only change private and driverextra if the incoming devmode
977 * has a new one. JRA.
980 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
981 safe_free(nt_devmode->private);
982 nt_devmode->driverextra=devmode->driverextra;
983 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
985 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
988 *pp_nt_devmode = nt_devmode;
993 /********************************************************************
994 * api_spoolss_closeprinter
995 ********************************************************************/
997 uint32 _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
999 POLICY_HND *handle = &q_u->handle;
1001 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1003 if (Printer && Printer->document_started)
1004 _spoolss_enddocprinter(handle); /* print job was not closed */
1006 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1008 if (!close_printer_handle(handle))
1009 return ERROR_INVALID_HANDLE;
1011 return NT_STATUS_NO_PROBLEMO;
1014 /********************************************************************
1015 * api_spoolss_deleteprinter
1017 ********************************************************************/
1019 uint32 _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1021 POLICY_HND *handle = &q_u->handle;
1023 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1026 if (Printer && Printer->document_started)
1027 _spoolss_enddocprinter(handle); /* print job was not closed */
1029 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1031 result = delete_printer_handle(handle);
1033 if (result == ERROR_SUCCESS) {
1034 srv_spoolss_sendnotify(handle);
1040 /********************************************************************
1041 GetPrinterData on a printer server Handle.
1042 ********************************************************************/
1043 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1047 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1049 if (!strcmp(value, "BeepEnabled")) {
1051 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1053 SIVAL(*data, 0, 0x01);
1058 if (!strcmp(value, "EventLog")) {
1060 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1062 SIVAL(*data, 0, 0x1B);
1067 if (!strcmp(value, "NetPopup")) {
1069 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1071 SIVAL(*data, 0, 0x01);
1076 if (!strcmp(value, "MajorVersion")) {
1078 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1080 SIVAL(*data, 0, 0x02);
1085 if (!strcmp(value, "DefaultSpoolDirectory")) {
1086 pstring string="You are using a Samba server";
1088 *needed = 2*(strlen(string)+1);
1089 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1091 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1093 /* it's done by hand ready to go on the wire */
1094 for (i=0; i<strlen(string); i++) {
1095 (*data)[2*i]=string[i];
1096 (*data)[2*i+1]='\0';
1101 if (!strcmp(value, "Architecture")) {
1102 pstring string="Windows NT x86";
1104 *needed = 2*(strlen(string)+1);
1105 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1107 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1108 for (i=0; i<strlen(string); i++) {
1109 (*data)[2*i]=string[i];
1110 (*data)[2*i+1]='\0';
1118 /********************************************************************
1119 GetPrinterData on a printer Handle.
1120 ********************************************************************/
1121 static BOOL getprinterdata_printer(POLICY_HND *handle,
1122 fstring value, uint32 *type,
1123 uint8 **data, uint32 *needed, uint32 in_size )
1125 NT_PRINTER_INFO_LEVEL *printer = NULL;
1129 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1131 DEBUG(5,("getprinterdata_printer\n"));
1133 if (!OPEN_HANDLE(Printer)) {
1134 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1138 if(!get_printer_snum(handle, &snum))
1141 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1144 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1145 free_a_printer(&printer, 2);
1149 free_a_printer(&printer, 2);
1151 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1154 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
1158 memset(*data, 0, in_size *sizeof(uint8));
1159 /* copy the min(in_size, len) */
1160 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1167 DEBUG(5,("getprinterdata_printer:copy done\n"));
1174 /********************************************************************
1175 * spoolss_getprinterdata
1176 ********************************************************************/
1178 uint32 _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1180 POLICY_HND *handle = &q_u->handle;
1181 UNISTR2 *valuename = &q_u->valuename;
1182 uint32 in_size = q_u->size;
1183 uint32 *type = &r_u->type;
1184 uint32 *out_size = &r_u->size;
1185 uint8 **data = &r_u->data;
1186 uint32 *needed = &r_u->needed;
1190 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1193 * Reminder: when it's a string, the length is in BYTES
1194 * even if UNICODE is negociated.
1201 /* in case of problem, return some default values */
1205 DEBUG(4,("_spoolss_getprinterdata\n"));
1207 if (!OPEN_HANDLE(Printer)) {
1208 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1209 return ERROR_NOT_ENOUGH_MEMORY;
1210 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1211 return ERROR_INVALID_HANDLE;
1214 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1216 if (handle_is_printserver(handle))
1217 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1219 found= getprinterdata_printer(handle, value, type, data, needed, *out_size);
1222 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1223 /* reply this param doesn't exist */
1225 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1226 return ERROR_NOT_ENOUGH_MEMORY;
1231 return ERROR_INVALID_PARAMETER;
1234 if (*needed > *out_size)
1235 return ERROR_MORE_DATA;
1237 return NT_STATUS_NO_PROBLEMO;
1241 /***************************************************************************
1242 connect to the client
1243 ****************************************************************************/
1244 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1249 * If it's the first connection, contact the client
1250 * and connect to the IPC$ share anonumously
1252 if (smb_connections==0) {
1253 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1255 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1261 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1267 /********************************************************************
1269 * ReplyFindFirstPrinterChangeNotifyEx
1271 * jfmxxxx: before replying OK: status=0
1272 * should do a rpc call to the workstation asking ReplyOpenPrinter
1273 * have to code it, later.
1275 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1276 * called from api_spoolss_rffpcnex
1277 ********************************************************************/
1279 uint32 _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1281 POLICY_HND *handle = &q_u->handle;
1282 uint32 flags = q_u->flags;
1283 uint32 options = q_u->options;
1284 UNISTR2 *localmachine = &q_u->localmachine;
1285 uint32 printerlocal = q_u->printerlocal;
1286 SPOOL_NOTIFY_OPTION *option = q_u->option;
1288 /* store the notify value in the printer struct */
1290 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1292 if (!OPEN_HANDLE(Printer)) {
1293 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1294 return ERROR_INVALID_HANDLE;
1297 Printer->notify.flags=flags;
1298 Printer->notify.options=options;
1299 Printer->notify.printerlocal=printerlocal;
1300 Printer->notify.option=option;
1301 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1303 /* connect to the client machine and send a ReplyOpenPrinter */
1304 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1305 Printer->notify.printerlocal, 1,
1306 &Printer->notify.client_hnd))
1307 Printer->notify.client_connected=True;
1309 return NT_STATUS_NO_PROBLEMO;
1312 /*******************************************************************
1313 * fill a notify_info_data with the servername
1314 ********************************************************************/
1316 static void spoolss_notify_server_name(int snum,
1317 SPOOL_NOTIFY_INFO_DATA *data,
1318 print_queue_struct *queue,
1319 NT_PRINTER_INFO_LEVEL *printer,
1320 TALLOC_CTX *mem_ctx)
1322 pstring temp_name, temp;
1325 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1327 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1329 data->notify_data.data.length = len / 2 - 1;
1330 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1332 if (!data->notify_data.data.string) {
1333 data->notify_data.data.length = 0;
1337 memcpy(data->notify_data.data.string, temp, len);
1340 /*******************************************************************
1341 * fill a notify_info_data with the printername (not including the servername).
1342 ********************************************************************/
1343 static void spoolss_notify_printer_name(int snum,
1344 SPOOL_NOTIFY_INFO_DATA *data,
1345 print_queue_struct *queue,
1346 NT_PRINTER_INFO_LEVEL *printer,
1347 TALLOC_CTX *mem_ctx)
1352 /* the notify name should not contain the \\server\ part */
1353 char *p = strrchr(printer->info_2->printername, '\\');
1356 p = printer->info_2->printername;
1361 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1363 data->notify_data.data.length = len / 2 - 1;
1364 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1366 if (!data->notify_data.data.string) {
1367 data->notify_data.data.length = 0;
1371 memcpy(data->notify_data.data.string, temp, len);
1374 /*******************************************************************
1375 * fill a notify_info_data with the servicename
1376 ********************************************************************/
1377 static void spoolss_notify_share_name(int snum,
1378 SPOOL_NOTIFY_INFO_DATA *data,
1379 print_queue_struct *queue,
1380 NT_PRINTER_INFO_LEVEL *printer,
1381 TALLOC_CTX *mem_ctx)
1386 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1387 sizeof(temp) - 2, True);
1389 data->notify_data.data.length = len / 2 - 1;
1390 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1392 if (!data->notify_data.data.string) {
1393 data->notify_data.data.length = 0;
1397 memcpy(data->notify_data.data.string, temp, len);
1400 /*******************************************************************
1401 * fill a notify_info_data with the port name
1402 ********************************************************************/
1403 static void spoolss_notify_port_name(int snum,
1404 SPOOL_NOTIFY_INFO_DATA *data,
1405 print_queue_struct *queue,
1406 NT_PRINTER_INFO_LEVEL *printer,
1407 TALLOC_CTX *mem_ctx)
1412 /* even if it's strange, that's consistant in all the code */
1414 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1415 sizeof(temp) - 2, True);
1417 data->notify_data.data.length = len / 2 - 1;
1418 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1420 if (!data->notify_data.data.string) {
1421 data->notify_data.data.length = 0;
1425 memcpy(data->notify_data.data.string, temp, len);
1428 /*******************************************************************
1429 * fill a notify_info_data with the printername
1430 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1431 * but it doesn't exist, have to see what to do
1432 ********************************************************************/
1433 static void spoolss_notify_driver_name(int snum,
1434 SPOOL_NOTIFY_INFO_DATA *data,
1435 print_queue_struct *queue,
1436 NT_PRINTER_INFO_LEVEL *printer,
1437 TALLOC_CTX *mem_ctx)
1442 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1443 sizeof(temp) - 2, True);
1445 data->notify_data.data.length = len / 2 - 1;
1446 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1448 if (!data->notify_data.data.string) {
1449 data->notify_data.data.length = 0;
1453 memcpy(data->notify_data.data.string, temp, len);
1456 /*******************************************************************
1457 * fill a notify_info_data with the comment
1458 ********************************************************************/
1459 static void spoolss_notify_comment(int snum,
1460 SPOOL_NOTIFY_INFO_DATA *data,
1461 print_queue_struct *queue,
1462 NT_PRINTER_INFO_LEVEL *printer,
1463 TALLOC_CTX *mem_ctx)
1468 if (*printer->info_2->comment == '\0')
1469 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1470 sizeof(temp) - 2, True);
1472 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1473 sizeof(temp) - 2, True);
1475 data->notify_data.data.length = len / 2 - 1;
1476 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1478 if (!data->notify_data.data.string) {
1479 data->notify_data.data.length = 0;
1483 memcpy(data->notify_data.data.string, temp, len);
1486 /*******************************************************************
1487 * fill a notify_info_data with the comment
1488 * jfm:xxxx incorrect, have to create a new smb.conf option
1489 * location = "Room 1, floor 2, building 3"
1490 ********************************************************************/
1491 static void spoolss_notify_location(int snum,
1492 SPOOL_NOTIFY_INFO_DATA *data,
1493 print_queue_struct *queue,
1494 NT_PRINTER_INFO_LEVEL *printer,
1495 TALLOC_CTX *mem_ctx)
1500 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1501 sizeof(temp) - 2, True);
1503 data->notify_data.data.length = len / 2 - 1;
1504 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1506 if (!data->notify_data.data.string) {
1507 data->notify_data.data.length = 0;
1511 memcpy(data->notify_data.data.string, temp, len);
1514 /*******************************************************************
1515 * fill a notify_info_data with the device mode
1516 * jfm:xxxx don't to it for know but that's a real problem !!!
1517 ********************************************************************/
1518 static void spoolss_notify_devmode(int snum,
1519 SPOOL_NOTIFY_INFO_DATA *data,
1520 print_queue_struct *queue,
1521 NT_PRINTER_INFO_LEVEL *printer,
1522 TALLOC_CTX *mem_ctx)
1526 /*******************************************************************
1527 * fill a notify_info_data with the separator file name
1528 * jfm:xxxx just return no file could add an option to smb.conf
1529 * separator file = "separator.txt"
1530 ********************************************************************/
1531 static void spoolss_notify_sepfile(int snum,
1532 SPOOL_NOTIFY_INFO_DATA *data,
1533 print_queue_struct *queue,
1534 NT_PRINTER_INFO_LEVEL *printer,
1535 TALLOC_CTX *mem_ctx)
1540 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1541 sizeof(temp) - 2, True);
1543 data->notify_data.data.length = len / 2 - 1;
1544 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1546 if (!data->notify_data.data.string) {
1547 data->notify_data.data.length = 0;
1551 memcpy(data->notify_data.data.string, temp, len);
1554 /*******************************************************************
1555 * fill a notify_info_data with the print processor
1556 * jfm:xxxx return always winprint to indicate we don't do anything to it
1557 ********************************************************************/
1558 static void spoolss_notify_print_processor(int snum,
1559 SPOOL_NOTIFY_INFO_DATA *data,
1560 print_queue_struct *queue,
1561 NT_PRINTER_INFO_LEVEL *printer,
1562 TALLOC_CTX *mem_ctx)
1567 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
1568 sizeof(temp) - 2, True);
1570 data->notify_data.data.length = len / 2 - 1;
1571 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1573 if (!data->notify_data.data.string) {
1574 data->notify_data.data.length = 0;
1578 memcpy(data->notify_data.data.string, temp, len);
1581 /*******************************************************************
1582 * fill a notify_info_data with the print processor options
1583 * jfm:xxxx send an empty string
1584 ********************************************************************/
1585 static void spoolss_notify_parameters(int snum,
1586 SPOOL_NOTIFY_INFO_DATA *data,
1587 print_queue_struct *queue,
1588 NT_PRINTER_INFO_LEVEL *printer,
1589 TALLOC_CTX *mem_ctx)
1594 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1595 sizeof(temp) - 2, True);
1597 data->notify_data.data.length = len / 2 - 1;
1598 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1600 if (!data->notify_data.data.string) {
1601 data->notify_data.data.length = 0;
1605 memcpy(data->notify_data.data.string, temp, len);
1608 /*******************************************************************
1609 * fill a notify_info_data with the data type
1610 * jfm:xxxx always send RAW as data type
1611 ********************************************************************/
1612 static void spoolss_notify_datatype(int snum,
1613 SPOOL_NOTIFY_INFO_DATA *data,
1614 print_queue_struct *queue,
1615 NT_PRINTER_INFO_LEVEL *printer,
1616 TALLOC_CTX *mem_ctx)
1621 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1622 sizeof(pstring) - 2, True);
1624 data->notify_data.data.length = len / 2 - 1;
1625 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1627 if (!data->notify_data.data.string) {
1628 data->notify_data.data.length = 0;
1632 memcpy(data->notify_data.data.string, temp, len);
1635 /*******************************************************************
1636 * fill a notify_info_data with the security descriptor
1637 * jfm:xxxx send an null pointer to say no security desc
1638 * have to implement security before !
1639 ********************************************************************/
1640 static void spoolss_notify_security_desc(int snum,
1641 SPOOL_NOTIFY_INFO_DATA *data,
1642 print_queue_struct *queue,
1643 NT_PRINTER_INFO_LEVEL *printer,
1644 TALLOC_CTX *mem_ctx)
1646 data->notify_data.data.length=0;
1647 data->notify_data.data.string = NULL;
1650 /*******************************************************************
1651 * fill a notify_info_data with the attributes
1652 * jfm:xxxx a samba printer is always shared
1653 ********************************************************************/
1654 static void spoolss_notify_attributes(int snum,
1655 SPOOL_NOTIFY_INFO_DATA *data,
1656 print_queue_struct *queue,
1657 NT_PRINTER_INFO_LEVEL *printer,
1658 TALLOC_CTX *mem_ctx)
1660 data->notify_data.value[0] = printer->info_2->attributes;
1663 /*******************************************************************
1664 * fill a notify_info_data with the priority
1665 ********************************************************************/
1666 static void spoolss_notify_priority(int snum,
1667 SPOOL_NOTIFY_INFO_DATA *data,
1668 print_queue_struct *queue,
1669 NT_PRINTER_INFO_LEVEL *printer,
1670 TALLOC_CTX *mem_ctx)
1672 data->notify_data.value[0] = printer->info_2->priority;
1675 /*******************************************************************
1676 * fill a notify_info_data with the default priority
1677 ********************************************************************/
1678 static void spoolss_notify_default_priority(int snum,
1679 SPOOL_NOTIFY_INFO_DATA *data,
1680 print_queue_struct *queue,
1681 NT_PRINTER_INFO_LEVEL *printer,
1682 TALLOC_CTX *mem_ctx)
1684 data->notify_data.value[0] = printer->info_2->default_priority;
1687 /*******************************************************************
1688 * fill a notify_info_data with the start time
1689 ********************************************************************/
1690 static void spoolss_notify_start_time(int snum,
1691 SPOOL_NOTIFY_INFO_DATA *data,
1692 print_queue_struct *queue,
1693 NT_PRINTER_INFO_LEVEL *printer,
1694 TALLOC_CTX *mem_ctx)
1696 data->notify_data.value[0] = printer->info_2->starttime;
1699 /*******************************************************************
1700 * fill a notify_info_data with the until time
1701 ********************************************************************/
1702 static void spoolss_notify_until_time(int snum,
1703 SPOOL_NOTIFY_INFO_DATA *data,
1704 print_queue_struct *queue,
1705 NT_PRINTER_INFO_LEVEL *printer,
1706 TALLOC_CTX *mem_ctx)
1708 data->notify_data.value[0] = printer->info_2->untiltime;
1711 /*******************************************************************
1712 * fill a notify_info_data with the status
1713 ********************************************************************/
1714 static void spoolss_notify_status(int snum,
1715 SPOOL_NOTIFY_INFO_DATA *data,
1716 print_queue_struct *queue,
1717 NT_PRINTER_INFO_LEVEL *printer,
1718 TALLOC_CTX *mem_ctx)
1722 print_queue_struct *q=NULL;
1723 print_status_struct status;
1725 memset(&status, 0, sizeof(status));
1726 count = print_queue_status(snum, &q, &status);
1727 data->notify_data.value[0]=(uint32) status.status;
1731 /*******************************************************************
1732 * fill a notify_info_data with the number of jobs queued
1733 ********************************************************************/
1734 static void spoolss_notify_cjobs(int snum,
1735 SPOOL_NOTIFY_INFO_DATA *data,
1736 print_queue_struct *queue,
1737 NT_PRINTER_INFO_LEVEL *printer,
1738 TALLOC_CTX *mem_ctx)
1740 print_queue_struct *q=NULL;
1741 print_status_struct status;
1743 memset(&status, 0, sizeof(status));
1744 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1748 /*******************************************************************
1749 * fill a notify_info_data with the average ppm
1750 ********************************************************************/
1751 static void spoolss_notify_average_ppm(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 /* always respond 8 pages per minutes */
1758 /* a little hard ! */
1759 data->notify_data.value[0] = printer->info_2->averageppm;
1762 /*******************************************************************
1763 * fill a notify_info_data with username
1764 ********************************************************************/
1765 static void spoolss_notify_username(int snum,
1766 SPOOL_NOTIFY_INFO_DATA *data,
1767 print_queue_struct *queue,
1768 NT_PRINTER_INFO_LEVEL *printer,
1769 TALLOC_CTX *mem_ctx)
1774 len = (uint32)dos_PutUniCode(temp, queue->user,
1775 sizeof(temp) - 2, True);
1777 data->notify_data.data.length = len / 2 - 1;
1778 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1780 if (!data->notify_data.data.string) {
1781 data->notify_data.data.length = 0;
1785 memcpy(data->notify_data.data.string, temp, len);
1788 /*******************************************************************
1789 * fill a notify_info_data with job status
1790 ********************************************************************/
1791 static void spoolss_notify_job_status(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]=nt_printj_status(queue->status);
1800 /*******************************************************************
1801 * fill a notify_info_data with job name
1802 ********************************************************************/
1803 static void spoolss_notify_job_name(int snum,
1804 SPOOL_NOTIFY_INFO_DATA *data,
1805 print_queue_struct *queue,
1806 NT_PRINTER_INFO_LEVEL *printer,
1807 TALLOC_CTX *mem_ctx)
1812 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1815 data->notify_data.data.length = len / 2 - 1;
1816 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1818 if (!data->notify_data.data.string) {
1819 data->notify_data.data.length = 0;
1823 memcpy(data->notify_data.data.string, temp, len);
1826 /*******************************************************************
1827 * fill a notify_info_data with job status
1828 ********************************************************************/
1829 static void spoolss_notify_job_status_string(int snum,
1830 SPOOL_NOTIFY_INFO_DATA *data,
1831 print_queue_struct *queue,
1832 NT_PRINTER_INFO_LEVEL *printer,
1833 TALLOC_CTX *mem_ctx)
1836 * Now we're returning job status codes we just return a "" here. JRA.
1843 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1846 switch (queue->status) {
1851 p = ""; /* NT provides the paused string */
1860 #endif /* NO LONGER NEEDED. */
1862 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1864 data->notify_data.data.length = len / 2 - 1;
1865 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1867 if (!data->notify_data.data.string) {
1868 data->notify_data.data.length = 0;
1872 memcpy(data->notify_data.data.string, temp, len);
1875 /*******************************************************************
1876 * fill a notify_info_data with job time
1877 ********************************************************************/
1878 static void spoolss_notify_job_time(int snum,
1879 SPOOL_NOTIFY_INFO_DATA *data,
1880 print_queue_struct *queue,
1881 NT_PRINTER_INFO_LEVEL *printer,
1882 TALLOC_CTX *mem_ctx)
1884 data->notify_data.value[0]=0x0;
1887 /*******************************************************************
1888 * fill a notify_info_data with job size
1889 ********************************************************************/
1890 static void spoolss_notify_job_size(int snum,
1891 SPOOL_NOTIFY_INFO_DATA *data,
1892 print_queue_struct *queue,
1893 NT_PRINTER_INFO_LEVEL *printer,
1894 TALLOC_CTX *mem_ctx)
1896 data->notify_data.value[0]=queue->size;
1899 /*******************************************************************
1900 * fill a notify_info_data with job position
1901 ********************************************************************/
1902 static void spoolss_notify_job_position(int snum,
1903 SPOOL_NOTIFY_INFO_DATA *data,
1904 print_queue_struct *queue,
1905 NT_PRINTER_INFO_LEVEL *printer,
1906 TALLOC_CTX *mem_ctx)
1908 data->notify_data.value[0]=queue->job;
1911 /*******************************************************************
1912 * fill a notify_info_data with submitted time
1913 ********************************************************************/
1914 static void spoolss_notify_submitted_time(int snum,
1915 SPOOL_NOTIFY_INFO_DATA *data,
1916 print_queue_struct *queue,
1917 NT_PRINTER_INFO_LEVEL *printer,
1918 TALLOC_CTX *mem_ctx)
1923 t=gmtime(&queue->time);
1925 len = sizeof(SYSTEMTIME);
1927 data->notify_data.data.length = len;
1928 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1930 if (!data->notify_data.data.string) {
1931 data->notify_data.data.length = 0;
1935 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1940 struct s_notify_info_data_table
1946 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1947 print_queue_struct *queue,
1948 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
1951 struct s_notify_info_data_table notify_info_data_table[] =
1953 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1954 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1955 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1956 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1957 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1958 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1959 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1960 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1961 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1962 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1963 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1964 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1965 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1966 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1967 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1968 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1969 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1970 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1971 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1972 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1973 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1974 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1975 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1976 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1977 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1978 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1979 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1980 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1981 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1982 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1983 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1984 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1985 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1986 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1987 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1988 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1989 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1990 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1991 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1992 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1993 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1994 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1995 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1996 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1997 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1998 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1999 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2000 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2001 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2002 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2003 { END, END, "", END, NULL }
2006 /*******************************************************************
2007 return the size of info_data structure
2008 ********************************************************************/
2009 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2013 while (notify_info_data_table[i].type != END)
2015 if ( (notify_info_data_table[i].type == type ) &&
2016 (notify_info_data_table[i].field == field ) )
2018 return (notify_info_data_table[i].size);
2025 /*******************************************************************
2026 return the type of notify_info_data
2027 ********************************************************************/
2028 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2032 while (notify_info_data_table[i].type != END)
2034 if ( (notify_info_data_table[i].type == type ) &&
2035 (notify_info_data_table[i].field == field ) )
2037 if (notify_info_data_table[i].size == POINTER)
2051 /****************************************************************************
2052 ****************************************************************************/
2053 static int search_notify(uint16 type, uint16 field, int *value)
2058 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2060 if ( (notify_info_data_table[j].type == type ) &&
2061 (notify_info_data_table[j].field == field ) )
2066 if ( found && (notify_info_data_table[j].fn != NULL) )
2072 /****************************************************************************
2073 ****************************************************************************/
2074 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2076 info_data->type = type;
2077 info_data->field = field;
2078 info_data->reserved = 0;
2080 info_data->size = size_of_notify_info_data(type, field);
2081 info_data->enc_type = type_of_notify_info_data(type, field);
2085 /*******************************************************************
2087 * fill a notify_info struct with info asked
2089 ********************************************************************/
2090 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2091 snum, SPOOL_NOTIFY_OPTION_TYPE
2092 *option_type, uint32 id,
2093 TALLOC_CTX *mem_ctx)
2099 SPOOL_NOTIFY_INFO_DATA *current_data;
2100 NT_PRINTER_INFO_LEVEL *printer = NULL;
2101 print_queue_struct *queue=NULL;
2102 size_t realloc_size = 0;
2103 SPOOL_NOTIFY_INFO_DATA *info_data_ptr = NULL;
2105 type=option_type->type;
2107 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2108 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2109 option_type->count, lp_servicename(snum)));
2111 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2114 for(field_num=0; field_num<option_type->count; field_num++) {
2115 field = option_type->fields[field_num];
2116 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2118 if (!search_notify(type, field, &j) )
2121 realloc_size = (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA);
2122 if((info_data_ptr=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info_data_ptr, realloc_size)) == NULL) {
2125 current_data=&info_data_ptr[info->count];
2127 construct_info_data(current_data, type, field, id);
2129 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2130 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2132 notify_info_data_table[j].fn(snum, current_data, queue,
2139 info->data = talloc_memdup(mem_ctx, info_data_ptr, realloc_size);
2143 safe_free(info_data_ptr);
2144 free_a_printer(&printer, 2);
2148 /*******************************************************************
2150 * fill a notify_info struct with info asked
2152 ********************************************************************/
2153 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2154 SPOOL_NOTIFY_INFO *info,
2155 NT_PRINTER_INFO_LEVEL *printer,
2156 int snum, SPOOL_NOTIFY_OPTION_TYPE
2157 *option_type, uint32 id,
2158 TALLOC_CTX *mem_ctx)
2164 SPOOL_NOTIFY_INFO_DATA *current_data;
2166 DEBUG(4,("construct_notify_jobs_info\n"));
2168 type = option_type->type;
2170 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2171 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2172 option_type->count));
2174 for(field_num=0; field_num<option_type->count; field_num++) {
2175 field = option_type->fields[field_num];
2177 if (!search_notify(type, field, &j) )
2180 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2184 current_data=&(info->data[info->count]);
2186 construct_info_data(current_data, type, field, id);
2187 notify_info_data_table[j].fn(snum, current_data, queue,
2196 * JFM: The enumeration is not that simple, it's even non obvious.
2198 * let's take an example: I want to monitor the PRINTER SERVER for
2199 * the printer's name and the number of jobs currently queued.
2200 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2201 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2203 * I have 3 printers on the back of my server.
2205 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2208 * 1 printer 1 name 1
2209 * 2 printer 1 cjob 1
2210 * 3 printer 2 name 2
2211 * 4 printer 2 cjob 2
2212 * 5 printer 3 name 3
2213 * 6 printer 3 name 3
2215 * that's the print server case, the printer case is even worse.
2220 /*******************************************************************
2222 * enumerate all printers on the printserver
2223 * fill a notify_info struct with info asked
2225 ********************************************************************/
2226 static uint32 printserver_notify_info(const POLICY_HND *hnd,
2227 SPOOL_NOTIFY_INFO *info,
2228 TALLOC_CTX *mem_ctx)
2231 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2232 int n_services=lp_numservices();
2235 SPOOL_NOTIFY_OPTION *option;
2236 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2238 DEBUG(4,("printserver_notify_info\n"));
2240 option=Printer->notify.option;
2246 for (i=0; i<option->count; i++) {
2247 option_type=&(option->ctr.type[i]);
2249 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2252 for (snum=0; snum<n_services; snum++)
2253 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2254 if (construct_notify_printer_info
2255 (info, snum, option_type, id, mem_ctx))
2260 * Debugging information, don't delete.
2263 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2264 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2265 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2267 for (i=0; i<info->count; i++) {
2268 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2269 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2270 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2274 return NT_STATUS_NO_PROBLEMO;
2277 /*******************************************************************
2279 * fill a notify_info struct with info asked
2281 ********************************************************************/
2282 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2283 TALLOC_CTX *mem_ctx)
2286 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2289 SPOOL_NOTIFY_OPTION *option;
2290 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2292 print_queue_struct *queue=NULL;
2293 print_status_struct status;
2295 DEBUG(4,("printer_notify_info\n"));
2297 option=Printer->notify.option;
2303 get_printer_snum(hnd, &snum);
2305 for (i=0; i<option->count; i++) {
2306 option_type=&option->ctr.type[i];
2308 switch ( option_type->type ) {
2309 case PRINTER_NOTIFY_TYPE:
2310 if(construct_notify_printer_info(info, snum,
2316 case JOB_NOTIFY_TYPE: {
2317 NT_PRINTER_INFO_LEVEL *printer = NULL;
2319 memset(&status, 0, sizeof(status));
2320 count = print_queue_status(snum, &queue, &status);
2322 if (get_a_printer(&printer, 2,
2323 lp_servicename(snum)) != 0)
2326 for (j=0; j<count; j++) {
2327 construct_notify_jobs_info(&queue[j], info,
2334 free_a_printer(&printer, 2);
2344 * Debugging information, don't delete.
2347 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2348 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2349 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2351 for (i=0; i<info->count; i++) {
2352 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2353 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2354 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2357 return NT_STATUS_NO_PROBLEMO;
2360 /********************************************************************
2362 ********************************************************************/
2364 uint32 _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2366 POLICY_HND *handle = &q_u->handle;
2367 /* uint32 change = q_u->change; - notused. */
2368 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2369 SPOOL_NOTIFY_INFO *info = &r_u->info;
2371 Printer_entry *Printer=find_printer_index_by_hnd(handle);
2372 uint32 result = ERROR_INVALID_HANDLE;
2374 /* we always have a NOTIFY_INFO struct */
2377 if (!OPEN_HANDLE(Printer)) {
2378 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2379 OUR_HANDLE(handle)));
2383 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2385 /* jfm: the change value isn't used right now.
2386 * we will honour it when
2387 * a) we'll be able to send notification to the client
2388 * b) we'll have a way to communicate between the spoolss process.
2390 * same thing for option->flags
2391 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2392 * I don't have a global notification system, I'm sending back all the
2393 * informations even when _NOTHING_ has changed.
2396 /* just ignore the SPOOL_NOTIFY_OPTION */
2398 switch (Printer->printer_type) {
2399 case PRINTER_HANDLE_IS_PRINTSERVER:
2400 result = printserver_notify_info(handle, info,
2404 case PRINTER_HANDLE_IS_PRINTER:
2405 result = printer_notify_info(handle, info, p->mem_ctx);
2413 /********************************************************************
2414 * construct_printer_info_0
2415 * fill a printer_info_0 struct
2416 ********************************************************************/
2417 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2421 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2422 counter_printer_0 *session_counter;
2423 uint32 global_counter;
2427 print_queue_struct *queue=NULL;
2428 print_status_struct status;
2430 memset(&status, 0, sizeof(status));
2432 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2435 count = print_queue_status(snum, &queue, &status);
2437 /* check if we already have a counter for this printer */
2438 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2440 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2441 if (session_counter->snum == snum)
2445 /* it's the first time, add it to the list */
2446 if (session_counter==NULL) {
2447 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2448 free_a_printer(&ntprinter, 2);
2451 ZERO_STRUCTP(session_counter);
2452 session_counter->snum=snum;
2453 session_counter->counter=0;
2454 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2458 session_counter->counter++;
2461 * the global_counter should be stored in a TDB as it's common to all the clients
2462 * and should be zeroed on samba startup
2464 global_counter=session_counter->counter;
2466 pstrcpy(chaine,ntprinter->info_2->printername);
2468 init_unistr(&printer->printername, chaine);
2470 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2471 init_unistr(&printer->servername, chaine);
2473 printer->cjobs = count;
2474 printer->total_jobs = 0;
2475 printer->total_bytes = 0;
2477 setuptime = (time_t)ntprinter->info_2->setuptime;
2478 t=gmtime(&setuptime);
2480 printer->year = t->tm_year+1900;
2481 printer->month = t->tm_mon+1;
2482 printer->dayofweek = t->tm_wday;
2483 printer->day = t->tm_mday;
2484 printer->hour = t->tm_hour;
2485 printer->minute = t->tm_min;
2486 printer->second = t->tm_sec;
2487 printer->milliseconds = 0;
2489 printer->global_counter = global_counter;
2490 printer->total_pages = 0;
2491 printer->major_version = 0x0004; /* NT 4 */
2492 printer->build_version = 0x0565; /* build 1381 */
2493 printer->unknown7 = 0x1;
2494 printer->unknown8 = 0x0;
2495 printer->unknown9 = 0x0;
2496 printer->session_counter = session_counter->counter;
2497 printer->unknown11 = 0x0;
2498 printer->printer_errors = 0x0; /* number of print failure */
2499 printer->unknown13 = 0x0;
2500 printer->unknown14 = 0x1;
2501 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2502 printer->unknown16 = 0x0;
2503 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2504 printer->unknown18 = 0x0;
2505 printer->status = nt_printq_status(status.status);
2506 printer->unknown20 = 0x0;
2507 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2508 printer->unknown22 = 0x0;
2509 printer->unknown23 = 0x6; /* 6 ???*/
2510 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2511 printer->unknown25 = 0;
2512 printer->unknown26 = 0;
2513 printer->unknown27 = 0;
2514 printer->unknown28 = 0;
2515 printer->unknown29 = 0;
2518 free_a_printer(&ntprinter,2);
2522 /********************************************************************
2523 * construct_printer_info_1
2524 * fill a printer_info_1 struct
2525 ********************************************************************/
2526 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2530 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2532 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2535 printer->flags=flags;
2537 if (*ntprinter->info_2->comment == '\0') {
2538 init_unistr(&printer->comment, lp_comment(snum));
2539 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2540 ntprinter->info_2->drivername, lp_comment(snum));
2543 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2544 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2545 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2548 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2550 init_unistr(&printer->description, chaine);
2551 init_unistr(&printer->name, chaine2);
2553 free_a_printer(&ntprinter,2);
2558 /****************************************************************************
2559 Free a DEVMODE struct.
2560 ****************************************************************************/
2562 static void free_dev_mode(DEVICEMODE *dev)
2568 safe_free(dev->private);
2573 /****************************************************************************
2574 Create a DEVMODE struct. Returns malloced memory.
2575 ****************************************************************************/
2577 static DEVICEMODE *construct_dev_mode(int snum)
2581 NT_PRINTER_INFO_LEVEL *printer = NULL;
2582 NT_DEVICEMODE *ntdevmode = NULL;
2583 DEVICEMODE *devmode = NULL;
2585 DEBUG(7,("construct_dev_mode\n"));
2587 DEBUGADD(8,("getting printer characteristics\n"));
2589 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2590 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2594 ZERO_STRUCTP(devmode);
2596 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2599 if (printer->info_2->devmode)
2600 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2602 if (ntdevmode == NULL)
2605 DEBUGADD(8,("loading DEVICEMODE\n"));
2607 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2608 init_unistr(&devmode->devicename, adevice);
2610 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2611 init_unistr(&devmode->formname, aform);
2613 devmode->specversion = ntdevmode->specversion;
2614 devmode->driverversion = ntdevmode->driverversion;
2615 devmode->size = ntdevmode->size;
2616 devmode->driverextra = ntdevmode->driverextra;
2617 devmode->fields = ntdevmode->fields;
2619 devmode->orientation = ntdevmode->orientation;
2620 devmode->papersize = ntdevmode->papersize;
2621 devmode->paperlength = ntdevmode->paperlength;
2622 devmode->paperwidth = ntdevmode->paperwidth;
2623 devmode->scale = ntdevmode->scale;
2624 devmode->copies = ntdevmode->copies;
2625 devmode->defaultsource = ntdevmode->defaultsource;
2626 devmode->printquality = ntdevmode->printquality;
2627 devmode->color = ntdevmode->color;
2628 devmode->duplex = ntdevmode->duplex;
2629 devmode->yresolution = ntdevmode->yresolution;
2630 devmode->ttoption = ntdevmode->ttoption;
2631 devmode->collate = ntdevmode->collate;
2632 devmode->icmmethod = ntdevmode->icmmethod;
2633 devmode->icmintent = ntdevmode->icmintent;
2634 devmode->mediatype = ntdevmode->mediatype;
2635 devmode->dithertype = ntdevmode->dithertype;
2637 if (ntdevmode->private != NULL) {
2638 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2642 free_nt_devicemode(&ntdevmode);
2643 free_a_printer(&printer,2);
2650 free_nt_devicemode(&ntdevmode);
2652 free_a_printer(&printer,2);
2653 free_dev_mode(devmode);
2658 /********************************************************************
2659 * construct_printer_info_2
2660 * fill a printer_info_2 struct
2661 ********************************************************************/
2663 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2666 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2668 print_queue_struct *queue=NULL;
2669 print_status_struct status;
2670 memset(&status, 0, sizeof(status));
2672 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2675 memset(&status, 0, sizeof(status));
2676 count = print_queue_status(snum, &queue, &status);
2678 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2679 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2680 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2681 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2682 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2684 if (*ntprinter->info_2->comment == '\0')
2685 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2687 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2689 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2690 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2691 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2692 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2693 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2695 printer->attributes = ntprinter->info_2->attributes;
2697 printer->priority = ntprinter->info_2->priority; /* priority */
2698 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2699 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2700 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2701 printer->status = nt_printq_status(status.status); /* status */
2702 printer->cjobs = count; /* jobs */
2703 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2705 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2706 DEBUG(8, ("Returning NULL Devicemode!\n"));
2709 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2710 /* steal the printer info sec_desc structure. [badly done]. */
2711 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2712 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2713 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2714 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2717 printer->secdesc = NULL;
2720 free_a_printer(&ntprinter, 2);
2725 /********************************************************************
2726 * construct_printer_info_3
2727 * fill a printer_info_3 struct
2728 ********************************************************************/
2729 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2731 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2732 PRINTER_INFO_3 *printer = NULL;
2734 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2738 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2739 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2743 ZERO_STRUCTP(printer);
2745 printer->flags = 4; /* These are the components of the SD we are returning. */
2746 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2747 /* steal the printer info sec_desc structure. [badly done]. */
2748 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2752 * Set the flags for the components we are returning.
2755 if (printer->secdesc->owner_sid)
2756 printer->flags |= OWNER_SECURITY_INFORMATION;
2758 if (printer->secdesc->grp_sid)
2759 printer->flags |= GROUP_SECURITY_INFORMATION;
2761 if (printer->secdesc->dacl)
2762 printer->flags |= DACL_SECURITY_INFORMATION;
2764 if (printer->secdesc->sacl)
2765 printer->flags |= SACL_SECURITY_INFORMATION;
2768 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2769 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2770 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2773 free_a_printer(&ntprinter, 2);
2775 *pp_printer = printer;
2779 /********************************************************************
2780 Spoolss_enumprinters.
2781 ********************************************************************/
2782 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2786 int n_services=lp_numservices();
2787 PRINTER_INFO_1 *printers=NULL;
2788 PRINTER_INFO_1 current_prt;
2790 DEBUG(4,("enum_all_printers_info_1\n"));
2792 for (snum=0; snum<n_services; snum++) {
2793 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2794 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2796 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2797 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2799 return ERROR_NOT_ENOUGH_MEMORY;
2801 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2802 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2808 /* check the required size. */
2809 for (i=0; i<*returned; i++)
2810 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2812 if (!alloc_buffer_size(buffer, *needed))
2813 return ERROR_INSUFFICIENT_BUFFER;
2815 /* fill the buffer with the structures */
2816 for (i=0; i<*returned; i++)
2817 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2820 safe_free(printers);
2822 if (*needed > offered) {
2824 return ERROR_INSUFFICIENT_BUFFER;
2827 return NT_STATUS_NO_PROBLEMO;
2830 /********************************************************************
2831 enum_all_printers_info_1_local.
2832 *********************************************************************/
2833 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2835 DEBUG(4,("enum_all_printers_info_1_local\n"));
2837 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2840 /********************************************************************
2841 enum_all_printers_info_1_name.
2842 *********************************************************************/
2843 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2846 DEBUG(4,("enum_all_printers_info_1_name\n"));
2848 fstrcpy(temp, "\\\\");
2849 fstrcat(temp, global_myname);
2851 if (strequal(name, temp)) {
2852 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2855 return ERROR_INVALID_NAME;
2858 /********************************************************************
2859 enum_all_printers_info_1_remote.
2860 *********************************************************************/
2861 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2863 PRINTER_INFO_1 *printer;
2864 fstring printername;
2867 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2869 /* JFM: currently it's more a place holder than anything else.
2870 * In the spooler world there is a notion of server registration.
2871 * the print servers are registring (sp ?) on the PDC (in the same domain)
2873 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2876 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2877 return ERROR_NOT_ENOUGH_MEMORY;
2881 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2882 slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2883 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2885 init_unistr(&printer->description, desc);
2886 init_unistr(&printer->name, printername);
2887 init_unistr(&printer->comment, comment);
2888 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2890 /* check the required size. */
2891 *needed += spoolss_size_printer_info_1(printer);
2893 if (!alloc_buffer_size(buffer, *needed)) {
2895 return ERROR_INSUFFICIENT_BUFFER;
2898 /* fill the buffer with the structures */
2899 new_smb_io_printer_info_1("", buffer, printer, 0);
2904 if (*needed > offered) {
2906 return ERROR_INSUFFICIENT_BUFFER;
2909 return NT_STATUS_NO_PROBLEMO;
2912 /********************************************************************
2913 enum_all_printers_info_1_network.
2914 *********************************************************************/
2916 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2918 DEBUG(4,("enum_all_printers_info_1_network\n"));
2920 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2923 /********************************************************************
2924 * api_spoolss_enumprinters
2926 * called from api_spoolss_enumprinters (see this to understand)
2927 ********************************************************************/
2929 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2933 int n_services=lp_numservices();
2934 PRINTER_INFO_2 *printers=NULL;
2935 PRINTER_INFO_2 current_prt;
2937 for (snum=0; snum<n_services; snum++) {
2938 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2939 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2941 if (construct_printer_info_2(¤t_prt, snum)) {
2942 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2943 return ERROR_NOT_ENOUGH_MEMORY;
2944 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2945 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2951 /* check the required size. */
2952 for (i=0; i<*returned; i++)
2953 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2955 if (!alloc_buffer_size(buffer, *needed)) {
2956 for (i=0; i<*returned; i++) {
2957 free_devmode(printers[i].devmode);
2959 safe_free(printers);
2960 return ERROR_INSUFFICIENT_BUFFER;
2963 /* fill the buffer with the structures */
2964 for (i=0; i<*returned; i++)
2965 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2968 for (i=0; i<*returned; i++) {
2969 free_devmode(printers[i].devmode);
2971 safe_free(printers);
2973 if (*needed > offered) {
2975 return ERROR_INSUFFICIENT_BUFFER;
2978 return NT_STATUS_NO_PROBLEMO;
2981 /********************************************************************
2982 * handle enumeration of printers at level 1
2983 ********************************************************************/
2984 static uint32 enumprinters_level1( uint32 flags, fstring name,
2985 NEW_BUFFER *buffer, uint32 offered,
2986 uint32 *needed, uint32 *returned)
2988 /* Not all the flags are equals */
2990 if (flags & PRINTER_ENUM_LOCAL)
2991 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2993 if (flags & PRINTER_ENUM_NAME)
2994 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2996 if (flags & PRINTER_ENUM_REMOTE)
2997 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2999 if (flags & PRINTER_ENUM_NETWORK)
3000 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3002 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
3005 /********************************************************************
3006 * handle enumeration of printers at level 2
3007 ********************************************************************/
3008 static uint32 enumprinters_level2( uint32 flags, fstring servername,
3009 NEW_BUFFER *buffer, uint32 offered,
3010 uint32 *needed, uint32 *returned)
3014 fstrcpy(temp, "\\\\");
3015 fstrcat(temp, global_myname);
3017 if (flags & PRINTER_ENUM_LOCAL) {
3018 if (strequal(servername, temp))
3019 return enum_all_printers_info_2(buffer, offered, needed, returned);
3021 return enum_all_printers_info_2(buffer, offered, needed, returned);
3024 if (flags & PRINTER_ENUM_NAME) {
3025 if (strequal(servername, temp))
3026 return enum_all_printers_info_2(buffer, offered, needed, returned);
3028 return ERROR_INVALID_NAME;
3031 if (flags & PRINTER_ENUM_REMOTE)
3032 return ERROR_INVALID_LEVEL;
3034 return NT_STATUS_NO_PROBLEMO;
3037 /********************************************************************
3038 * handle enumeration of printers at level 5
3039 ********************************************************************/
3040 static uint32 enumprinters_level5( uint32 flags, fstring servername,
3041 NEW_BUFFER *buffer, uint32 offered,
3042 uint32 *needed, uint32 *returned)
3044 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3045 return NT_STATUS_NO_PROBLEMO;
3048 /********************************************************************
3049 * api_spoolss_enumprinters
3051 * called from api_spoolss_enumprinters (see this to understand)
3052 ********************************************************************/
3054 uint32 _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3056 uint32 flags = q_u->flags;
3057 UNISTR2 *servername = &q_u->servername;
3058 uint32 level = q_u->level;
3059 NEW_BUFFER *buffer = NULL;
3060 uint32 offered = q_u->offered;
3061 uint32 *needed = &r_u->needed;
3062 uint32 *returned = &r_u->returned;
3066 /* that's an [in out] buffer */
3067 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3068 buffer = r_u->buffer;
3070 DEBUG(4,("_spoolss_enumprinters\n"));
3077 * flags==PRINTER_ENUM_NAME
3078 * if name=="" then enumerates all printers
3079 * if name!="" then enumerate the printer
3080 * flags==PRINTER_ENUM_REMOTE
3081 * name is NULL, enumerate printers
3082 * Level 2: name!="" enumerates printers, name can't be NULL
3083 * Level 3: doesn't exist
3084 * Level 4: does a local registry lookup
3085 * Level 5: same as Level 2
3088 unistr2_to_ascii(name, servername, sizeof(name)-1);
3093 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3095 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3097 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3101 return ERROR_INVALID_LEVEL;
3105 /****************************************************************************
3106 ****************************************************************************/
3107 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3109 PRINTER_INFO_0 *printer=NULL;
3111 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3112 return ERROR_NOT_ENOUGH_MEMORY;
3114 construct_printer_info_0(printer, snum);
3116 /* check the required size. */
3117 *needed += spoolss_size_printer_info_0(printer);
3119 if (!alloc_buffer_size(buffer, *needed)) {
3121 return ERROR_INSUFFICIENT_BUFFER;
3124 /* fill the buffer with the structures */
3125 new_smb_io_printer_info_0("", buffer, printer, 0);
3130 if (*needed > offered) {
3131 return ERROR_INSUFFICIENT_BUFFER;
3134 return NT_STATUS_NO_PROBLEMO;
3137 /****************************************************************************
3138 ****************************************************************************/
3139 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3141 PRINTER_INFO_1 *printer=NULL;
3143 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3144 return ERROR_NOT_ENOUGH_MEMORY;
3146 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3148 /* check the required size. */
3149 *needed += spoolss_size_printer_info_1(printer);
3151 if (!alloc_buffer_size(buffer, *needed)) {
3153 return ERROR_INSUFFICIENT_BUFFER;
3156 /* fill the buffer with the structures */
3157 new_smb_io_printer_info_1("", buffer, printer, 0);
3162 if (*needed > offered) {
3163 return ERROR_INSUFFICIENT_BUFFER;
3166 return NT_STATUS_NO_PROBLEMO;
3169 /****************************************************************************
3170 ****************************************************************************/
3171 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3173 PRINTER_INFO_2 *printer=NULL;
3175 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3176 return ERROR_NOT_ENOUGH_MEMORY;
3178 construct_printer_info_2(printer, snum);
3180 /* check the required size. */
3181 *needed += spoolss_size_printer_info_2(printer);
3183 if (!alloc_buffer_size(buffer, *needed)) {
3184 free_printer_info_2(printer);
3185 return ERROR_INSUFFICIENT_BUFFER;
3188 /* fill the buffer with the structures */
3189 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
3190 free_printer_info_2(printer);
3191 return ERROR_NOT_ENOUGH_MEMORY;
3195 free_printer_info_2(printer);
3197 if (*needed > offered) {
3198 return ERROR_INSUFFICIENT_BUFFER;
3201 return NT_STATUS_NO_PROBLEMO;
3204 /****************************************************************************
3205 ****************************************************************************/
3206 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3208 PRINTER_INFO_3 *printer=NULL;
3210 if (!construct_printer_info_3(&printer, snum))
3211 return ERROR_NOT_ENOUGH_MEMORY;
3213 /* check the required size. */
3214 *needed += spoolss_size_printer_info_3(printer);
3216 if (!alloc_buffer_size(buffer, *needed)) {
3217 free_printer_info_3(printer);
3218 return ERROR_INSUFFICIENT_BUFFER;
3221 /* fill the buffer with the structures */
3222 new_smb_io_printer_info_3("", buffer, printer, 0);
3225 free_printer_info_3(printer);
3227 if (*needed > offered) {
3228 return ERROR_INSUFFICIENT_BUFFER;
3231 return NT_STATUS_NO_PROBLEMO;
3234 /****************************************************************************
3235 ****************************************************************************/
3236 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
3237 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3243 if (!get_printer_snum(handle, &snum))
3244 return ERROR_INVALID_HANDLE;
3248 return getprinter_level_0(snum, buffer, offered, needed);
3250 return getprinter_level_1(snum, buffer, offered, needed);
3252 return getprinter_level_2(snum, buffer, offered, needed);
3254 return getprinter_level_3(snum, buffer, offered, needed);
3256 return ERROR_INVALID_LEVEL;
3260 /********************************************************************
3261 * fill a DRIVER_INFO_1 struct
3262 ********************************************************************/
3263 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3265 init_unistr( &info->name, driver.info_3->name);
3268 /********************************************************************
3269 * construct_printer_driver_info_1
3270 ********************************************************************/
3271 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3273 NT_PRINTER_INFO_LEVEL *printer = NULL;
3274 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3276 ZERO_STRUCT(driver);
3278 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3279 return ERROR_INVALID_PRINTER_NAME;
3281 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3282 return ERROR_UNKNOWN_PRINTER_DRIVER;
3284 fill_printer_driver_info_1(info, driver, servername, architecture);
3286 free_a_printer(&printer,2);
3288 return NT_STATUS_NO_PROBLEMO;
3291 /********************************************************************
3292 * construct_printer_driver_info_2
3293 * fill a printer_info_2 struct
3294 ********************************************************************/
3295 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3299 info->version=driver.info_3->cversion;
3301 init_unistr( &info->name, driver.info_3->name );
3302 init_unistr( &info->architecture, driver.info_3->environment );
3305 if (strlen(driver.info_3->driverpath)) {
3306 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3307 init_unistr( &info->driverpath, temp );
3309 init_unistr( &info->driverpath, "" );
3311 if (strlen(driver.info_3->datafile)) {
3312 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3313 init_unistr( &info->datafile, temp );
3315 init_unistr( &info->datafile, "" );
3317 if (strlen(driver.info_3->configfile)) {
3318 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3319 init_unistr( &info->configfile, temp );
3321 init_unistr( &info->configfile, "" );
3324 /********************************************************************
3325 * construct_printer_driver_info_2
3326 * fill a printer_info_2 struct
3327 ********************************************************************/
3328 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3330 NT_PRINTER_INFO_LEVEL *printer = NULL;
3331 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3333 ZERO_STRUCT(printer);
3334 ZERO_STRUCT(driver);
3336 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3337 return ERROR_INVALID_PRINTER_NAME;
3339 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3340 return ERROR_UNKNOWN_PRINTER_DRIVER;
3342 fill_printer_driver_info_2(info, driver, servername);
3344 free_a_printer(&printer,2);
3346 return NT_STATUS_NO_PROBLEMO;
3349 /********************************************************************
3350 * copy a strings array and convert to UNICODE
3352 * convert an array of ascii string to a UNICODE string
3353 ********************************************************************/
3354 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3361 DEBUG(6,("init_unistr_array\n"));
3365 if (char_array == NULL)
3369 if (!v) v = ""; /* hack to handle null lists */
3371 if (strlen(v) == 0) break;
3372 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3373 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3374 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3375 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3378 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3383 (*uni_array)[j]=0x0000;
3386 DEBUGADD(6,("last one:done\n"));
3389 /********************************************************************
3390 * construct_printer_info_3
3391 * fill a printer_info_3 struct
3392 ********************************************************************/
3393 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3399 info->version=driver.info_3->cversion;
3401 init_unistr( &info->name, driver.info_3->name );
3402 init_unistr( &info->architecture, driver.info_3->environment );
3404 if (strlen(driver.info_3->driverpath)) {
3405 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3406 init_unistr( &info->driverpath, temp );
3408 init_unistr( &info->driverpath, "" );
3410 if (strlen(driver.info_3->datafile)) {
3411 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3412 init_unistr( &info->datafile, temp );
3414 init_unistr( &info->datafile, "" );
3416 if (strlen(driver.info_3->configfile)) {
3417 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3418 init_unistr( &info->configfile, temp );
3420 init_unistr( &info->configfile, "" );
3422 if (strlen(driver.info_3->helpfile)) {
3423 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3424 init_unistr( &info->helpfile, temp );
3426 init_unistr( &info->helpfile, "" );
3428 init_unistr( &info->monitorname, driver.info_3->monitorname );
3429 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3431 info->dependentfiles=NULL;
3432 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3435 /********************************************************************
3436 * construct_printer_info_3
3437 * fill a printer_info_3 struct
3438 ********************************************************************/
3439 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3441 NT_PRINTER_INFO_LEVEL *printer = NULL;
3442 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3444 ZERO_STRUCT(driver);
3446 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3447 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3449 return ERROR_INVALID_PRINTER_NAME;
3451 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3452 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3454 free_a_printer(&printer,2);
3455 return ERROR_UNKNOWN_PRINTER_DRIVER;
3458 fill_printer_driver_info_3(info, driver, servername);
3460 free_a_printer(&printer,2);
3462 return NT_STATUS_NO_PROBLEMO;
3465 /********************************************************************
3466 * construct_printer_info_6
3467 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3468 ********************************************************************/
3470 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3476 memset(&nullstr, '\0', sizeof(fstring));
3478 info->version=driver.info_3->cversion;
3480 init_unistr( &info->name, driver.info_3->name );
3481 init_unistr( &info->architecture, driver.info_3->environment );
3483 if (strlen(driver.info_3->driverpath)) {
3484 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3485 init_unistr( &info->driverpath, temp );
3487 init_unistr( &info->driverpath, "" );
3489 if (strlen(driver.info_3->datafile)) {
3490 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3491 init_unistr( &info->datafile, temp );
3493 init_unistr( &info->datafile, "" );
3495 if (strlen(driver.info_3->configfile)) {
3496 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3497 init_unistr( &info->configfile, temp );
3499 init_unistr( &info->configfile, "" );
3501 if (strlen(driver.info_3->helpfile)) {
3502 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3503 init_unistr( &info->helpfile, temp );
3505 init_unistr( &info->helpfile, "" );
3507 init_unistr( &info->monitorname, driver.info_3->monitorname );
3508 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3510 info->dependentfiles=NULL;
3511 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3513 info->previousdrivernames=NULL;
3514 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3516 info->driver_date.low=0;
3517 info->driver_date.high=0;
3520 info->driver_version_low=0;
3521 info->driver_version_high=0;
3523 init_unistr( &info->mfgname, "");
3524 init_unistr( &info->oem_url, "");
3525 init_unistr( &info->hardware_id, "");
3526 init_unistr( &info->provider, "");
3529 /********************************************************************
3530 * construct_printer_info_6
3531 * fill a printer_info_6 struct
3532 ********************************************************************/
3533 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3535 NT_PRINTER_INFO_LEVEL *printer = NULL;
3536 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3538 ZERO_STRUCT(driver);
3540 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3541 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3543 return ERROR_INVALID_PRINTER_NAME;
3545 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3546 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3549 * Is this a W2k client ?
3553 free_a_printer(&printer,2);
3554 return ERROR_UNKNOWN_PRINTER_DRIVER;
3557 /* Yes - try again with a WinNT driver. */
3559 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3560 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3562 free_a_printer(&printer,2);
3563 return ERROR_UNKNOWN_PRINTER_DRIVER;
3567 fill_printer_driver_info_6(info, driver, servername);
3569 free_a_printer(&printer,2);
3571 return NT_STATUS_NO_PROBLEMO;
3574 /****************************************************************************
3575 ****************************************************************************/
3577 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3579 safe_free(info->dependentfiles);
3582 /****************************************************************************
3583 ****************************************************************************/
3585 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3587 safe_free(info->dependentfiles);
3591 /****************************************************************************
3592 ****************************************************************************/
3593 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3595 DRIVER_INFO_1 *info=NULL;
3598 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3599 return ERROR_NOT_ENOUGH_MEMORY;
3601 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3602 if (status != NT_STATUS_NO_PROBLEMO) {
3607 /* check the required size. */
3608 *needed += spoolss_size_printer_driver_info_1(info);
3610 if (!alloc_buffer_size(buffer, *needed)) {
3612 return ERROR_INSUFFICIENT_BUFFER;
3615 /* fill the buffer with the structures */
3616 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3621 if (*needed > offered)
3622 return ERROR_INSUFFICIENT_BUFFER;
3624 return NT_STATUS_NO_PROBLEMO;
3627 /****************************************************************************
3628 ****************************************************************************/
3629 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3631 DRIVER_INFO_2 *info=NULL;
3634 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3635 return ERROR_NOT_ENOUGH_MEMORY;
3637 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3638 if (status != NT_STATUS_NO_PROBLEMO) {
3643 /* check the required size. */
3644 *needed += spoolss_size_printer_driver_info_2(info);
3646 if (!alloc_buffer_size(buffer, *needed)) {
3648 return ERROR_INSUFFICIENT_BUFFER;
3651 /* fill the buffer with the structures */
3652 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3657 if (*needed > offered)
3658 return ERROR_INSUFFICIENT_BUFFER;
3660 return NT_STATUS_NO_PROBLEMO;
3663 /****************************************************************************
3664 ****************************************************************************/
3665 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3672 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3673 if (status != NT_STATUS_NO_PROBLEMO) {
3677 /* check the required size. */
3678 *needed += spoolss_size_printer_driver_info_3(&info);
3680 if (!alloc_buffer_size(buffer, *needed)) {
3681 free_printer_driver_info_3(&info);
3682 return ERROR_INSUFFICIENT_BUFFER;
3685 /* fill the buffer with the structures */
3686 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3688 free_printer_driver_info_3(&info);
3690 if (*needed > offered)
3691 return ERROR_INSUFFICIENT_BUFFER;
3693 return NT_STATUS_NO_PROBLEMO;
3696 /****************************************************************************
3697 ****************************************************************************/
3698 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3705 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3706 if (status != NT_STATUS_NO_PROBLEMO) {
3710 /* check the required size. */
3711 *needed += spoolss_size_printer_driver_info_6(&info);
3713 if (!alloc_buffer_size(buffer, *needed)) {
3714 free_printer_driver_info_6(&info);
3715 return ERROR_INSUFFICIENT_BUFFER;
3718 /* fill the buffer with the structures */
3719 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3721 free_printer_driver_info_6(&info);
3723 if (*needed > offered)
3724 return ERROR_INSUFFICIENT_BUFFER;
3726 return NT_STATUS_NO_PROBLEMO;
3729 /****************************************************************************
3730 ****************************************************************************/
3731 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3732 uint32 clientmajorversion, uint32 clientminorversion,
3733 NEW_BUFFER *buffer, uint32 offered,
3734 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3737 fstring architecture;
3740 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3743 *servermajorversion=0;
3744 *serverminorversion=0;
3746 pstrcpy(servername, global_myname);
3747 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3749 if (!get_printer_snum(handle, &snum))
3750 return ERROR_INVALID_HANDLE;
3754 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3756 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3758 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3760 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3762 return ERROR_INVALID_LEVEL;
3766 /****************************************************************************
3767 ****************************************************************************/
3768 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3770 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3772 if (OPEN_HANDLE(Printer)) {
3773 Printer->page_started=True;
3777 DEBUG(3,("Error in startpageprinter printer handle\n"));
3778 return ERROR_INVALID_HANDLE;
3781 /****************************************************************************
3782 ****************************************************************************/
3783 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3785 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3787 if (!OPEN_HANDLE(Printer)) {
3788 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3789 return ERROR_INVALID_HANDLE;
3792 Printer->page_started=False;
3794 return NT_STATUS_NO_PROBLEMO;
3798 /********************************************************************
3799 * api_spoolss_getprinter
3800 * called from the spoolss dispatcher
3802 ********************************************************************/
3803 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3804 pipes_struct *p, DOC_INFO *docinfo,
3807 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3811 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3812 struct current_user user;
3814 if (!OPEN_HANDLE(Printer)) {
3815 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3816 return ERROR_INVALID_HANDLE;
3819 get_current_user(&user, p);
3822 * a nice thing with NT is it doesn't listen to what you tell it.
3823 * when asked to send _only_ RAW datas, it tries to send datas
3826 * So I add checks like in NT Server ...
3828 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3829 * there's a bug in NT client-side code, so we'll fix it in the
3830 * server-side code. *nnnnnggggh!*
3833 if (info_1->p_datatype != 0) {
3834 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3835 if (strcmp(datatype, "RAW") != 0) {
3837 return ERROR_INVALID_DATATYPE;
3841 /* get the share number of the printer */
3842 if (!get_printer_snum(handle, &snum)) {
3843 return ERROR_INVALID_HANDLE;
3846 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3848 Printer->jobid = print_job_start(&user, snum, jobname);
3850 /* An error occured in print_job_start() so return an appropriate
3853 if (Printer->jobid == -1) {
3854 return map_nt_error_from_unix(errno);
3857 Printer->document_started=True;
3858 (*jobid) = Printer->jobid;
3863 /********************************************************************
3864 * api_spoolss_getprinter
3865 * called from the spoolss dispatcher
3867 ********************************************************************/
3868 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3870 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3872 if (!OPEN_HANDLE(Printer)) {
3873 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3874 return ERROR_INVALID_HANDLE;
3877 Printer->document_started=False;
3878 print_job_end(Printer->jobid,True);
3879 /* error codes unhandled so far ... */
3884 /****************************************************************************
3885 ****************************************************************************/
3886 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3889 uint32 *buffer_written)
3891 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3893 if (!OPEN_HANDLE(Printer)) {
3894 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3895 return ERROR_INVALID_HANDLE;
3898 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3904 /********************************************************************
3905 * api_spoolss_getprinter
3906 * called from the spoolss dispatcher
3908 ********************************************************************/
3909 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3912 struct current_user user;
3913 int snum, errcode = ERROR_INVALID_FUNCTION;
3914 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3916 get_current_user(&user, p);
3918 if (!OPEN_HANDLE(Printer)) {
3919 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3920 return ERROR_INVALID_HANDLE;
3923 if (!get_printer_snum(handle, &snum))
3924 return ERROR_INVALID_HANDLE;
3927 case PRINTER_CONTROL_PAUSE:
3928 if (print_queue_pause(&user, snum, &errcode)) {
3932 case PRINTER_CONTROL_RESUME:
3933 case PRINTER_CONTROL_UNPAUSE:
3934 if (print_queue_resume(&user, snum, &errcode)) {
3938 case PRINTER_CONTROL_PURGE:
3939 if (print_queue_purge(&user, snum, &errcode)) {
3944 return ERROR_INVALID_LEVEL;
3950 /********************************************************************
3951 * api_spoolss_abortprinter
3952 ********************************************************************/
3954 uint32 _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
3956 POLICY_HND *handle = &q_u->handle;
3958 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3961 /********************************************************************
3962 * called by spoolss_api_setprinter
3963 * when updating a printer description
3964 ********************************************************************/
3965 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3966 const SPOOL_PRINTER_INFO_LEVEL *info,
3967 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3969 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3970 struct current_user user;
3974 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3976 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3977 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3978 OUR_HANDLE(handle)));
3980 result = ERROR_INVALID_HANDLE;
3984 /* NT seems to like setting the security descriptor even though
3985 nothing may have actually changed. This causes annoying
3986 dialog boxes when the user doesn't have permission to change
3987 the security descriptor. */
3989 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
3991 if (DEBUGLEVEL >= 10) {
3995 acl = old_secdesc_ctr->sec->dacl;
3996 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3997 PRINTERNAME(snum), acl->num_aces));
3999 for (i = 0; i < acl->num_aces; i++) {
4002 sid_to_string(sid_str, &acl->ace[i].sid);
4004 DEBUG(10, ("%s 0x%08x\n", sid_str,
4005 acl->ace[i].info.mask));
4008 acl = secdesc_ctr->sec->dacl;
4011 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4012 PRINTERNAME(snum), acl->num_aces));
4014 for (i = 0; i < acl->num_aces; i++) {
4017 sid_to_string(sid_str, &acl->ace[i].sid);
4019 DEBUG(10, ("%s 0x%08x\n", sid_str,
4020 acl->ace[i].info.mask));
4023 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4027 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4029 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4030 result = NT_STATUS_NO_PROBLEMO;
4034 /* Work out which user is performing the operation */
4036 get_current_user(&user, p);
4038 /* Check the user has permissions to change the security
4039 descriptor. By experimentation with two NT machines, the user
4040 requires Full Access to the printer to change security
4043 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4044 result = ERROR_ACCESS_DENIED;
4048 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4055 /********************************************************************
4056 Do Samba sanity checks on a printer info struct.
4057 this has changed purpose: it now "canonicalises" printer
4058 info from a client rather than just checking it is correct
4059 ********************************************************************/
4061 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4063 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4064 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4066 /* we force some elements to "correct" values */
4067 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4068 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4069 global_myname, lp_servicename(snum));
4070 fstrcpy(info->sharename, lp_servicename(snum));
4071 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4072 | PRINTER_ATTRIBUTE_LOCAL \
4073 | PRINTER_ATTRIBUTE_RAW_ONLY \
4074 | PRINTER_ATTRIBUTE_QUEUED ;
4079 /****************************************************************************
4080 ****************************************************************************/
4081 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4083 pid_t local_pid = sys_getpid();
4084 char *cmd = lp_addprinter_cmd();
4089 pstring driverlocation;
4093 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4094 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4098 /* build driver path... only 9X architecture is needed for legacy reasons */
4099 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4101 /* change \ to \\ for the shell */
4102 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4104 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
4105 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4106 cmd, printer->info_2->printername, printer->info_2->sharename,
4107 printer->info_2->portname, printer->info_2->drivername,
4108 printer->info_2->location, driverlocation);
4112 /* Convert script args to unix-codepage */
4113 dos_to_unix(command, True);
4114 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4115 ret = smbrun(command, tmp_file, False);
4116 DEBUGADD(10,("returned [%d]\n", ret));
4124 /* Get lines and convert them back to dos-codepage */
4125 qlines = file_lines_load(tmp_file, &numlines, True);
4126 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4127 DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
4131 /* Set the portname to what the script says the portname should be. */
4132 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4133 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4135 /* Send SIGHUP to process group... is there a better way? */
4140 file_lines_free(qlines);
4144 /* Return true if two devicemodes are equal */
4146 #define DEVMODE_CHECK_INT(field) \
4147 if (d1->field != d2->field) { \
4148 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4149 d1->field, d2->field)); \
4153 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4155 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4158 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4159 return False; /* if either is exclusively NULL are not equal */
4162 if (!strequal(d1->devicename, d2->devicename)) {
4163 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4167 if (!strequal(d1->formname, d2->formname)) {
4168 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4172 DEVMODE_CHECK_INT(specversion);
4173 DEVMODE_CHECK_INT(driverversion);
4174 DEVMODE_CHECK_INT(driverextra);
4175 DEVMODE_CHECK_INT(orientation);
4176 DEVMODE_CHECK_INT(papersize);
4177 DEVMODE_CHECK_INT(paperlength);
4178 DEVMODE_CHECK_INT(paperwidth);
4179 DEVMODE_CHECK_INT(scale);
4180 DEVMODE_CHECK_INT(copies);
4181 DEVMODE_CHECK_INT(defaultsource);
4182 DEVMODE_CHECK_INT(printquality);
4183 DEVMODE_CHECK_INT(color);
4184 DEVMODE_CHECK_INT(duplex);
4185 DEVMODE_CHECK_INT(yresolution);
4186 DEVMODE_CHECK_INT(ttoption);
4187 DEVMODE_CHECK_INT(collate);
4188 DEVMODE_CHECK_INT(logpixels);
4190 DEVMODE_CHECK_INT(fields);
4191 DEVMODE_CHECK_INT(bitsperpel);
4192 DEVMODE_CHECK_INT(pelswidth);
4193 DEVMODE_CHECK_INT(pelsheight);
4194 DEVMODE_CHECK_INT(displayflags);
4195 DEVMODE_CHECK_INT(displayfrequency);
4196 DEVMODE_CHECK_INT(icmmethod);
4197 DEVMODE_CHECK_INT(icmintent);
4198 DEVMODE_CHECK_INT(mediatype);
4199 DEVMODE_CHECK_INT(dithertype);
4200 DEVMODE_CHECK_INT(reserved1);
4201 DEVMODE_CHECK_INT(reserved2);
4202 DEVMODE_CHECK_INT(panningwidth);
4203 DEVMODE_CHECK_INT(panningheight);
4205 /* compare the private data if it exists */
4206 if (!d1->driverextra && !d2->driverextra) goto equal;
4209 DEVMODE_CHECK_INT(driverextra);
4211 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4212 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4217 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4221 /* Return true if two NT_PRINTER_PARAM structures are equal */
4223 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4224 NT_PRINTER_PARAM *p2)
4226 if (!p1 && !p2) goto equal;
4228 if ((!p1 && p2) || (p1 && !p2)) {
4229 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4233 /* Compare lists of printer parameters */
4237 NT_PRINTER_PARAM *q = p1;
4239 /* Find the parameter in the second structure */
4243 if (strequal(p1->value, q->value)) {
4245 if (p1->type != q->type) {
4246 DEBUG(10, ("nt_printer_param_equal():"
4247 "types for %s differ (%d != %d)\n",
4248 p1->value, p1->type,
4253 if (p1->data_len != q->data_len) {
4254 DEBUG(10, ("nt_printer_param_equal():"
4255 "len for %s differs (%d != %d)\n",
4256 p1->value, p1->data_len,
4261 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4264 DEBUG(10, ("nt_printer_param_equal():"
4265 "data for %s differs\n", p1->value));
4275 DEBUG(10, ("nt_printer_param_equal(): param %s "
4276 "does not exist\n", p1->value));
4285 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4289 /********************************************************************
4290 * Called by update_printer when trying to work out whether to
4291 * actually update printer info.
4292 ********************************************************************/
4294 #define PI_CHECK_INT(field) \
4295 if (pi1->field != pi2->field) { \
4296 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4297 pi1->field, pi2->field)); \
4301 #define PI_CHECK_STR(field) \
4302 if (!strequal(pi1->field, pi2->field)) { \
4303 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4304 pi1->field, pi2->field)); \
4308 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4309 NT_PRINTER_INFO_LEVEL *p2)
4311 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4313 /* Trivial conditions */
4315 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4319 if ((!p1 && p2) || (p1 && !p2) ||
4320 (!p1->info_2 && p2->info_2) ||
4321 (p1->info_2 && !p2->info_2)) {
4322 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4327 /* Compare two nt_printer_info_level structures. Don't compare
4328 status or cjobs as they seem to have something to do with the
4334 /* Don't check the attributes as we stomp on the value in
4335 check_printer_ok() anyway. */
4338 PI_CHECK_INT(attributes);
4341 PI_CHECK_INT(priority);
4342 PI_CHECK_INT(default_priority);
4343 PI_CHECK_INT(starttime);
4344 PI_CHECK_INT(untiltime);
4345 PI_CHECK_INT(averageppm);
4347 /* Yuck - don't check the printername or servername as the
4348 add_a_printer() code plays games with them. You can't
4349 change the printername or the sharename through this interface
4352 PI_CHECK_STR(sharename);
4353 PI_CHECK_STR(portname);
4354 PI_CHECK_STR(drivername);
4355 PI_CHECK_STR(comment);
4356 PI_CHECK_STR(location);
4358 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4362 PI_CHECK_STR(sepfile);
4363 PI_CHECK_STR(printprocessor);
4364 PI_CHECK_STR(datatype);
4365 PI_CHECK_STR(parameters);
4367 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4371 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4375 PI_CHECK_INT(changeid);
4376 PI_CHECK_INT(c_setprinter);
4377 PI_CHECK_INT(setuptime);
4380 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4384 /********************************************************************
4385 * called by spoolss_api_setprinter
4386 * when updating a printer description
4387 ********************************************************************/
4389 static uint32 update_printer(POLICY_HND *handle, uint32 level,
4390 const SPOOL_PRINTER_INFO_LEVEL *info,
4391 DEVICEMODE *devmode)
4394 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4395 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4398 DEBUG(8,("update_printer\n"));
4400 result = NT_STATUS_NO_PROBLEMO;
4403 DEBUG(0,("Send a mail to samba@samba.org\n"));
4404 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4405 result = ERROR_INVALID_LEVEL;
4409 if (!OPEN_HANDLE(Printer)) {
4410 result = ERROR_INVALID_HANDLE;
4414 if (!get_printer_snum(handle, &snum)) {
4415 result = ERROR_INVALID_HANDLE;
4419 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4420 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4421 result = ERROR_INVALID_HANDLE;
4425 DEBUGADD(8,("Converting info_2 struct\n"));
4428 * convert_printer_info converts the incoming
4429 * info from the client and overwrites the info
4430 * just read from the tdb in the pointer 'printer'.
4433 convert_printer_info(info, printer, level);
4435 if (info->info_2->devmode_ptr != 0) {
4436 /* we have a valid devmode
4437 convert it and link it*/
4439 DEBUGADD(8,("Converting the devicemode struct\n"));
4440 if (!convert_devicemode(printer->info_2->printername, devmode,
4441 &printer->info_2->devmode)) {
4442 result = ERROR_NOT_ENOUGH_MEMORY;
4447 /* Do sanity check on the requested changes for Samba */
4449 if (!check_printer_ok(printer->info_2, snum)) {
4450 result = ERROR_INVALID_PARAMETER;
4454 /* NT likes to call this function even though nothing has actually
4455 changed. Check this so the user doesn't end up with an
4456 annoying permission denied dialog box. */
4458 if (nt_printer_info_level_equal(printer, old_printer)) {
4459 DEBUG(3, ("printer info has not changed\n"));
4460 result = NT_STATUS_NO_PROBLEMO;
4464 /* Check calling user has permission to update printer description */
4466 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4467 DEBUG(3, ("printer property change denied by security "
4469 result = ERROR_ACCESS_DENIED;
4473 /* Call addprinter hook */
4475 if (*lp_addprinter_cmd() )
4476 if ( !add_printer_hook(printer) ) {
4477 result = ERROR_ACCESS_DENIED;
4481 /* Update printer info */
4483 if (add_a_printer(*printer, 2)!=0) {
4484 /* I don't really know what to return here !!! */
4485 result = ERROR_ACCESS_DENIED;
4490 free_a_printer(&printer, 2);
4491 free_a_printer(&old_printer, 2);
4493 srv_spoolss_sendnotify(handle);
4498 /****************************************************************************
4499 ****************************************************************************/
4500 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
4501 const SPOOL_PRINTER_INFO_LEVEL *info,
4502 DEVMODE_CTR devmode_ctr,
4503 SEC_DESC_BUF *secdesc_ctr,
4504 uint32 command, pipes_struct *p)
4506 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4508 if (!OPEN_HANDLE(Printer)) {
4509 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4510 return ERROR_INVALID_HANDLE;
4513 /* check the level */
4516 return control_printer(handle, command, p);
4518 return update_printer(handle, level, info, devmode_ctr.devmode);
4520 return update_printer_sec(handle, level, info, p,
4523 return ERROR_INVALID_LEVEL;
4527 /****************************************************************************
4528 ****************************************************************************/
4529 uint32 _spoolss_fcpn(POLICY_HND *handle)
4531 Printer_entry *Printer= find_printer_index_by_hnd(handle);
4533 if (!OPEN_HANDLE(Printer)) {
4534 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4535 return ERROR_INVALID_HANDLE;
4538 if (Printer->notify.client_connected==True)
4539 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4540 return ERROR_INVALID_HANDLE;
4542 Printer->notify.flags=0;
4543 Printer->notify.options=0;
4544 Printer->notify.localmachine[0]='\0';
4545 Printer->notify.printerlocal=0;
4546 if (Printer->notify.option)
4547 safe_free(Printer->notify.option->ctr.type);
4548 safe_free(Printer->notify.option);
4549 Printer->notify.option=NULL;
4550 Printer->notify.client_connected=False;
4552 return NT_STATUS_NO_PROBLEMO;
4555 /****************************************************************************
4556 ****************************************************************************/
4557 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
4558 NEW_BUFFER *buffer, uint32 offered,
4562 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4563 returns for AddJob. AddJob
4564 must fail on non-local
4568 /****************************************************************************
4569 ****************************************************************************/
4570 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4571 int position, int snum)
4577 t=gmtime(&queue->time);
4578 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4580 job_info->jobid=queue->job;
4581 init_unistr(&job_info->printername, lp_servicename(snum));
4582 init_unistr(&job_info->machinename, temp_name);
4583 init_unistr(&job_info->username, queue->user);
4584 init_unistr(&job_info->document, queue->file);
4585 init_unistr(&job_info->datatype, "RAW");
4586 init_unistr(&job_info->text_status, "");
4587 job_info->status=nt_printj_status(queue->status);
4588 job_info->priority=queue->priority;
4589 job_info->position=position;
4590 job_info->totalpages=0;
4591 job_info->pagesprinted=0;
4593 make_systemtime(&job_info->submitted, t);
4596 /****************************************************************************
4597 ****************************************************************************/
4598 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4599 int position, int snum,
4600 NT_PRINTER_INFO_LEVEL *ntprinter)
4606 t=gmtime(&queue->time);
4607 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4609 job_info->jobid=queue->job;
4611 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4613 init_unistr(&job_info->printername, chaine);
4615 init_unistr(&job_info->machinename, temp_name);
4616 init_unistr(&job_info->username, queue->user);
4617 init_unistr(&job_info->document, queue->file);
4618 init_unistr(&job_info->notifyname, queue->user);
4619 init_unistr(&job_info->datatype, "RAW");
4620 init_unistr(&job_info->printprocessor, "winprint");
4621 init_unistr(&job_info->parameters, "");
4622 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4623 init_unistr(&job_info->text_status, "");
4625 /* and here the security descriptor */
4627 job_info->status=nt_printj_status(queue->status);
4628 job_info->priority=queue->priority;
4629 job_info->position=position;
4630 job_info->starttime=0;
4631 job_info->untiltime=0;
4632 job_info->totalpages=0;
4633 job_info->size=queue->size;
4634 make_systemtime(&(job_info->submitted), t);
4635 job_info->timeelapsed=0;
4636 job_info->pagesprinted=0;
4638 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4645 /****************************************************************************
4646 Enumjobs at level 1.
4647 ****************************************************************************/
4648 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4649 NEW_BUFFER *buffer, uint32 offered,
4650 uint32 *needed, uint32 *returned)
4655 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4659 return ERROR_NOT_ENOUGH_MEMORY;
4662 for (i=0; i<*returned; i++)
4663 fill_job_info_1(&info[i], &queue[i], i, snum);
4667 /* check the required size. */
4668 for (i=0; i<*returned; i++)
4669 (*needed) += spoolss_size_job_info_1(&info[i]);
4671 if (!alloc_buffer_size(buffer, *needed)) {
4673 return ERROR_INSUFFICIENT_BUFFER;
4676 /* fill the buffer with the structures */
4677 for (i=0; i<*returned; i++)
4678 new_smb_io_job_info_1("", buffer, &info[i], 0);
4683 if (*needed > offered) {
4685 return ERROR_INSUFFICIENT_BUFFER;
4688 return NT_STATUS_NO_PROBLEMO;
4691 /****************************************************************************
4692 Enumjobs at level 2.
4693 ****************************************************************************/
4694 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4695 NEW_BUFFER *buffer, uint32 offered,
4696 uint32 *needed, uint32 *returned)
4698 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4702 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4705 return ERROR_NOT_ENOUGH_MEMORY;
4708 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4710 return ERROR_NOT_ENOUGH_MEMORY;
4713 for (i=0; i<*returned; i++)
4714 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4716 free_a_printer(&ntprinter, 2);
4719 /* check the required size. */
4720 for (i=0; i<*returned; i++)
4721 (*needed) += spoolss_size_job_info_2(&info[i]);
4723 if (!alloc_buffer_size(buffer, *needed)) {
4725 return ERROR_INSUFFICIENT_BUFFER;
4728 /* fill the buffer with the structures */
4729 for (i=0; i<*returned; i++)
4730 new_smb_io_job_info_2("", buffer, &info[i], 0);
4733 for (i = 0; i < *returned; i++)
4734 free_job_info_2(&info[i]);
4738 if (*needed > offered) {
4740 return ERROR_INSUFFICIENT_BUFFER;
4743 return NT_STATUS_NO_PROBLEMO;
4746 /****************************************************************************
4748 ****************************************************************************/
4749 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4750 NEW_BUFFER *buffer, uint32 offered,
4751 uint32 *needed, uint32 *returned)
4754 print_queue_struct *queue=NULL;
4755 print_status_struct prt_status;
4757 DEBUG(4,("_spoolss_enumjobs\n"));
4759 ZERO_STRUCT(prt_status);
4764 if (!get_printer_snum(handle, &snum))
4765 return ERROR_INVALID_HANDLE;
4767 *returned = print_queue_status(snum, &queue, &prt_status);
4768 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4770 if (*returned == 0) {
4772 return NT_STATUS_NO_PROBLEMO;
4777 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4779 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4783 return ERROR_INVALID_LEVEL;
4788 /****************************************************************************
4789 ****************************************************************************/
4790 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4795 /****************************************************************************
4796 ****************************************************************************/
4797 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4798 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4800 struct current_user user;
4801 print_status_struct prt_status;
4802 int snum, errcode = ERROR_INVALID_FUNCTION;
4804 memset(&prt_status, 0, sizeof(prt_status));
4806 if (!get_printer_snum(handle, &snum)) {
4807 return ERROR_INVALID_HANDLE;
4810 if (!print_job_exists(jobid)) {
4811 return ERROR_INVALID_PRINTER_NAME;
4814 get_current_user(&user, p);
4817 case JOB_CONTROL_CANCEL:
4818 case JOB_CONTROL_DELETE:
4819 if (print_job_delete(&user, jobid, &errcode)) {
4823 case JOB_CONTROL_PAUSE:
4824 if (print_job_pause(&user, jobid, &errcode)) {
4828 case JOB_CONTROL_RESTART:
4829 case JOB_CONTROL_RESUME:
4830 if (print_job_resume(&user, jobid, &errcode)) {
4835 return ERROR_INVALID_LEVEL;
4841 /****************************************************************************
4842 Enumerates all printer drivers at level 1.
4843 ****************************************************************************/
4844 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4849 fstring *list = NULL;
4851 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4852 DRIVER_INFO_1 *driver_info_1=NULL;
4856 #define MAX_VERSION 4
4858 for (version=0; version<MAX_VERSION; version++) {
4860 ndrivers=get_ntdrivers(&list, architecture, version);
4861 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4864 return ERROR_NOT_ENOUGH_MEMORY;
4867 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4869 return ERROR_NOT_ENOUGH_MEMORY;
4873 for (i=0; i<ndrivers; i++) {
4875 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4876 ZERO_STRUCT(driver);
4877 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4881 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4882 free_a_printer_driver(driver, 3);
4885 *returned+=ndrivers;
4889 /* check the required size. */
4890 for (i=0; i<*returned; i++) {
4891 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4892 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4895 if (!alloc_buffer_size(buffer, *needed)) {
4896 safe_free(driver_info_1);
4897 return ERROR_INSUFFICIENT_BUFFER;
4900 /* fill the buffer with the form structures */
4901 for (i=0; i<*returned; i++) {
4902 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4903 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4906 safe_free(driver_info_1);
4908 if (*needed > offered) {
4910 return ERROR_INSUFFICIENT_BUFFER;
4913 return NT_STATUS_NO_PROBLEMO;
4916 /****************************************************************************
4917 Enumerates all printer drivers at level 2.
4918 ****************************************************************************/
4919 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4924 fstring *list = NULL;
4926 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4927 DRIVER_INFO_2 *driver_info_2=NULL;
4931 #define MAX_VERSION 4
4933 for (version=0; version<MAX_VERSION; version++) {
4935 ndrivers=get_ntdrivers(&list, architecture, version);
4936 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4939 return ERROR_NOT_ENOUGH_MEMORY;
4942 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4944 return ERROR_NOT_ENOUGH_MEMORY;
4948 for (i=0; i<ndrivers; i++) {
4951 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4952 ZERO_STRUCT(driver);
4953 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4957 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4958 free_a_printer_driver(driver, 3);
4961 *returned+=ndrivers;
4965 /* check the required size. */
4966 for (i=0; i<*returned; i++) {
4967 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4968 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4971 if (!alloc_buffer_size(buffer, *needed)) {
4972 safe_free(driver_info_2);
4973 return ERROR_INSUFFICIENT_BUFFER;
4976 /* fill the buffer with the form structures */
4977 for (i=0; i<*returned; i++) {
4978 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4979 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4982 safe_free(driver_info_2);
4984 if (*needed > offered) {
4986 return ERROR_INSUFFICIENT_BUFFER;
4989 return NT_STATUS_NO_PROBLEMO;
4992 /****************************************************************************
4993 Enumerates all printer drivers at level 3.
4994 ****************************************************************************/
4995 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5000 fstring *list = NULL;
5002 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5003 DRIVER_INFO_3 *driver_info_3=NULL;
5007 #define MAX_VERSION 4
5009 for (version=0; version<MAX_VERSION; version++) {
5011 ndrivers=get_ntdrivers(&list, architecture, version);
5012 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5015 return ERROR_NOT_ENOUGH_MEMORY;
5018 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5020 return ERROR_NOT_ENOUGH_MEMORY;
5024 for (i=0; i<ndrivers; i++) {
5027 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5028 ZERO_STRUCT(driver);
5029 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5033 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5034 free_a_printer_driver(driver, 3);
5037 *returned+=ndrivers;
5041 /* check the required size. */
5042 for (i=0; i<*returned; i++) {
5043 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5044 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5047 if (!alloc_buffer_size(buffer, *needed)) {
5048 safe_free(driver_info_3);
5049 return ERROR_INSUFFICIENT_BUFFER;
5052 /* fill the buffer with the driver structures */
5053 for (i=0; i<*returned; i++) {
5054 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5055 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5058 for (i=0; i<*returned; i++)
5059 safe_free(driver_info_3[i].dependentfiles);
5061 safe_free(driver_info_3);
5063 if (*needed > offered) {
5065 return ERROR_INSUFFICIENT_BUFFER;
5068 return NT_STATUS_NO_PROBLEMO;
5071 /****************************************************************************
5072 Enumerates all printer drivers.
5073 ****************************************************************************/
5074 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
5075 NEW_BUFFER *buffer, uint32 offered,
5076 uint32 *needed, uint32 *returned)
5078 fstring *list = NULL;
5080 fstring architecture;
5082 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5083 fstrcpy(servername, global_myname);
5087 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5091 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5093 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5095 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5099 return ERROR_INVALID_LEVEL;
5103 /****************************************************************************
5104 ****************************************************************************/
5105 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5107 form->flag=list->flag;
5108 init_unistr(&form->name, list->name);
5109 form->width=list->width;
5110 form->length=list->length;
5111 form->left=list->left;
5112 form->top=list->top;
5113 form->right=list->right;
5114 form->bottom=list->bottom;
5117 /****************************************************************************
5118 ****************************************************************************/
5119 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
5120 NEW_BUFFER *buffer, uint32 offered,
5121 uint32 *needed, uint32 *numofforms)
5123 nt_forms_struct *list=NULL;
5128 DEBUG(4,("_new_spoolss_enumforms\n"));
5129 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5130 DEBUGADD(5,("Info level [%d]\n", level));
5132 *numofforms = get_ntforms(&list);
5133 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
5135 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
5139 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5141 return ERROR_NOT_ENOUGH_MEMORY;
5144 /* construct the list of form structures */
5145 for (i=0; i<*numofforms; i++) {
5146 DEBUGADD(6,("Filling form number [%d]\n",i));
5147 fill_form_1(&forms_1[i], &list[i]);
5152 /* check the required size. */
5153 for (i=0; i<*numofforms; i++) {
5154 DEBUGADD(6,("adding form [%d]'s size\n",i));
5155 buffer_size += spoolss_size_form_1(&forms_1[i]);
5158 *needed=buffer_size;
5160 if (!alloc_buffer_size(buffer, buffer_size)){
5162 return ERROR_INSUFFICIENT_BUFFER;
5165 /* fill the buffer with the form structures */
5166 for (i=0; i<*numofforms; i++) {
5167 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5168 new_smb_io_form_1("", buffer, &forms_1[i], 0);
5173 if (*needed > offered) {
5175 return ERROR_INSUFFICIENT_BUFFER;
5178 return NT_STATUS_NO_PROBLEMO;
5182 return ERROR_INVALID_LEVEL;
5187 /****************************************************************************
5188 ****************************************************************************/
5189 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5191 nt_forms_struct *list=NULL;
5197 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5199 DEBUG(4,("_spoolss_getform\n"));
5200 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5201 DEBUGADD(5,("Info level [%d]\n", level));
5203 numofforms = get_ntforms(&list);
5204 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5206 if (numofforms == 0)
5207 return ERROR_NO_MORE_ITEMS;
5212 /* Check if the requested name is in the list of form structures */
5213 for (i=0; i<numofforms; i++) {
5215 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5217 if (strequal(form_name, list[i].name)) {
5218 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5219 fill_form_1(&form_1, &list[i]);
5226 /* check the required size. */
5228 *needed=spoolss_size_form_1(&form_1);
5230 if (!alloc_buffer_size(buffer, buffer_size)){
5231 return ERROR_INSUFFICIENT_BUFFER;
5234 if (*needed > offered) {
5235 return ERROR_INSUFFICIENT_BUFFER;
5238 /* fill the buffer with the form structures */
5239 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5240 new_smb_io_form_1("", buffer, &form_1, 0);
5242 return NT_STATUS_NO_PROBLEMO;
5246 return ERROR_INVALID_LEVEL;
5250 /****************************************************************************
5251 ****************************************************************************/
5252 static void fill_port_1(PORT_INFO_1 *port, char *name)
5254 init_unistr(&port->port_name, name);
5257 /****************************************************************************
5258 ****************************************************************************/
5259 static void fill_port_2(PORT_INFO_2 *port, char *name)
5261 init_unistr(&port->port_name, name);
5262 init_unistr(&port->monitor_name, "Local Monitor");
5263 init_unistr(&port->description, "Local Port");
5264 #define PORT_TYPE_WRITE 1
5265 port->port_type=PORT_TYPE_WRITE;
5269 /****************************************************************************
5271 ****************************************************************************/
5272 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5274 PORT_INFO_1 *ports=NULL;
5277 if (*lp_enumports_cmd()) {
5278 pid_t local_pid = sys_getpid();
5279 char *cmd = lp_enumports_cmd();
5287 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5288 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5292 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5293 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5296 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5297 ret = smbrun(command, tmp_file, False);
5298 DEBUG(10,("Returned [%d]\n", ret));
5301 /* Is this the best error to return here? */
5302 return ERROR_ACCESS_DENIED;
5306 qlines = file_lines_load(tmp_file, &numlines,True);
5307 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5308 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5312 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5313 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5314 file_lines_free(qlines);
5315 return ERROR_NOT_ENOUGH_MEMORY;
5318 for (i=0; i<numlines; i++) {
5319 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5320 fill_port_1(&ports[i], qlines[i]);
5323 file_lines_free(qlines);
5326 *returned = numlines;
5329 *returned = 1; /* Sole Samba port returned. */
5331 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5332 return ERROR_NOT_ENOUGH_MEMORY;
5334 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5336 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5339 /* check the required size. */
5340 for (i=0; i<*returned; i++) {
5341 DEBUGADD(6,("adding port [%d]'s size\n", i));
5342 *needed += spoolss_size_port_info_1(&ports[i]);
5345 if (!alloc_buffer_size(buffer, *needed)) {
5347 return ERROR_INSUFFICIENT_BUFFER;
5350 /* fill the buffer with the ports structures */
5351 for (i=0; i<*returned; i++) {
5352 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5353 new_smb_io_port_1("", buffer, &ports[i], 0);
5358 if (*needed > offered) {
5360 return ERROR_INSUFFICIENT_BUFFER;
5363 return NT_STATUS_NO_PROBLEMO;
5366 /****************************************************************************
5368 ****************************************************************************/
5370 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5372 PORT_INFO_2 *ports=NULL;
5375 if (*lp_enumports_cmd()) {
5376 pid_t local_pid = sys_getpid();
5377 char *cmd = lp_enumports_cmd();
5385 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5386 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5390 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5391 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5394 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5395 ret = smbrun(command, tmp_file, False);
5396 DEBUGADD(10,("returned [%d]\n", ret));
5399 /* Is this the best error to return here? */
5400 return ERROR_ACCESS_DENIED;
5404 qlines = file_lines_load(tmp_file, &numlines,True);
5405 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5406 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5410 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5411 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5412 file_lines_free(qlines);
5413 return ERROR_NOT_ENOUGH_MEMORY;
5416 for (i=0; i<numlines; i++) {
5417 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5418 fill_port_2(&(ports[i]), qlines[i]);
5421 file_lines_free(qlines);
5424 *returned = numlines;
5430 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5431 return ERROR_NOT_ENOUGH_MEMORY;
5433 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5435 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5438 /* check the required size. */
5439 for (i=0; i<*returned; i++) {
5440 DEBUGADD(6,("adding port [%d]'s size\n", i));
5441 *needed += spoolss_size_port_info_2(&ports[i]);
5444 if (!alloc_buffer_size(buffer, *needed)) {
5446 return ERROR_INSUFFICIENT_BUFFER;
5449 /* fill the buffer with the ports structures */
5450 for (i=0; i<*returned; i++) {
5451 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5452 new_smb_io_port_2("", buffer, &ports[i], 0);
5457 if (*needed > offered) {
5459 return ERROR_INSUFFICIENT_BUFFER;
5462 return NT_STATUS_NO_PROBLEMO;
5465 /****************************************************************************
5467 ****************************************************************************/
5468 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
5469 NEW_BUFFER *buffer, uint32 offered,
5470 uint32 *needed, uint32 *returned)
5472 DEBUG(4,("_spoolss_enumports\n"));
5479 return enumports_level_1(buffer, offered, needed, returned);
5481 return enumports_level_2(buffer, offered, needed, returned);
5483 return ERROR_INVALID_LEVEL;
5487 /****************************************************************************
5488 ****************************************************************************/
5489 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5490 const SPOOL_PRINTER_INFO_LEVEL *info,
5491 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5492 uint32 user_switch, const SPOOL_USER_CTR *user,
5495 NT_PRINTER_INFO_LEVEL *printer = NULL;
5499 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5500 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5501 return ERROR_NOT_ENOUGH_MEMORY;
5504 ZERO_STRUCTP(printer);
5506 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5507 convert_printer_info(info, printer, 2);
5509 if (*lp_addprinter_cmd() )
5510 if ( !add_printer_hook(printer) ) {
5511 free_a_printer(&printer,2);
5512 return ERROR_ACCESS_DENIED;
5515 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5516 printer->info_2->sharename);
5518 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5519 free_a_printer(&printer,2);
5520 return ERROR_ACCESS_DENIED;
5523 /* you must be a printer admin to add a new printer */
5524 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5525 free_a_printer(&printer,2);
5526 return ERROR_ACCESS_DENIED;
5530 * Do sanity check on the requested changes for Samba.
5533 if (!check_printer_ok(printer->info_2, snum)) {
5534 free_a_printer(&printer,2);
5535 return ERROR_INVALID_PARAMETER;
5538 /* write the ASCII on disk */
5539 if (add_a_printer(*printer, 2) != 0) {
5540 free_a_printer(&printer,2);
5541 return ERROR_ACCESS_DENIED;
5544 if (!open_printer_hnd(handle, name)) {
5545 /* Handle open failed - remove addition. */
5546 del_a_printer(printer->info_2->sharename);
5547 free_a_printer(&printer,2);
5548 return ERROR_ACCESS_DENIED;
5551 free_a_printer(&printer,2);
5553 srv_spoolss_sendnotify(handle);
5555 return NT_STATUS_NO_PROBLEMO;
5558 /****************************************************************************
5559 ****************************************************************************/
5560 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5561 const SPOOL_PRINTER_INFO_LEVEL *info,
5562 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5563 uint32 user_switch, const SPOOL_USER_CTR *user,
5568 /* we don't handle yet */
5569 /* but I know what to do ... */
5570 return ERROR_INVALID_LEVEL;
5572 return spoolss_addprinterex_level_2(uni_srv_name, info,
5573 unk0, unk1, unk2, unk3,
5574 user_switch, user, handle);
5576 return ERROR_INVALID_LEVEL;
5580 /****************************************************************************
5581 ****************************************************************************/
5582 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5583 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5585 uint32 err = NT_STATUS_NO_PROBLEMO;
5586 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5587 struct current_user user;
5589 ZERO_STRUCT(driver);
5591 get_current_user(&user, p);
5593 convert_printer_driver_info(info, &driver, level);
5595 DEBUG(5,("Cleaning driver's information\n"));
5596 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5599 DEBUG(5,("Moving driver to final destination\n"));
5600 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5602 err = ERROR_ACCESS_DENIED;
5606 if (add_a_printer_driver(driver, level)!=0) {
5607 err = ERROR_ACCESS_DENIED;
5612 free_a_printer_driver(driver, level);
5616 /****************************************************************************
5617 ****************************************************************************/
5618 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5620 init_unistr(&info->name, name);
5623 /****************************************************************************
5624 ****************************************************************************/
5625 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5629 pstring short_archi;
5630 DRIVER_DIRECTORY_1 *info=NULL;
5632 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5634 if (get_short_archi(short_archi, long_archi)==FALSE)
5635 return ERROR_INVALID_ENVIRONMENT;
5637 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5638 return ERROR_NOT_ENOUGH_MEMORY;
5640 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5642 DEBUG(4,("printer driver directory: [%s]\n", path));
5644 fill_driverdir_1(info, path);
5646 *needed += spoolss_size_driverdir_info_1(info);
5648 if (!alloc_buffer_size(buffer, *needed)) {
5650 return ERROR_INSUFFICIENT_BUFFER;
5653 new_smb_io_driverdir_1("", buffer, info, 0);
5657 if (*needed > offered)
5658 return ERROR_INSUFFICIENT_BUFFER;
5660 return NT_STATUS_NO_PROBLEMO;
5663 /****************************************************************************
5664 ****************************************************************************/
5665 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5666 NEW_BUFFER *buffer, uint32 offered,
5669 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5675 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5677 return ERROR_INVALID_LEVEL;
5681 /****************************************************************************
5682 ****************************************************************************/
5683 uint32 _spoolss_enumprinterdata(pipes_struct *p, POLICY_HND *handle, uint32 idx,
5684 uint32 in_value_len, uint32 in_data_len,
5685 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5687 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5689 NT_PRINTER_INFO_LEVEL *printer = NULL;
5694 uint32 biggest_valuesize;
5695 uint32 biggest_datasize;
5697 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5702 ZERO_STRUCT(printer);
5704 *out_max_value_len=0;
5710 *out_max_data_len=0;
5714 DEBUG(5,("spoolss_enumprinterdata\n"));
5716 if (!OPEN_HANDLE(Printer)) {
5717 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5718 return ERROR_INVALID_HANDLE;
5721 if (!get_printer_snum(handle, &snum))
5722 return ERROR_INVALID_HANDLE;
5724 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5725 return ERROR_INVALID_HANDLE;
5728 * The NT machine wants to know the biggest size of value and data
5730 * cf: MSDN EnumPrinterData remark section
5732 if ( (in_value_len==0) && (in_data_len==0) ) {
5733 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5737 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5738 * if this parameter size doesn't exist.
5739 * Ok - my opinion here is that the client is not asking for the greatest
5740 * possible size of all the parameters, but is asking specifically for the size needed
5741 * for this specific parameter. In that case we can remove the loop below and
5742 * simplify this lookup code considerably. JF - comments welcome. JRA.
5745 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5747 free_a_printer(&printer, 2);
5748 return ERROR_NO_MORE_ITEMS;
5756 biggest_valuesize=0;
5759 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5760 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5761 if (data_len > biggest_datasize) biggest_datasize=data_len;
5763 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5771 * I think this is correct, it doesn't break APW and
5772 * allows Gerald's Win32 test programs to work correctly,
5773 * but may need altering.... JRA.
5776 if (param_index == 0) {
5777 /* No parameters found. */
5778 free_a_printer(&printer, 2);
5779 return ERROR_NO_MORE_ITEMS;
5782 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5783 *out_value_len=2*(1+biggest_valuesize);
5784 *out_data_len=biggest_datasize;
5786 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5788 free_a_printer(&printer, 2);
5789 return NT_STATUS_NO_PROBLEMO;
5793 * the value len is wrong in NT sp3
5794 * that's the number of bytes not the number of unicode chars
5797 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5799 free_a_printer(&printer, 2);
5800 return ERROR_NO_MORE_ITEMS;
5803 free_a_printer(&printer, 2);
5807 * - counted in bytes in the request
5808 * - counted in UNICODE chars in the max reply
5809 * - counted in bytes in the real size
5811 * take a pause *before* coding not *during* coding
5814 *out_max_value_len=(in_value_len/sizeof(uint16));
5815 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
5817 return ERROR_NOT_ENOUGH_MEMORY;
5820 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5824 /* the data is counted in bytes */
5825 *out_max_data_len=in_data_len;
5826 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
5828 return ERROR_NOT_ENOUGH_MEMORY;
5831 memcpy(*data_out, data, (size_t)data_len);
5832 *out_data_len=data_len;
5836 return NT_STATUS_NO_PROBLEMO;
5839 /****************************************************************************
5840 ****************************************************************************/
5841 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5842 const UNISTR2 *value,
5847 uint32 numeric_data)
5849 NT_PRINTER_INFO_LEVEL *printer = NULL;
5850 NT_PRINTER_PARAM *param = NULL, old_param;
5852 uint32 status = 0x0;
5853 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5855 DEBUG(5,("spoolss_setprinterdata\n"));
5857 if (!OPEN_HANDLE(Printer)) {
5858 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5859 return ERROR_INVALID_HANDLE;
5862 if (!get_printer_snum(handle, &snum))
5863 return ERROR_INVALID_HANDLE;
5865 status = get_a_printer(&printer, 2, lp_servicename(snum));
5867 return ERROR_INVALID_NAME;
5869 convert_specific_param(¶m, value , type, data, real_len);
5871 /* Check if we are making any changes or not. Return true if
5872 nothing is actually changing. */
5874 ZERO_STRUCT(old_param);
5876 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5877 &old_param.type, (unsigned int *)&old_param.data_len)) {
5879 if (param->type == old_param.type &&
5880 param->data_len == old_param.data_len &&
5881 memcmp(param->data, old_param.data,
5882 old_param.data_len) == 0) {
5884 DEBUG(3, ("setprinterdata hasn't changed\n"));
5885 status = NT_STATUS_NO_PROBLEMO;
5892 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5893 DEBUG(3, ("security descriptor change denied by existing "
5894 "security descriptor\n"));
5895 status = ERROR_ACCESS_DENIED;
5899 unlink_specific_param_if_exist(printer->info_2, param);
5901 add_a_specific_param(printer->info_2, ¶m);
5902 status = mod_a_printer(*printer, 2);
5905 free_a_printer(&printer, 2);
5907 free_nt_printer_param(¶m);
5908 safe_free(old_param.data);
5913 /****************************************************************************
5914 ****************************************************************************/
5916 uint32 _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
5918 POLICY_HND *handle = &q_u->handle;
5919 UNISTR2 *value = &q_u->valuename;
5921 NT_PRINTER_INFO_LEVEL *printer = NULL;
5922 NT_PRINTER_PARAM param;
5924 uint32 status = 0x0;
5925 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5927 DEBUG(5,("spoolss_deleteprinterdata\n"));
5929 if (!OPEN_HANDLE(Printer)) {
5930 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5931 return ERROR_INVALID_HANDLE;
5934 if (!get_printer_snum(handle, &snum))
5935 return ERROR_INVALID_HANDLE;
5937 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5938 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
5939 "change denied by existing security descriptor\n"));
5940 return ERROR_ACCESS_DENIED;
5943 status = get_a_printer(&printer, 2, lp_servicename(snum));
5945 return ERROR_INVALID_NAME;
5947 ZERO_STRUCTP(¶m);
5948 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5950 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5951 status = ERROR_INVALID_PARAMETER;
5953 status = mod_a_printer(*printer, 2);
5955 free_a_printer(&printer, 2);
5959 /****************************************************************************
5960 ****************************************************************************/
5961 uint32 _spoolss_addform( POLICY_HND *handle,
5966 nt_forms_struct *list=NULL;
5967 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5969 DEBUG(5,("spoolss_addform\n"));
5971 if (!OPEN_HANDLE(Printer)) {
5972 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5973 return ERROR_INVALID_HANDLE;
5976 count=get_ntforms(&list);
5977 if(!add_a_form(&list, form, &count))
5978 return ERROR_NOT_ENOUGH_MEMORY;
5979 write_ntforms(&list, count);
5986 /****************************************************************************
5987 ****************************************************************************/
5988 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5992 nt_forms_struct *list=NULL;
5993 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5995 DEBUG(5,("spoolss_deleteform\n"));
5997 if (!OPEN_HANDLE(Printer)) {
5998 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5999 return ERROR_INVALID_HANDLE;
6002 count = get_ntforms(&list);
6003 if(!delete_a_form(&list, form_name, &count, &ret))
6004 return ERROR_INVALID_PARAMETER;
6011 /****************************************************************************
6012 ****************************************************************************/
6013 uint32 _spoolss_setform( POLICY_HND *handle,
6014 const UNISTR2 *uni_name,
6019 nt_forms_struct *list=NULL;
6020 Printer_entry *Printer = find_printer_index_by_hnd(handle);
6022 DEBUG(5,("spoolss_setform\n"));
6024 if (!OPEN_HANDLE(Printer)) {
6025 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6026 return ERROR_INVALID_HANDLE;
6028 count=get_ntforms(&list);
6029 update_a_form(&list, form, count);
6030 write_ntforms(&list, count);
6037 /****************************************************************************
6038 enumprintprocessors level 1.
6039 ****************************************************************************/
6040 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6042 PRINTPROCESSOR_1 *info_1=NULL;
6044 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6045 return ERROR_NOT_ENOUGH_MEMORY;
6049 init_unistr(&info_1->name, "winprint");
6051 *needed += spoolss_size_printprocessor_info_1(info_1);
6053 if (!alloc_buffer_size(buffer, *needed))
6054 return ERROR_INSUFFICIENT_BUFFER;
6056 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6060 if (*needed > offered) {
6062 return ERROR_INSUFFICIENT_BUFFER;
6065 return NT_STATUS_NO_PROBLEMO;
6068 /****************************************************************************
6069 ****************************************************************************/
6070 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
6071 NEW_BUFFER *buffer, uint32 offered,
6072 uint32 *needed, uint32 *returned)
6074 DEBUG(5,("spoolss_enumprintprocessors\n"));
6077 * Enumerate the print processors ...
6079 * Just reply with "winprint", to keep NT happy
6080 * and I can use my nice printer checker.
6088 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6090 return ERROR_INVALID_LEVEL;
6094 /****************************************************************************
6095 enumprintprocdatatypes level 1.
6096 ****************************************************************************/
6097 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6099 PRINTPROCDATATYPE_1 *info_1=NULL;
6101 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6102 return ERROR_NOT_ENOUGH_MEMORY;
6106 init_unistr(&info_1->name, "RAW");
6108 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6110 if (!alloc_buffer_size(buffer, *needed))
6111 return ERROR_INSUFFICIENT_BUFFER;
6113 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6117 if (*needed > offered) {
6119 return ERROR_INSUFFICIENT_BUFFER;
6122 return NT_STATUS_NO_PROBLEMO;
6125 /****************************************************************************
6126 ****************************************************************************/
6127 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
6128 NEW_BUFFER *buffer, uint32 offered,
6129 uint32 *needed, uint32 *returned)
6131 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6138 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6140 return ERROR_INVALID_LEVEL;
6144 /****************************************************************************
6145 enumprintmonitors level 1.
6146 ****************************************************************************/
6147 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6149 PRINTMONITOR_1 *info_1=NULL;
6151 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6152 return ERROR_NOT_ENOUGH_MEMORY;
6156 init_unistr(&info_1->name, "Local Port");
6158 *needed += spoolss_size_printmonitor_info_1(info_1);
6160 if (!alloc_buffer_size(buffer, *needed))
6161 return ERROR_INSUFFICIENT_BUFFER;
6163 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6167 if (*needed > offered) {
6169 return ERROR_INSUFFICIENT_BUFFER;
6172 return NT_STATUS_NO_PROBLEMO;
6175 /****************************************************************************
6176 enumprintmonitors level 2.
6177 ****************************************************************************/
6178 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6180 PRINTMONITOR_2 *info_2=NULL;
6182 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6183 return ERROR_NOT_ENOUGH_MEMORY;
6187 init_unistr(&info_2->name, "Local Port");
6188 init_unistr(&info_2->environment, "Windows NT X86");
6189 init_unistr(&info_2->dll_name, "localmon.dll");
6191 *needed += spoolss_size_printmonitor_info_2(info_2);
6193 if (!alloc_buffer_size(buffer, *needed))
6194 return ERROR_INSUFFICIENT_BUFFER;
6196 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6200 if (*needed > offered) {
6202 return ERROR_INSUFFICIENT_BUFFER;
6205 return NT_STATUS_NO_PROBLEMO;
6208 /****************************************************************************
6209 ****************************************************************************/
6210 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
6211 NEW_BUFFER *buffer, uint32 offered,
6212 uint32 *needed, uint32 *returned)
6214 DEBUG(5,("spoolss_enumprintmonitors\n"));
6217 * Enumerate the print monitors ...
6219 * Just reply with "Local Port", to keep NT happy
6220 * and I can use my nice printer checker.
6228 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6230 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6232 return ERROR_INVALID_LEVEL;
6236 /****************************************************************************
6237 ****************************************************************************/
6238 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6242 JOB_INFO_1 *info_1=NULL;
6244 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6246 if (info_1 == NULL) {
6248 return ERROR_NOT_ENOUGH_MEMORY;
6251 for (i=0; i<count && found==False; i++) {
6252 if (queue[i].job==(int)jobid)
6259 /* I shoud reply something else ... I can't find the good one */
6260 return NT_STATUS_NO_PROBLEMO;
6263 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6267 *needed += spoolss_size_job_info_1(info_1);
6269 if (!alloc_buffer_size(buffer, *needed)) {
6271 return ERROR_INSUFFICIENT_BUFFER;
6274 new_smb_io_job_info_1("", buffer, info_1, 0);
6278 if (*needed > offered)
6279 return ERROR_INSUFFICIENT_BUFFER;
6281 return NT_STATUS_NO_PROBLEMO;
6285 /****************************************************************************
6286 ****************************************************************************/
6287 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6292 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6294 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6296 ZERO_STRUCTP(info_2);
6298 if (info_2 == NULL) {
6300 return ERROR_NOT_ENOUGH_MEMORY;
6303 for (i=0; i<count && found==False; i++) {
6304 if (queue[i].job==(int)jobid)
6311 /* I shoud reply something else ... I can't find the good one */
6312 return NT_STATUS_NO_PROBLEMO;
6315 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6317 return ERROR_NOT_ENOUGH_MEMORY;
6320 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6322 free_a_printer(&ntprinter, 2);
6325 *needed += spoolss_size_job_info_2(info_2);
6327 if (!alloc_buffer_size(buffer, *needed)) {
6329 return ERROR_INSUFFICIENT_BUFFER;
6332 new_smb_io_job_info_2("", buffer, info_2, 0);
6334 free_job_info_2(info_2);
6337 if (*needed > offered)
6338 return ERROR_INSUFFICIENT_BUFFER;
6340 return NT_STATUS_NO_PROBLEMO;
6343 /****************************************************************************
6344 ****************************************************************************/
6345 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
6346 NEW_BUFFER *buffer, uint32 offered,
6351 print_queue_struct *queue=NULL;
6352 print_status_struct prt_status;
6354 DEBUG(5,("spoolss_getjob\n"));
6356 memset(&prt_status, 0, sizeof(prt_status));
6360 if (!get_printer_snum(handle, &snum))
6361 return ERROR_INVALID_HANDLE;
6363 count = print_queue_status(snum, &queue, &prt_status);
6365 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6366 count, prt_status.status, prt_status.message));
6370 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6372 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6375 return ERROR_INVALID_LEVEL;