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)
94 return PRINTER_STATUS_PAUSED;
103 static int nt_printq_status(int v)
107 return PRINTER_STATUS_PAUSED;
116 /****************************************************************************
117 initialise printer handle states...
118 ****************************************************************************/
119 void init_printer_hnd(void)
121 ubi_dlInitList(&Printer_list);
122 ubi_dlInitList(&counter_list);
125 /****************************************************************************
126 create a unique printer handle
127 ****************************************************************************/
128 static void create_printer_hnd(POLICY_HND *hnd)
130 static uint32 prt_hnd_low = 0;
131 static uint32 prt_hnd_high = 0;
133 if (hnd == NULL) return;
135 /* i severely doubt that prt_hnd_high will ever be non-zero... */
137 if (prt_hnd_low == 0) prt_hnd_high++;
139 SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */
140 SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */
141 SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */
142 SIVAL(hnd->data, 12, time(NULL)); /* something random */
143 SIVAL(hnd->data, 16, sys_getpid()); /* something more random */
146 /****************************************************************************
147 find printer index by handle
148 ****************************************************************************/
149 static Printer_entry *find_printer_index_by_hnd(const POLICY_HND *hnd)
151 Printer_entry *find_printer;
153 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
155 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
157 if (memcmp(&(find_printer->printer_hnd), hnd, sizeof(*hnd)) == 0) {
158 DEBUG(4,("Found printer handle \n"));
159 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
164 DEBUG(3,("Whoops, Printer handle not found: "));
165 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
169 /****************************************************************************
171 ****************************************************************************/
172 static void clear_handle(POLICY_HND *hnd)
177 /***************************************************************************
178 Disconnect from the client
179 ****************************************************************************/
180 static BOOL srv_spoolss_replycloseprinter(POLICY_HND *handle)
184 /* weird if the test succeds !!! */
185 if (smb_connections==0) {
186 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
190 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
193 /* if it's the last connection, deconnect the IPC$ share */
194 if (smb_connections==1) {
195 if(!spoolss_disconnect_from_client(&cli))
198 message_deregister(MSG_PRINTER_NOTIFY);
206 /****************************************************************************
207 close printer index by handle
208 ****************************************************************************/
209 static BOOL close_printer_handle(POLICY_HND *hnd)
211 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
213 if (!OPEN_HANDLE(Printer)) {
214 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
218 if (Printer->notify.client_connected==True)
219 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
220 return ERROR_INVALID_HANDLE;
223 Printer->notify.flags=0;
224 Printer->notify.options=0;
225 Printer->notify.localmachine[0]='\0';
226 Printer->notify.printerlocal=0;
227 safe_free(Printer->notify.option);
228 Printer->notify.option=NULL;
229 Printer->notify.client_connected=False;
233 ubi_dlRemThis(&Printer_list, Printer);
240 /****************************************************************************
241 delete a printer given a handle
242 ****************************************************************************/
243 static BOOL delete_printer_handle(POLICY_HND *hnd)
245 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
247 if (!OPEN_HANDLE(Printer)) {
248 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
252 if (del_a_printer(Printer->dev.handlename) != 0) {
253 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
257 if (*lp_deleteprinter_cmd()) {
259 pid_t local_pid = sys_getpid();
260 char *cmd = lp_deleteprinter_cmd();
267 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
268 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
272 /* Printer->dev.handlename equals portname equals sharename */
273 slprintf(command, sizeof(command), "%s \"%s\"", cmd,
274 Printer->dev.handlename);
275 dos_to_unix(command, True); /* Convert printername to unix-codepage */
276 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
279 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
280 ret = smbrun(command, tmp_file, False);
285 DEBUGADD(10,("returned [%d]\n", ret));
286 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
289 /* Send SIGHUP to process group... is there a better way? */
292 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
302 /****************************************************************************
303 return the snum of a printer corresponding to an handle
304 ****************************************************************************/
305 static BOOL get_printer_snum(POLICY_HND *hnd, int *number)
307 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
309 if (!OPEN_HANDLE(Printer)) {
310 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
314 switch (Printer->printer_type) {
315 case PRINTER_HANDLE_IS_PRINTER:
316 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
317 *number = print_queue_snum(Printer->dev.handlename);
318 return (*number != -1);
319 case PRINTER_HANDLE_IS_PRINTSERVER:
326 /****************************************************************************
327 set printer handle type.
328 ****************************************************************************/
329 static BOOL set_printer_hnd_accesstype(POLICY_HND *hnd, uint32 access_required)
331 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
333 if (!OPEN_HANDLE(Printer)) {
334 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
338 DEBUG(4,("Setting printer access=%x\n", access_required));
339 Printer->access = access_required;
343 /****************************************************************************
344 Set printer handle type.
345 Check if it's \\server or \\server\printer
346 ****************************************************************************/
348 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
350 DEBUG(3,("Setting printer type=%s\n", handlename));
352 if ( strlen(handlename) < 3 ) {
353 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
357 /* it's a print server */
358 if (!strchr(handlename+2, '\\')) {
359 DEBUGADD(4,("Printer is a print server\n"));
360 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
364 DEBUGADD(4,("Printer is a printer\n"));
365 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
371 /****************************************************************************
372 Set printer handle name.
373 ****************************************************************************/
375 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
377 NT_PRINTER_INFO_LEVEL *printer = NULL;
379 int n_services=lp_numservices();
383 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
385 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
386 ZERO_STRUCT(Printer->dev.printerservername);
387 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
391 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
394 aprinter=strchr(handlename+2, '\\');
397 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
400 * store the Samba share name in it
401 * in back we have the long printer name
402 * need to iterate all the snum and do a
403 * get_a_printer each time to find the printer
404 * faster to do it here than later.
407 for (snum=0;snum<n_services && found==False;snum++) {
410 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
413 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
415 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
418 printername=strchr(printer->info_2->printername+2, '\\');
421 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
422 printer->info_2->printername, aprinter ));
424 if ( strlen(printername) != strlen(aprinter) ) {
425 free_a_printer(&printer, 2);
429 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
430 free_a_printer(&printer, 2);
438 * if we haven't found a printer with the given handlename
439 * then it can be a share name as you can open both \\server\printer and
444 * we still check if the printer description file exists as NT won't be happy
445 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
449 DEBUGADD(5,("Printer not found, checking for share now\n"));
451 for (snum=0;snum<n_services && found==False;snum++) {
453 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
456 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
458 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
461 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
462 printer->info_2->printername, aprinter ));
464 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
465 free_a_printer(&printer, 2);
469 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
470 free_a_printer(&printer, 2);
479 DEBUGADD(4,("Printer not found\n"));
484 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
485 printer->info_2->printername, lp_servicename(snum),snum));
487 ZERO_STRUCT(Printer->dev.handlename);
488 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
490 free_a_printer(&printer, 2);
495 /****************************************************************************
496 find first available printer slot. creates a printer handle for you.
497 ****************************************************************************/
499 static BOOL open_printer_hnd(POLICY_HND *hnd, char *name)
501 Printer_entry *new_printer;
503 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
505 create_printer_hnd(hnd);
507 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
510 ZERO_STRUCTP(new_printer);
512 new_printer->open = True;
513 new_printer->notify.option=NULL;
515 memcpy(&new_printer->printer_hnd, hnd, sizeof(*hnd));
517 ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
519 if (!set_printer_hnd_printertype(new_printer, name)) {
520 close_printer_handle(hnd);
524 if (!set_printer_hnd_name(new_printer, name)) {
525 close_printer_handle(hnd);
529 DEBUG(5, ("%d printer handles active\n",
530 (int)ubi_dlCount(&Printer_list)));
535 /********************************************************************
536 Return True is the handle is a print server.
537 ********************************************************************/
538 static BOOL handle_is_printserver(const POLICY_HND *handle)
540 Printer_entry *Printer=find_printer_index_by_hnd(handle);
542 if (!OPEN_HANDLE(Printer))
545 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
551 /****************************************************************************
552 allocate more memory for a BUFFER.
553 ****************************************************************************/
554 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
562 /* damn, I'm doing the reverse operation of prs_grow() :) */
563 if (buffer_size < prs_data_size(ps))
566 extra_space = buffer_size - prs_data_size(ps);
569 * save the offset and move to the end of the buffer
570 * prs_grow() checks the extra_space against the offset
572 old_offset=prs_offset(ps);
573 prs_set_offset(ps, prs_data_size(ps));
575 if (!prs_grow(ps, extra_space))
578 prs_set_offset(ps, old_offset);
580 buffer->string_at_end=prs_data_size(ps);
585 /***************************************************************************
586 receive the notify message
587 ****************************************************************************/
588 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
592 Printer_entry *find_printer;
595 fstrcpy(printer,buf);
598 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
602 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
604 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
606 /* Iterate the printer list. */
607 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
610 * if the entry is the given printer or if it's a printerserver
611 * we send the message
614 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
615 if (strcmp(find_printer->dev.handlename, printer))
618 if (find_printer->notify.client_connected==True)
619 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
624 /***************************************************************************
626 ****************************************************************************/
627 static BOOL srv_spoolss_sendnotify(POLICY_HND *handle)
631 Printer_entry *Printer=find_printer_index_by_hnd(handle);
633 if (!OPEN_HANDLE(Printer)) {
634 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
638 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
639 fstrcpy(printer, Printer->dev.handlename);
641 fstrcpy(printer, "");
643 /*srv_spoolss_receive_message(printer);*/
644 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
646 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
651 /********************************************************************
652 * spoolss_open_printer
654 * called from the spoolss dispatcher
655 ********************************************************************/
656 uint32 _spoolss_open_printer_ex( const UNISTR2 *printername,
657 const PRINTER_DEFAULT *printer_default,
658 uint32 user_switch, SPOOL_USER_CTR user_ctr,
661 uint32 result = NT_STATUS_NO_PROBLEMO;
662 SEC_DESC_BUF *sec_desc = NULL;
663 uint32 acc_granted, status;
665 extern struct current_user current_user;
667 if (printername == NULL) {
668 result = ERROR_INVALID_PRINTER_NAME;
672 /* some sanity check because you can open a printer or a print server */
673 /* aka: \\server\printer or \\server */
674 unistr2_to_ascii(name, printername, sizeof(name)-1);
676 DEBUGADD(3,("checking name: %s\n",name));
678 if (!open_printer_hnd(handle, name)) {
679 result = ERROR_INVALID_PRINTER_NAME;
684 if (printer_default->datatype_ptr != NULL)
686 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
687 set_printer_hnd_datatype(handle, datatype);
690 set_printer_hnd_datatype(handle, "");
693 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
694 close_printer_handle(handle);
695 result = ERROR_ACCESS_DENIED;
699 /* Disallow MS AddPrinterWizard if parameter disables it. A Win2k
700 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
701 Then both Win2k and WinNT clients try an OpenPrinterEx with
702 SERVER_ALL_ACCESS, which we force to fail. Then they try
703 OpenPrinterEx with SERVER_READ which we allow. This lets the
704 client view printer folder, but does not show the MSAPW.
706 Note: this test needs code to check access rights here too. Jeremy
707 could you look at this? */
709 if (handle_is_printserver(handle) &&
710 !lp_ms_add_printer_wizard()) {
711 if (printer_default->access_required == 0) {
714 else if (printer_default->access_required != (SERVER_READ)) {
715 close_printer_handle(handle);
716 result = ERROR_ACCESS_DENIED;
721 /* NT doesn't let us connect to a printer if the connecting user
722 doesn't have print permission. If no security descriptor just
725 if (!nt_printing_getsec(name, &sec_desc)) {
729 /* Yuck - we should use the pipe_user rather than current_user but
730 it doesn't seem to be filled in correctly. )-: */
732 map_printer_permissions(sec_desc->sec);
734 if (!se_access_check(sec_desc->sec, ¤t_user, PRINTER_ACCESS_USE,
735 &acc_granted, &status)) {
736 DEBUG(3, ("access DENIED for printer open\n"));
737 close_printer_handle(handle);
738 result = ERROR_ACCESS_DENIED;
743 free_sec_desc_buf(&sec_desc);
748 /****************************************************************************
749 ****************************************************************************/
750 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
751 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
755 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
764 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
765 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
769 printer->info_3=NULL;
770 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
773 printer->info_6=NULL;
774 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
783 static BOOL convert_devicemode(const DEVICEMODE *devmode, NT_DEVICEMODE *nt_devmode)
785 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
786 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
788 nt_devmode->specversion=devmode->specversion;
789 nt_devmode->driverversion=devmode->driverversion;
790 nt_devmode->size=devmode->size;
791 nt_devmode->driverextra=devmode->driverextra;
792 nt_devmode->fields=devmode->fields;
793 nt_devmode->orientation=devmode->orientation;
794 nt_devmode->papersize=devmode->papersize;
795 nt_devmode->paperlength=devmode->paperlength;
796 nt_devmode->paperwidth=devmode->paperwidth;
797 nt_devmode->scale=devmode->scale;
798 nt_devmode->copies=devmode->copies;
799 nt_devmode->defaultsource=devmode->defaultsource;
800 nt_devmode->printquality=devmode->printquality;
801 nt_devmode->color=devmode->color;
802 nt_devmode->duplex=devmode->duplex;
803 nt_devmode->yresolution=devmode->yresolution;
804 nt_devmode->ttoption=devmode->ttoption;
805 nt_devmode->collate=devmode->collate;
807 nt_devmode->logpixels=devmode->logpixels;
808 nt_devmode->bitsperpel=devmode->bitsperpel;
809 nt_devmode->pelswidth=devmode->pelswidth;
810 nt_devmode->pelsheight=devmode->pelsheight;
811 nt_devmode->displayflags=devmode->displayflags;
812 nt_devmode->displayfrequency=devmode->displayfrequency;
813 nt_devmode->icmmethod=devmode->icmmethod;
814 nt_devmode->icmintent=devmode->icmintent;
815 nt_devmode->mediatype=devmode->mediatype;
816 nt_devmode->dithertype=devmode->dithertype;
817 nt_devmode->reserved1=devmode->reserved1;
818 nt_devmode->reserved2=devmode->reserved2;
819 nt_devmode->panningwidth=devmode->panningwidth;
820 nt_devmode->panningheight=devmode->panningheight;
822 safe_free(nt_devmode->private);
823 if (nt_devmode->driverextra != 0) {
824 /* if we had a previous private delete it and make a new one */
825 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
827 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
830 nt_devmode->private = NULL;
836 /********************************************************************
837 * api_spoolss_closeprinter
838 ********************************************************************/
839 uint32 _spoolss_closeprinter(POLICY_HND *handle)
841 Printer_entry *Printer=find_printer_index_by_hnd(handle);
843 if (Printer && Printer->document_started)
844 _spoolss_enddocprinter(handle); /* print job was not closed */
846 if (!close_printer_handle(handle))
847 return ERROR_INVALID_HANDLE;
849 return NT_STATUS_NO_PROBLEMO;
852 /********************************************************************
853 * api_spoolss_deleteprinter
854 ********************************************************************/
855 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
857 Printer_entry *Printer=find_printer_index_by_hnd(handle);
859 if (Printer && Printer->document_started)
860 _spoolss_enddocprinter(handle); /* print job was not closed */
862 if (!delete_printer_handle(handle))
863 return ERROR_INVALID_HANDLE;
865 srv_spoolss_sendnotify(handle);
867 return NT_STATUS_NO_PROBLEMO;
870 /********************************************************************
871 GetPrinterData on a printer server Handle.
872 ********************************************************************/
873 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
877 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
879 if (!strcmp(value, "BeepEnabled")) {
881 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
883 SIVAL(*data, 0, 0x01);
888 if (!strcmp(value, "EventLog")) {
890 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
892 SIVAL(*data, 0, 0x1B);
897 if (!strcmp(value, "NetPopup")) {
899 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
901 SIVAL(*data, 0, 0x01);
906 if (!strcmp(value, "MajorVersion")) {
908 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
910 SIVAL(*data, 0, 0x02);
915 if (!strcmp(value, "DefaultSpoolDirectory")) {
916 pstring string="You are using a Samba server";
918 *needed = 2*(strlen(string)+1);
919 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
921 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
923 /* it's done by hand ready to go on the wire */
924 for (i=0; i<strlen(string); i++) {
925 (*data)[2*i]=string[i];
931 if (!strcmp(value, "Architecture")) {
932 pstring string="Windows NT x86";
934 *needed = 2*(strlen(string)+1);
935 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
937 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
938 for (i=0; i<strlen(string); i++) {
939 (*data)[2*i]=string[i];
948 /********************************************************************
949 GetPrinterData on a printer Handle.
950 ********************************************************************/
951 static BOOL getprinterdata_printer(POLICY_HND *handle,
952 fstring value, uint32 *type,
953 uint8 **data, uint32 *needed, uint32 in_size )
955 NT_PRINTER_INFO_LEVEL *printer = NULL;
959 Printer_entry *Printer = find_printer_index_by_hnd(handle);
961 DEBUG(5,("getprinterdata_printer\n"));
963 if (!OPEN_HANDLE(Printer)) {
964 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
968 if(!get_printer_snum(handle, &snum))
971 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
974 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
975 free_a_printer(&printer, 2);
979 free_a_printer(&printer, 2);
981 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
984 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
988 memset(*data, 0, in_size *sizeof(uint8));
989 /* copy the min(in_size, len) */
990 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
997 DEBUG(5,("getprinterdata_printer:copy done\n"));
1004 /********************************************************************
1005 * spoolss_getprinterdata
1006 ********************************************************************/
1007 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
1016 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1019 * Reminder: when it's a string, the length is in BYTES
1020 * even if UNICODE is negociated.
1027 /* in case of problem, return some default values */
1031 DEBUG(4,("_spoolss_getprinterdata\n"));
1033 if (!OPEN_HANDLE(Printer)) {
1034 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1035 return ERROR_NOT_ENOUGH_MEMORY;
1036 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1037 return ERROR_INVALID_HANDLE;
1040 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1042 if (handle_is_printserver(handle))
1043 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1045 found=getprinterdata_printer(handle, value, type, data, needed, *out_size);
1048 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1049 /* reply this param doesn't exist */
1051 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
1052 return ERROR_NOT_ENOUGH_MEMORY;
1053 memset(*data, '\0', *out_size*sizeof(uint8));
1058 return ERROR_INVALID_PARAMETER;
1061 if (*needed > *out_size)
1062 return ERROR_MORE_DATA;
1064 return NT_STATUS_NO_PROBLEMO;
1067 /***************************************************************************
1068 connect to the client
1069 ****************************************************************************/
1070 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1075 * If it's the first connection, contact the client
1076 * and connect to the IPC$ share anonumously
1078 if (smb_connections==0) {
1079 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1081 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1087 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1093 /********************************************************************
1095 * ReplyFindFirstPrinterChangeNotifyEx
1097 * jfmxxxx: before replying OK: status=0
1098 * should do a rpc call to the workstation asking ReplyOpenPrinter
1099 * have to code it, later.
1101 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1102 * called from api_spoolss_rffpcnex
1103 ********************************************************************/
1104 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1105 const UNISTR2 *localmachine, uint32 printerlocal,
1106 SPOOL_NOTIFY_OPTION *option)
1108 /* store the notify value in the printer struct */
1110 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1112 if (!OPEN_HANDLE(Printer)) {
1113 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1114 return ERROR_INVALID_HANDLE;
1117 Printer->notify.flags=flags;
1118 Printer->notify.options=options;
1119 Printer->notify.printerlocal=printerlocal;
1120 Printer->notify.option=option;
1121 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1123 /* connect to the client machine and send a ReplyOpenPrinter */
1124 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1125 Printer->notify.printerlocal, 1,
1126 &Printer->notify.client_hnd))
1127 Printer->notify.client_connected=True;
1129 return NT_STATUS_NO_PROBLEMO;
1132 /*******************************************************************
1133 * fill a notify_info_data with the servername
1134 ********************************************************************/
1135 static void spoolss_notify_server_name(int snum,
1136 SPOOL_NOTIFY_INFO_DATA *data,
1137 print_queue_struct *queue,
1138 NT_PRINTER_INFO_LEVEL *printer,
1139 TALLOC_CTX *mem_ctx)
1141 pstring temp_name, temp;
1144 snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1146 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1148 data->notify_data.data.length = len / 2 - 1;
1149 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1151 if (!data->notify_data.data.string) {
1152 data->notify_data.data.length = 0;
1156 memcpy(data->notify_data.data.string, temp, len);
1159 /*******************************************************************
1160 * fill a notify_info_data with the printername (not including the servername).
1161 ********************************************************************/
1162 static void spoolss_notify_printer_name(int snum,
1163 SPOOL_NOTIFY_INFO_DATA *data,
1164 print_queue_struct *queue,
1165 NT_PRINTER_INFO_LEVEL *printer,
1166 TALLOC_CTX *mem_ctx)
1171 /* the notify name should not contain the \\server\ part */
1172 char *p = strrchr(printer->info_2->printername, '\\');
1175 p = printer->info_2->printername;
1180 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1182 data->notify_data.data.length = len / 2 - 1;
1183 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1185 if (!data->notify_data.data.string) {
1186 data->notify_data.data.length = 0;
1190 memcpy(data->notify_data.data.string, temp, len);
1193 /*******************************************************************
1194 * fill a notify_info_data with the servicename
1195 ********************************************************************/
1196 static void spoolss_notify_share_name(int snum,
1197 SPOOL_NOTIFY_INFO_DATA *data,
1198 print_queue_struct *queue,
1199 NT_PRINTER_INFO_LEVEL *printer,
1200 TALLOC_CTX *mem_ctx)
1205 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1206 sizeof(temp) - 2, True);
1208 data->notify_data.data.length = len / 2 - 1;
1209 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1211 if (!data->notify_data.data.string) {
1212 data->notify_data.data.length = 0;
1216 memcpy(data->notify_data.data.string, temp, len);
1219 /*******************************************************************
1220 * fill a notify_info_data with the port name
1221 ********************************************************************/
1222 static void spoolss_notify_port_name(int snum,
1223 SPOOL_NOTIFY_INFO_DATA *data,
1224 print_queue_struct *queue,
1225 NT_PRINTER_INFO_LEVEL *printer,
1226 TALLOC_CTX *mem_ctx)
1231 /* even if it's strange, that's consistant in all the code */
1233 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1234 sizeof(temp) - 2, True);
1236 data->notify_data.data.length = len / 2 - 1;
1237 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1239 if (!data->notify_data.data.string) {
1240 data->notify_data.data.length = 0;
1244 memcpy(data->notify_data.data.string, temp, len);
1247 /*******************************************************************
1248 * fill a notify_info_data with the printername
1249 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1250 * but it doesn't exist, have to see what to do
1251 ********************************************************************/
1252 static void spoolss_notify_driver_name(int snum,
1253 SPOOL_NOTIFY_INFO_DATA *data,
1254 print_queue_struct *queue,
1255 NT_PRINTER_INFO_LEVEL *printer,
1256 TALLOC_CTX *mem_ctx)
1261 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1262 sizeof(temp) - 2, True);
1264 data->notify_data.data.length = len / 2 - 1;
1265 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1267 if (!data->notify_data.data.string) {
1268 data->notify_data.data.length = 0;
1272 memcpy(data->notify_data.data.string, temp, len);
1275 /*******************************************************************
1276 * fill a notify_info_data with the comment
1277 ********************************************************************/
1278 static void spoolss_notify_comment(int snum,
1279 SPOOL_NOTIFY_INFO_DATA *data,
1280 print_queue_struct *queue,
1281 NT_PRINTER_INFO_LEVEL *printer,
1282 TALLOC_CTX *mem_ctx)
1287 if (*printer->info_2->comment == '\0')
1288 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1289 sizeof(temp) - 2, True);
1291 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1292 sizeof(temp) - 2, True);
1294 data->notify_data.data.length = len / 2 - 1;
1295 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1297 if (!data->notify_data.data.string) {
1298 data->notify_data.data.length = 0;
1302 memcpy(data->notify_data.data.string, temp, len);
1305 /*******************************************************************
1306 * fill a notify_info_data with the comment
1307 * jfm:xxxx incorrect, have to create a new smb.conf option
1308 * location = "Room 1, floor 2, building 3"
1309 ********************************************************************/
1310 static void spoolss_notify_location(int snum,
1311 SPOOL_NOTIFY_INFO_DATA *data,
1312 print_queue_struct *queue,
1313 NT_PRINTER_INFO_LEVEL *printer,
1314 TALLOC_CTX *mem_ctx)
1319 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1320 sizeof(temp) - 2, True);
1322 data->notify_data.data.length = len / 2 - 1;
1323 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1325 if (!data->notify_data.data.string) {
1326 data->notify_data.data.length = 0;
1330 memcpy(data->notify_data.data.string, temp, len);
1333 /*******************************************************************
1334 * fill a notify_info_data with the device mode
1335 * jfm:xxxx don't to it for know but that's a real problem !!!
1336 ********************************************************************/
1337 static void spoolss_notify_devmode(int snum,
1338 SPOOL_NOTIFY_INFO_DATA *data,
1339 print_queue_struct *queue,
1340 NT_PRINTER_INFO_LEVEL *printer,
1341 TALLOC_CTX *mem_ctx)
1345 /*******************************************************************
1346 * fill a notify_info_data with the separator file name
1347 * jfm:xxxx just return no file could add an option to smb.conf
1348 * separator file = "separator.txt"
1349 ********************************************************************/
1350 static void spoolss_notify_sepfile(int snum,
1351 SPOOL_NOTIFY_INFO_DATA *data,
1352 print_queue_struct *queue,
1353 NT_PRINTER_INFO_LEVEL *printer,
1354 TALLOC_CTX *mem_ctx)
1359 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1360 sizeof(temp) - 2, True);
1362 data->notify_data.data.length = len / 2 - 1;
1363 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1365 if (!data->notify_data.data.string) {
1366 data->notify_data.data.length = 0;
1370 memcpy(data->notify_data.data.string, temp, len);
1373 /*******************************************************************
1374 * fill a notify_info_data with the print processor
1375 * jfm:xxxx return always winprint to indicate we don't do anything to it
1376 ********************************************************************/
1377 static void spoolss_notify_print_processor(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, printer->info_2->printprocessor,
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 print processor options
1402 * jfm:xxxx send an empty string
1403 ********************************************************************/
1404 static void spoolss_notify_parameters(int snum,
1405 SPOOL_NOTIFY_INFO_DATA *data,
1406 print_queue_struct *queue,
1407 NT_PRINTER_INFO_LEVEL *printer,
1408 TALLOC_CTX *mem_ctx)
1413 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1414 sizeof(temp) - 2, True);
1416 data->notify_data.data.length = len / 2 - 1;
1417 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1419 if (!data->notify_data.data.string) {
1420 data->notify_data.data.length = 0;
1424 memcpy(data->notify_data.data.string, temp, len);
1427 /*******************************************************************
1428 * fill a notify_info_data with the data type
1429 * jfm:xxxx always send RAW as data type
1430 ********************************************************************/
1431 static void spoolss_notify_datatype(int snum,
1432 SPOOL_NOTIFY_INFO_DATA *data,
1433 print_queue_struct *queue,
1434 NT_PRINTER_INFO_LEVEL *printer,
1435 TALLOC_CTX *mem_ctx)
1440 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1441 sizeof(pstring) - 2, True);
1443 data->notify_data.data.length = len / 2 - 1;
1444 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1446 if (!data->notify_data.data.string) {
1447 data->notify_data.data.length = 0;
1451 memcpy(data->notify_data.data.string, temp, len);
1454 /*******************************************************************
1455 * fill a notify_info_data with the security descriptor
1456 * jfm:xxxx send an null pointer to say no security desc
1457 * have to implement security before !
1458 ********************************************************************/
1459 static void spoolss_notify_security_desc(int snum,
1460 SPOOL_NOTIFY_INFO_DATA *data,
1461 print_queue_struct *queue,
1462 NT_PRINTER_INFO_LEVEL *printer,
1463 TALLOC_CTX *mem_ctx)
1465 data->notify_data.data.length=0;
1466 data->notify_data.data.string = NULL;
1469 /*******************************************************************
1470 * fill a notify_info_data with the attributes
1471 * jfm:xxxx a samba printer is always shared
1472 ********************************************************************/
1473 static void spoolss_notify_attributes(int snum,
1474 SPOOL_NOTIFY_INFO_DATA *data,
1475 print_queue_struct *queue,
1476 NT_PRINTER_INFO_LEVEL *printer,
1477 TALLOC_CTX *mem_ctx)
1479 data->notify_data.value[0] = printer->info_2->attributes;
1482 /*******************************************************************
1483 * fill a notify_info_data with the priority
1484 ********************************************************************/
1485 static void spoolss_notify_priority(int snum,
1486 SPOOL_NOTIFY_INFO_DATA *data,
1487 print_queue_struct *queue,
1488 NT_PRINTER_INFO_LEVEL *printer,
1489 TALLOC_CTX *mem_ctx)
1491 data->notify_data.value[0] = printer->info_2->priority;
1494 /*******************************************************************
1495 * fill a notify_info_data with the default priority
1496 ********************************************************************/
1497 static void spoolss_notify_default_priority(int snum,
1498 SPOOL_NOTIFY_INFO_DATA *data,
1499 print_queue_struct *queue,
1500 NT_PRINTER_INFO_LEVEL *printer,
1501 TALLOC_CTX *mem_ctx)
1503 data->notify_data.value[0] = printer->info_2->default_priority;
1506 /*******************************************************************
1507 * fill a notify_info_data with the start time
1508 ********************************************************************/
1509 static void spoolss_notify_start_time(int snum,
1510 SPOOL_NOTIFY_INFO_DATA *data,
1511 print_queue_struct *queue,
1512 NT_PRINTER_INFO_LEVEL *printer,
1513 TALLOC_CTX *mem_ctx)
1515 data->notify_data.value[0] = printer->info_2->starttime;
1518 /*******************************************************************
1519 * fill a notify_info_data with the until time
1520 ********************************************************************/
1521 static void spoolss_notify_until_time(int snum,
1522 SPOOL_NOTIFY_INFO_DATA *data,
1523 print_queue_struct *queue,
1524 NT_PRINTER_INFO_LEVEL *printer,
1525 TALLOC_CTX *mem_ctx)
1527 data->notify_data.value[0] = printer->info_2->untiltime;
1530 /*******************************************************************
1531 * fill a notify_info_data with the status
1532 ********************************************************************/
1533 static void spoolss_notify_status(int snum,
1534 SPOOL_NOTIFY_INFO_DATA *data,
1535 print_queue_struct *queue,
1536 NT_PRINTER_INFO_LEVEL *printer,
1537 TALLOC_CTX *mem_ctx)
1541 print_queue_struct *q=NULL;
1542 print_status_struct status;
1544 memset(&status, 0, sizeof(status));
1545 count = print_queue_status(snum, &q, &status);
1546 data->notify_data.value[0]=(uint32) status.status;
1550 /*******************************************************************
1551 * fill a notify_info_data with the number of jobs queued
1552 ********************************************************************/
1553 static void spoolss_notify_cjobs(int snum,
1554 SPOOL_NOTIFY_INFO_DATA *data,
1555 print_queue_struct *queue,
1556 NT_PRINTER_INFO_LEVEL *printer,
1557 TALLOC_CTX *mem_ctx)
1559 print_queue_struct *q=NULL;
1560 print_status_struct status;
1562 memset(&status, 0, sizeof(status));
1563 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1567 /*******************************************************************
1568 * fill a notify_info_data with the average ppm
1569 ********************************************************************/
1570 static void spoolss_notify_average_ppm(int snum,
1571 SPOOL_NOTIFY_INFO_DATA *data,
1572 print_queue_struct *queue,
1573 NT_PRINTER_INFO_LEVEL *printer,
1574 TALLOC_CTX *mem_ctx)
1576 /* always respond 8 pages per minutes */
1577 /* a little hard ! */
1578 data->notify_data.value[0] = printer->info_2->averageppm;
1581 /*******************************************************************
1582 * fill a notify_info_data with username
1583 ********************************************************************/
1584 static void spoolss_notify_username(int snum,
1585 SPOOL_NOTIFY_INFO_DATA *data,
1586 print_queue_struct *queue,
1587 NT_PRINTER_INFO_LEVEL *printer,
1588 TALLOC_CTX *mem_ctx)
1593 len = (uint32)dos_PutUniCode(temp, queue->user,
1594 sizeof(temp) - 2, True);
1596 data->notify_data.data.length = len / 2 - 1;
1597 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1599 if (!data->notify_data.data.string) {
1600 data->notify_data.data.length = 0;
1604 memcpy(data->notify_data.data.string, temp, len);
1607 /*******************************************************************
1608 * fill a notify_info_data with job status
1609 ********************************************************************/
1610 static void spoolss_notify_job_status(int snum,
1611 SPOOL_NOTIFY_INFO_DATA *data,
1612 print_queue_struct *queue,
1613 NT_PRINTER_INFO_LEVEL *printer,
1614 TALLOC_CTX *mem_ctx)
1616 data->notify_data.value[0]=nt_printj_status(queue->status);
1619 /*******************************************************************
1620 * fill a notify_info_data with job name
1621 ********************************************************************/
1622 static void spoolss_notify_job_name(int snum,
1623 SPOOL_NOTIFY_INFO_DATA *data,
1624 print_queue_struct *queue,
1625 NT_PRINTER_INFO_LEVEL *printer,
1626 TALLOC_CTX *mem_ctx)
1631 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1634 data->notify_data.data.length = len / 2 - 1;
1635 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1637 if (!data->notify_data.data.string) {
1638 data->notify_data.data.length = 0;
1642 memcpy(data->notify_data.data.string, temp, len);
1645 /*******************************************************************
1646 * fill a notify_info_data with job status
1647 ********************************************************************/
1648 static void spoolss_notify_job_status_string(int snum,
1649 SPOOL_NOTIFY_INFO_DATA *data,
1650 print_queue_struct *queue,
1651 NT_PRINTER_INFO_LEVEL *printer,
1652 TALLOC_CTX *mem_ctx)
1654 char *p = "unknown";
1658 switch (queue->status) {
1663 p = ""; /* NT provides the paused string */
1673 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1675 data->notify_data.data.length = len / 2 - 1;
1676 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1678 if (!data->notify_data.data.string) {
1679 data->notify_data.data.length = 0;
1683 memcpy(data->notify_data.data.string, temp, len);
1686 /*******************************************************************
1687 * fill a notify_info_data with job time
1688 ********************************************************************/
1689 static void spoolss_notify_job_time(int snum,
1690 SPOOL_NOTIFY_INFO_DATA *data,
1691 print_queue_struct *queue,
1692 NT_PRINTER_INFO_LEVEL *printer,
1693 TALLOC_CTX *mem_ctx)
1695 data->notify_data.value[0]=0x0;
1698 /*******************************************************************
1699 * fill a notify_info_data with job size
1700 ********************************************************************/
1701 static void spoolss_notify_job_size(int snum,
1702 SPOOL_NOTIFY_INFO_DATA *data,
1703 print_queue_struct *queue,
1704 NT_PRINTER_INFO_LEVEL *printer,
1705 TALLOC_CTX *mem_ctx)
1707 data->notify_data.value[0]=queue->size;
1710 /*******************************************************************
1711 * fill a notify_info_data with job position
1712 ********************************************************************/
1713 static void spoolss_notify_job_position(int snum,
1714 SPOOL_NOTIFY_INFO_DATA *data,
1715 print_queue_struct *queue,
1716 NT_PRINTER_INFO_LEVEL *printer,
1717 TALLOC_CTX *mem_ctx)
1719 data->notify_data.value[0]=queue->job;
1722 /*******************************************************************
1723 * fill a notify_info_data with submitted time
1724 ********************************************************************/
1725 static void spoolss_notify_submitted_time(int snum,
1726 SPOOL_NOTIFY_INFO_DATA *data,
1727 print_queue_struct *queue,
1728 NT_PRINTER_INFO_LEVEL *printer,
1729 TALLOC_CTX *mem_ctx)
1734 t=gmtime(&queue->time);
1736 len = sizeof(SYSTEMTIME);
1738 data->notify_data.data.length = len;
1739 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1741 if (!data->notify_data.data.string) {
1742 data->notify_data.data.length = 0;
1746 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1751 struct s_notify_info_data_table
1757 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1758 print_queue_struct *queue,
1759 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
1762 struct s_notify_info_data_table notify_info_data_table[] =
1764 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1765 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1766 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1767 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1768 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1769 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1770 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1771 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1772 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1773 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1774 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1775 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1776 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1777 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1778 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1779 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1780 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1781 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1782 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1783 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1784 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1785 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1786 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1787 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1788 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1789 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1790 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1791 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1792 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1793 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1794 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1795 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1796 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1797 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1798 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1799 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1800 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1801 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1802 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1803 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1804 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1805 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1806 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1807 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1808 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1809 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1810 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1811 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1812 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1813 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1814 { END, END, "", END, NULL }
1817 /*******************************************************************
1818 return the size of info_data structure
1819 ********************************************************************/
1820 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1824 while (notify_info_data_table[i].type != END)
1826 if ( (notify_info_data_table[i].type == type ) &&
1827 (notify_info_data_table[i].field == field ) )
1829 return (notify_info_data_table[i].size);
1836 /*******************************************************************
1837 return the type of notify_info_data
1838 ********************************************************************/
1839 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1843 while (notify_info_data_table[i].type != END)
1845 if ( (notify_info_data_table[i].type == type ) &&
1846 (notify_info_data_table[i].field == field ) )
1848 if (notify_info_data_table[i].size == POINTER)
1862 /****************************************************************************
1863 ****************************************************************************/
1864 static int search_notify(uint16 type, uint16 field, int *value)
1869 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1871 if ( (notify_info_data_table[j].type == type ) &&
1872 (notify_info_data_table[j].field == field ) )
1877 if ( found && (notify_info_data_table[j].fn != NULL) )
1883 /****************************************************************************
1884 ****************************************************************************/
1885 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1887 info_data->type = type;
1888 info_data->field = field;
1889 info_data->reserved = 0;
1891 info_data->size = size_of_notify_info_data(type, field);
1892 info_data->enc_type = type_of_notify_info_data(type, field);
1896 /*******************************************************************
1898 * fill a notify_info struct with info asked
1900 ********************************************************************/
1901 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
1902 snum, SPOOL_NOTIFY_OPTION_TYPE
1903 *option_type, uint32 id,
1904 TALLOC_CTX *mem_ctx)
1910 SPOOL_NOTIFY_INFO_DATA *current_data;
1911 NT_PRINTER_INFO_LEVEL *printer = NULL;
1912 print_queue_struct *queue=NULL;
1914 type=option_type->type;
1916 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1917 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1918 option_type->count, lp_servicename(snum)));
1920 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1923 for(field_num=0; field_num<option_type->count; field_num++) {
1924 field = option_type->fields[field_num];
1925 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1927 if (!search_notify(type, field, &j) )
1930 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1933 current_data=&info->data[info->count];
1935 construct_info_data(current_data, type, field, id);
1937 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
1938 notify_info_data_table[j].name, snum, printer->info_2->printername ));
1940 notify_info_data_table[j].fn(snum, current_data, queue,
1946 free_a_printer(&printer, 2);
1950 /*******************************************************************
1952 * fill a notify_info struct with info asked
1954 ********************************************************************/
1955 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
1956 SPOOL_NOTIFY_INFO *info,
1957 NT_PRINTER_INFO_LEVEL *printer,
1958 int snum, SPOOL_NOTIFY_OPTION_TYPE
1959 *option_type, uint32 id,
1960 TALLOC_CTX *mem_ctx)
1966 SPOOL_NOTIFY_INFO_DATA *current_data;
1968 DEBUG(4,("construct_notify_jobs_info\n"));
1970 type = option_type->type;
1972 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1973 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1974 option_type->count));
1976 for(field_num=0; field_num<option_type->count; field_num++) {
1977 field = option_type->fields[field_num];
1979 if (!search_notify(type, field, &j) )
1982 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1986 current_data=&(info->data[info->count]);
1988 construct_info_data(current_data, type, field, id);
1989 notify_info_data_table[j].fn(snum, current_data, queue,
1998 * JFM: The enumeration is not that simple, it's even non obvious.
2000 * let's take an example: I want to monitor the PRINTER SERVER for
2001 * the printer's name and the number of jobs currently queued.
2002 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2003 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2005 * I have 3 printers on the back of my server.
2007 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2010 * 1 printer 1 name 1
2011 * 2 printer 1 cjob 1
2012 * 3 printer 2 name 2
2013 * 4 printer 2 cjob 2
2014 * 5 printer 3 name 3
2015 * 6 printer 3 name 3
2017 * that's the print server case, the printer case is even worse.
2022 /*******************************************************************
2024 * enumerate all printers on the printserver
2025 * fill a notify_info struct with info asked
2027 ********************************************************************/
2028 static uint32 printserver_notify_info(const POLICY_HND *hnd,
2029 SPOOL_NOTIFY_INFO *info,
2030 TALLOC_CTX *mem_ctx)
2033 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2034 int n_services=lp_numservices();
2037 SPOOL_NOTIFY_OPTION *option;
2038 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2040 DEBUG(4,("printserver_notify_info\n"));
2042 option=Printer->notify.option;
2048 for (i=0; i<option->count; i++) {
2049 option_type=&(option->ctr.type[i]);
2051 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2054 for (snum=0; snum<n_services; snum++)
2055 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2056 if (construct_notify_printer_info
2057 (info, snum, option_type, id, mem_ctx))
2062 * Debugging information, don't delete.
2065 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2066 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2067 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2069 for (i=0; i<info->count; i++) {
2070 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2071 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2072 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2076 return NT_STATUS_NO_PROBLEMO;
2079 /*******************************************************************
2081 * fill a notify_info struct with info asked
2083 ********************************************************************/
2084 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2085 TALLOC_CTX *mem_ctx)
2088 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2091 SPOOL_NOTIFY_OPTION *option;
2092 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2094 print_queue_struct *queue=NULL;
2095 print_status_struct status;
2097 DEBUG(4,("printer_notify_info\n"));
2099 option=Printer->notify.option;
2105 get_printer_snum(hnd, &snum);
2107 for (i=0; i<option->count; i++) {
2108 option_type=&option->ctr.type[i];
2110 switch ( option_type->type ) {
2111 case PRINTER_NOTIFY_TYPE:
2112 if(construct_notify_printer_info(info, snum,
2118 case JOB_NOTIFY_TYPE: {
2119 NT_PRINTER_INFO_LEVEL *printer = NULL;
2121 memset(&status, 0, sizeof(status));
2122 count = print_queue_status(snum, &queue, &status);
2124 if (get_a_printer(&printer, 2,
2125 lp_servicename(snum)) != 0)
2128 for (j=0; j<count; j++) {
2129 construct_notify_jobs_info(&queue[j], info,
2136 free_a_printer(&printer, 2);
2146 * Debugging information, don't delete.
2149 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2150 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2151 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2153 for (i=0; i<info->count; i++) {
2154 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2155 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2156 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2159 return NT_STATUS_NO_PROBLEMO;
2162 /********************************************************************
2164 ********************************************************************/
2165 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
2166 SPOOL_NOTIFY_OPTION *option, TALLOC_CTX *mem_ctx,
2167 SPOOL_NOTIFY_INFO *info)
2169 Printer_entry *Printer=find_printer_index_by_hnd(handle);
2170 uint32 result = ERROR_INVALID_HANDLE;
2172 if (!OPEN_HANDLE(Printer)) {
2173 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2174 OUR_HANDLE(handle)));
2178 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2180 /* jfm: the change value isn't used right now.
2181 * we will honour it when
2182 * a) we'll be able to send notification to the client
2183 * b) we'll have a way to communicate between the spoolss process.
2185 * same thing for option->flags
2186 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2187 * I don't have a global notification system, I'm sending back all the
2188 * informations even when _NOTHING_ has changed.
2191 /* just discard the SPOOL_NOTIFY_OPTION */
2193 safe_free(option->ctr.type);
2195 switch (Printer->printer_type) {
2196 case PRINTER_HANDLE_IS_PRINTSERVER:
2197 result = printserver_notify_info(handle, info,
2201 case PRINTER_HANDLE_IS_PRINTER:
2202 result = printer_notify_info(handle, info, mem_ctx);
2210 /********************************************************************
2211 * construct_printer_info_0
2212 * fill a printer_info_0 struct
2213 ********************************************************************/
2214 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2218 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2219 counter_printer_0 *session_counter;
2220 uint32 global_counter;
2224 print_queue_struct *queue=NULL;
2225 print_status_struct status;
2227 memset(&status, 0, sizeof(status));
2229 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2232 count = print_queue_status(snum, &queue, &status);
2234 /* check if we already have a counter for this printer */
2235 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2237 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2238 if (session_counter->snum == snum)
2242 /* it's the first time, add it to the list */
2243 if (session_counter==NULL) {
2244 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2245 free_a_printer(&ntprinter, 2);
2248 ZERO_STRUCTP(session_counter);
2249 session_counter->snum=snum;
2250 session_counter->counter=0;
2251 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2255 session_counter->counter++;
2258 * the global_counter should be stored in a TDB as it's common to all the clients
2259 * and should be zeroed on samba startup
2261 global_counter=session_counter->counter;
2263 pstrcpy(chaine,ntprinter->info_2->printername);
2265 init_unistr(&printer->printername, chaine);
2267 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2268 init_unistr(&printer->servername, chaine);
2270 printer->cjobs = count;
2271 printer->total_jobs = 0;
2272 printer->total_bytes = 0;
2274 setuptime = (time_t)ntprinter->info_2->setuptime;
2275 t=gmtime(&setuptime);
2277 printer->year = t->tm_year+1900;
2278 printer->month = t->tm_mon+1;
2279 printer->dayofweek = t->tm_wday;
2280 printer->day = t->tm_mday;
2281 printer->hour = t->tm_hour;
2282 printer->minute = t->tm_min;
2283 printer->second = t->tm_sec;
2284 printer->milliseconds = 0;
2286 printer->global_counter = global_counter;
2287 printer->total_pages = 0;
2288 printer->major_version = 0x0004; /* NT 4 */
2289 printer->build_version = 0x0565; /* build 1381 */
2290 printer->unknown7 = 0x1;
2291 printer->unknown8 = 0x0;
2292 printer->unknown9 = 0x0;
2293 printer->session_counter = session_counter->counter;
2294 printer->unknown11 = 0x0;
2295 printer->printer_errors = 0x0; /* number of print failure */
2296 printer->unknown13 = 0x0;
2297 printer->unknown14 = 0x1;
2298 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2299 printer->unknown16 = 0x0;
2300 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2301 printer->unknown18 = 0x0;
2302 printer->status = nt_printq_status(status.status);
2303 printer->unknown20 = 0x0;
2304 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2305 printer->unknown22 = 0x0;
2306 printer->unknown23 = 0x6; /* 6 ???*/
2307 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2308 printer->unknown25 = 0;
2309 printer->unknown26 = 0;
2310 printer->unknown27 = 0;
2311 printer->unknown28 = 0;
2312 printer->unknown29 = 0;
2315 free_a_printer(&ntprinter,2);
2319 /********************************************************************
2320 * construct_printer_info_1
2321 * fill a printer_info_1 struct
2322 ********************************************************************/
2323 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2327 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2329 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2332 printer->flags=flags;
2334 if (*ntprinter->info_2->comment == '\0') {
2335 init_unistr(&printer->comment, lp_comment(snum));
2336 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2337 ntprinter->info_2->drivername, lp_comment(snum));
2340 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2341 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2342 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2345 snprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2347 init_unistr(&printer->description, chaine);
2348 init_unistr(&printer->name, chaine2);
2350 free_a_printer(&ntprinter,2);
2355 /****************************************************************************
2356 Free a DEVMODE struct.
2357 ****************************************************************************/
2359 static void free_dev_mode(DEVICEMODE *dev)
2365 safe_free(dev->private);
2370 /****************************************************************************
2371 Create a DEVMODE struct. Returns malloced memory.
2372 ****************************************************************************/
2374 static DEVICEMODE *construct_dev_mode(int snum)
2378 NT_PRINTER_INFO_LEVEL *printer = NULL;
2379 NT_DEVICEMODE *ntdevmode = NULL;
2380 DEVICEMODE *devmode = NULL;
2382 DEBUG(7,("construct_dev_mode\n"));
2384 DEBUGADD(8,("getting printer characteristics\n"));
2386 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2387 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2391 ZERO_STRUCTP(devmode);
2393 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2396 if (printer->info_2->devmode)
2397 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2399 if (ntdevmode == NULL)
2402 DEBUGADD(8,("loading DEVICEMODE\n"));
2404 snprintf(adevice, sizeof(adevice), printer->info_2->printername);
2405 init_unistr(&devmode->devicename, adevice);
2407 snprintf(aform, sizeof(aform), ntdevmode->formname);
2408 init_unistr(&devmode->formname, aform);
2410 devmode->specversion = ntdevmode->specversion;
2411 devmode->driverversion = ntdevmode->driverversion;
2412 devmode->size = ntdevmode->size;
2413 devmode->driverextra = ntdevmode->driverextra;
2414 devmode->fields = ntdevmode->fields;
2416 devmode->orientation = ntdevmode->orientation;
2417 devmode->papersize = ntdevmode->papersize;
2418 devmode->paperlength = ntdevmode->paperlength;
2419 devmode->paperwidth = ntdevmode->paperwidth;
2420 devmode->scale = ntdevmode->scale;
2421 devmode->copies = ntdevmode->copies;
2422 devmode->defaultsource = ntdevmode->defaultsource;
2423 devmode->printquality = ntdevmode->printquality;
2424 devmode->color = ntdevmode->color;
2425 devmode->duplex = ntdevmode->duplex;
2426 devmode->yresolution = ntdevmode->yresolution;
2427 devmode->ttoption = ntdevmode->ttoption;
2428 devmode->collate = ntdevmode->collate;
2429 devmode->icmmethod = ntdevmode->icmmethod;
2430 devmode->icmintent = ntdevmode->icmintent;
2431 devmode->mediatype = ntdevmode->mediatype;
2432 devmode->dithertype = ntdevmode->dithertype;
2434 if (ntdevmode->private != NULL) {
2435 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2439 free_nt_devicemode(&ntdevmode);
2440 free_a_printer(&printer,2);
2447 free_nt_devicemode(&ntdevmode);
2449 free_a_printer(&printer,2);
2450 free_dev_mode(devmode);
2455 /********************************************************************
2456 * construct_printer_info_2
2457 * fill a printer_info_2 struct
2458 ********************************************************************/
2460 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2463 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2465 print_queue_struct *queue=NULL;
2466 print_status_struct status;
2467 memset(&status, 0, sizeof(status));
2469 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2472 memset(&status, 0, sizeof(status));
2473 count = print_queue_status(snum, &queue, &status);
2475 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2476 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2477 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2478 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2479 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2481 if (*ntprinter->info_2->comment == '\0')
2482 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2484 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2486 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2487 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2488 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2489 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2490 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2492 printer->attributes = ntprinter->info_2->attributes;
2494 printer->priority = ntprinter->info_2->priority; /* priority */
2495 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2496 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2497 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2498 printer->status = nt_printq_status(status.status); /* status */
2499 printer->cjobs = count; /* jobs */
2500 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2502 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2503 DEBUG(8, ("Returning NULL Devicemode!\n"));
2506 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2507 /* steal the printer info sec_desc structure. [badly done]. */
2508 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2509 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2510 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2511 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2514 printer->secdesc = NULL;
2517 free_a_printer(&ntprinter, 2);
2522 /********************************************************************
2523 * construct_printer_info_3
2524 * fill a printer_info_3 struct
2525 ********************************************************************/
2526 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2528 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2529 PRINTER_INFO_3 *printer = NULL;
2531 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2535 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2536 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2540 ZERO_STRUCTP(printer);
2542 printer->flags = 4; /* These are the components of the SD we are returning. */
2543 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2544 /* steal the printer info sec_desc structure. [badly done]. */
2545 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2549 * Set the flags for the components we are returning.
2552 if (printer->secdesc->owner_sid)
2553 printer->flags |= OWNER_SECURITY_INFORMATION;
2555 if (printer->secdesc->grp_sid)
2556 printer->flags |= GROUP_SECURITY_INFORMATION;
2558 if (printer->secdesc->dacl)
2559 printer->flags |= DACL_SECURITY_INFORMATION;
2561 if (printer->secdesc->sacl)
2562 printer->flags |= SACL_SECURITY_INFORMATION;
2565 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2566 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2567 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2570 free_a_printer(&ntprinter, 2);
2572 *pp_printer = printer;
2576 /********************************************************************
2577 Spoolss_enumprinters.
2578 ********************************************************************/
2579 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2583 int n_services=lp_numservices();
2584 PRINTER_INFO_1 *printers=NULL;
2585 PRINTER_INFO_1 current_prt;
2587 DEBUG(4,("enum_all_printers_info_1\n"));
2589 for (snum=0; snum<n_services; snum++) {
2590 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2591 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2593 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2594 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2596 return ERROR_NOT_ENOUGH_MEMORY;
2598 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2599 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2605 /* check the required size. */
2606 for (i=0; i<*returned; i++)
2607 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2609 if (!alloc_buffer_size(buffer, *needed))
2610 return ERROR_INSUFFICIENT_BUFFER;
2612 /* fill the buffer with the structures */
2613 for (i=0; i<*returned; i++)
2614 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2617 safe_free(printers);
2619 if (*needed > offered) {
2621 return ERROR_INSUFFICIENT_BUFFER;
2624 return NT_STATUS_NO_PROBLEMO;
2627 /********************************************************************
2628 enum_all_printers_info_1_local.
2629 *********************************************************************/
2630 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2632 DEBUG(4,("enum_all_printers_info_1_local\n"));
2634 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2637 /********************************************************************
2638 enum_all_printers_info_1_name.
2639 *********************************************************************/
2640 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2643 DEBUG(4,("enum_all_printers_info_1_name\n"));
2645 fstrcpy(temp, "\\\\");
2646 fstrcat(temp, global_myname);
2648 if (strequal(name, temp)) {
2649 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2652 return ERROR_INVALID_NAME;
2655 /********************************************************************
2656 enum_all_printers_info_1_remote.
2657 *********************************************************************/
2658 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2660 PRINTER_INFO_1 *printer;
2661 fstring printername;
2664 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2666 /* JFM: currently it's more a place holder than anything else.
2667 * In the spooler world there is a notion of server registration.
2668 * the print servers are registring (sp ?) on the PDC (in the same domain)
2670 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2673 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2674 return ERROR_NOT_ENOUGH_MEMORY;
2678 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2679 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2680 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2682 init_unistr(&printer->description, desc);
2683 init_unistr(&printer->name, printername);
2684 init_unistr(&printer->comment, comment);
2685 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2687 /* check the required size. */
2688 *needed += spoolss_size_printer_info_1(printer);
2690 if (!alloc_buffer_size(buffer, *needed)) {
2692 return ERROR_INSUFFICIENT_BUFFER;
2695 /* fill the buffer with the structures */
2696 new_smb_io_printer_info_1("", buffer, printer, 0);
2701 if (*needed > offered) {
2703 return ERROR_INSUFFICIENT_BUFFER;
2706 return NT_STATUS_NO_PROBLEMO;
2709 /********************************************************************
2710 enum_all_printers_info_1_network.
2711 *********************************************************************/
2712 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2714 DEBUG(4,("enum_all_printers_info_1_network\n"));
2716 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2719 /********************************************************************
2720 * api_spoolss_enumprinters
2722 * called from api_spoolss_enumprinters (see this to understand)
2723 ********************************************************************/
2724 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2728 int n_services=lp_numservices();
2729 PRINTER_INFO_2 *printers=NULL;
2730 PRINTER_INFO_2 current_prt;
2732 for (snum=0; snum<n_services; snum++) {
2733 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2734 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2736 if (construct_printer_info_2(¤t_prt, snum)) {
2737 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2738 return ERROR_NOT_ENOUGH_MEMORY;
2739 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2740 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2746 /* check the required size. */
2747 for (i=0; i<*returned; i++)
2748 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2750 if (!alloc_buffer_size(buffer, *needed)) {
2751 for (i=0; i<*returned; i++) {
2752 free_devmode(printers[i].devmode);
2753 free_sec_desc(&printers[i].secdesc);
2755 safe_free(printers);
2756 return ERROR_INSUFFICIENT_BUFFER;
2759 /* fill the buffer with the structures */
2760 for (i=0; i<*returned; i++)
2761 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2764 for (i=0; i<*returned; i++) {
2765 free_devmode(printers[i].devmode);
2766 free_sec_desc(&printers[i].secdesc);
2768 safe_free(printers);
2770 if (*needed > offered) {
2772 return ERROR_INSUFFICIENT_BUFFER;
2775 return NT_STATUS_NO_PROBLEMO;
2778 /********************************************************************
2779 * handle enumeration of printers at level 1
2780 ********************************************************************/
2781 static uint32 enumprinters_level1( uint32 flags, fstring name,
2782 NEW_BUFFER *buffer, uint32 offered,
2783 uint32 *needed, uint32 *returned)
2785 /* Not all the flags are equals */
2787 if (flags & PRINTER_ENUM_LOCAL)
2788 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2790 if (flags & PRINTER_ENUM_NAME)
2791 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2793 if (flags & PRINTER_ENUM_REMOTE)
2794 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2796 if (flags & PRINTER_ENUM_NETWORK)
2797 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
2799 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2802 /********************************************************************
2803 * handle enumeration of printers at level 2
2804 ********************************************************************/
2805 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2806 NEW_BUFFER *buffer, uint32 offered,
2807 uint32 *needed, uint32 *returned)
2811 fstrcpy(temp, "\\\\");
2812 fstrcat(temp, global_myname);
2814 if (flags & PRINTER_ENUM_LOCAL) {
2815 if (strequal(servername, temp))
2816 return enum_all_printers_info_2(buffer, offered, needed, returned);
2818 return enum_all_printers_info_2(buffer, offered, needed, returned);
2821 if (flags & PRINTER_ENUM_NAME) {
2822 if (strequal(servername, temp))
2823 return enum_all_printers_info_2(buffer, offered, needed, returned);
2825 return ERROR_INVALID_NAME;
2828 if (flags & PRINTER_ENUM_REMOTE)
2829 return ERROR_INVALID_LEVEL;
2831 return NT_STATUS_NO_PROBLEMO;
2834 /********************************************************************
2835 * handle enumeration of printers at level 5
2836 ********************************************************************/
2837 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2838 NEW_BUFFER *buffer, uint32 offered,
2839 uint32 *needed, uint32 *returned)
2841 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2842 return NT_STATUS_NO_PROBLEMO;
2845 /********************************************************************
2846 * api_spoolss_enumprinters
2848 * called from api_spoolss_enumprinters (see this to understand)
2849 ********************************************************************/
2850 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2851 NEW_BUFFER *buffer, uint32 offered,
2852 uint32 *needed, uint32 *returned)
2856 DEBUG(4,("_spoolss_enumprinters\n"));
2863 * flags==PRINTER_ENUM_NAME
2864 * if name=="" then enumerates all printers
2865 * if name!="" then enumerate the printer
2866 * flags==PRINTER_ENUM_REMOTE
2867 * name is NULL, enumerate printers
2868 * Level 2: name!="" enumerates printers, name can't be NULL
2869 * Level 3: doesn't exist
2870 * Level 4: does a local registry lookup
2871 * Level 5: same as Level 2
2874 unistr2_to_ascii(name, servername, sizeof(name)-1);
2879 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2881 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2883 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2887 return ERROR_INVALID_LEVEL;
2891 /****************************************************************************
2892 ****************************************************************************/
2893 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2895 PRINTER_INFO_0 *printer=NULL;
2897 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2898 return ERROR_NOT_ENOUGH_MEMORY;
2900 construct_printer_info_0(printer, snum);
2902 /* check the required size. */
2903 *needed += spoolss_size_printer_info_0(printer);
2905 if (!alloc_buffer_size(buffer, *needed)) {
2907 return ERROR_INSUFFICIENT_BUFFER;
2910 /* fill the buffer with the structures */
2911 new_smb_io_printer_info_0("", buffer, printer, 0);
2916 if (*needed > offered) {
2917 return ERROR_INSUFFICIENT_BUFFER;
2920 return NT_STATUS_NO_PROBLEMO;
2923 /****************************************************************************
2924 ****************************************************************************/
2925 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2927 PRINTER_INFO_1 *printer=NULL;
2929 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2930 return ERROR_NOT_ENOUGH_MEMORY;
2932 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
2934 /* check the required size. */
2935 *needed += spoolss_size_printer_info_1(printer);
2937 if (!alloc_buffer_size(buffer, *needed)) {
2939 return ERROR_INSUFFICIENT_BUFFER;
2942 /* fill the buffer with the structures */
2943 new_smb_io_printer_info_1("", buffer, printer, 0);
2948 if (*needed > offered) {
2949 return ERROR_INSUFFICIENT_BUFFER;
2952 return NT_STATUS_NO_PROBLEMO;
2955 /****************************************************************************
2956 ****************************************************************************/
2957 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2959 PRINTER_INFO_2 *printer=NULL;
2961 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2962 return ERROR_NOT_ENOUGH_MEMORY;
2964 construct_printer_info_2(printer, snum);
2966 /* check the required size. */
2967 *needed += spoolss_size_printer_info_2(printer);
2969 if (!alloc_buffer_size(buffer, *needed)) {
2970 free_printer_info_2(printer);
2971 return ERROR_INSUFFICIENT_BUFFER;
2974 /* fill the buffer with the structures */
2975 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2976 free_printer_info_2(printer);
2977 return ERROR_NOT_ENOUGH_MEMORY;
2981 free_printer_info_2(printer);
2983 if (*needed > offered) {
2984 return ERROR_INSUFFICIENT_BUFFER;
2987 return NT_STATUS_NO_PROBLEMO;
2990 /****************************************************************************
2991 ****************************************************************************/
2992 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2994 PRINTER_INFO_3 *printer=NULL;
2996 if (!construct_printer_info_3(&printer, snum))
2997 return ERROR_NOT_ENOUGH_MEMORY;
2999 /* check the required size. */
3000 *needed += spoolss_size_printer_info_3(printer);
3002 if (!alloc_buffer_size(buffer, *needed)) {
3003 free_printer_info_3(printer);
3004 return ERROR_INSUFFICIENT_BUFFER;
3007 /* fill the buffer with the structures */
3008 new_smb_io_printer_info_3("", buffer, printer, 0);
3011 free_printer_info_3(printer);
3013 if (*needed > offered) {
3014 return ERROR_INSUFFICIENT_BUFFER;
3017 return NT_STATUS_NO_PROBLEMO;
3020 /****************************************************************************
3021 ****************************************************************************/
3022 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
3023 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3029 if (!get_printer_snum(handle, &snum))
3030 return ERROR_INVALID_HANDLE;
3034 return getprinter_level_0(snum, buffer, offered, needed);
3036 return getprinter_level_1(snum, buffer, offered, needed);
3038 return getprinter_level_2(snum, buffer, offered, needed);
3040 return getprinter_level_3(snum, buffer, offered, needed);
3042 return ERROR_INVALID_LEVEL;
3046 /********************************************************************
3047 * fill a DRIVER_INFO_1 struct
3048 ********************************************************************/
3049 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3051 init_unistr( &info->name, driver.info_3->name);
3054 /********************************************************************
3055 * construct_printer_driver_info_1
3056 ********************************************************************/
3057 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3059 NT_PRINTER_INFO_LEVEL *printer = NULL;
3060 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3062 ZERO_STRUCT(driver);
3064 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3065 return ERROR_INVALID_PRINTER_NAME;
3067 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3068 return ERROR_UNKNOWN_PRINTER_DRIVER;
3070 fill_printer_driver_info_1(info, driver, servername, architecture);
3072 free_a_printer(&printer,2);
3074 return NT_STATUS_NO_PROBLEMO;
3077 /********************************************************************
3078 * construct_printer_driver_info_2
3079 * fill a printer_info_2 struct
3080 ********************************************************************/
3081 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3085 info->version=driver.info_3->cversion;
3087 init_unistr( &info->name, driver.info_3->name );
3088 init_unistr( &info->architecture, driver.info_3->environment );
3091 if (strlen(driver.info_3->driverpath)) {
3092 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3093 init_unistr( &info->driverpath, temp );
3095 init_unistr( &info->driverpath, "" );
3097 if (strlen(driver.info_3->datafile)) {
3098 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3099 init_unistr( &info->datafile, temp );
3101 init_unistr( &info->datafile, "" );
3103 if (strlen(driver.info_3->configfile)) {
3104 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3105 init_unistr( &info->configfile, temp );
3107 init_unistr( &info->configfile, "" );
3110 /********************************************************************
3111 * construct_printer_driver_info_2
3112 * fill a printer_info_2 struct
3113 ********************************************************************/
3114 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3116 NT_PRINTER_INFO_LEVEL *printer = NULL;
3117 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3119 ZERO_STRUCT(printer);
3120 ZERO_STRUCT(driver);
3122 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3123 return ERROR_INVALID_PRINTER_NAME;
3125 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3126 return ERROR_UNKNOWN_PRINTER_DRIVER;
3128 fill_printer_driver_info_2(info, driver, servername);
3130 free_a_printer(&printer,2);
3132 return NT_STATUS_NO_PROBLEMO;
3135 /********************************************************************
3136 * copy a strings array and convert to UNICODE
3138 * convert an array of ascii string to a UNICODE string
3139 ********************************************************************/
3140 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3147 DEBUG(6,("init_unistr_array\n"));
3151 if (char_array == NULL)
3155 if (!v) v = ""; /* hack to handle null lists */
3157 if (strlen(v) == 0) break;
3158 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3159 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3160 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3161 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3164 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3169 (*uni_array)[j]=0x0000;
3172 DEBUGADD(6,("last one:done\n"));
3175 /********************************************************************
3176 * construct_printer_info_3
3177 * fill a printer_info_3 struct
3178 ********************************************************************/
3179 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3185 info->version=driver.info_3->cversion;
3187 init_unistr( &info->name, driver.info_3->name );
3188 init_unistr( &info->architecture, driver.info_3->environment );
3190 if (strlen(driver.info_3->driverpath)) {
3191 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3192 init_unistr( &info->driverpath, temp );
3194 init_unistr( &info->driverpath, "" );
3196 if (strlen(driver.info_3->datafile)) {
3197 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3198 init_unistr( &info->datafile, temp );
3200 init_unistr( &info->datafile, "" );
3202 if (strlen(driver.info_3->configfile)) {
3203 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3204 init_unistr( &info->configfile, temp );
3206 init_unistr( &info->configfile, "" );
3208 if (strlen(driver.info_3->helpfile)) {
3209 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3210 init_unistr( &info->helpfile, temp );
3212 init_unistr( &info->helpfile, "" );
3214 init_unistr( &info->monitorname, driver.info_3->monitorname );
3215 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3217 info->dependentfiles=NULL;
3218 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3221 /********************************************************************
3222 * construct_printer_info_3
3223 * fill a printer_info_3 struct
3224 ********************************************************************/
3225 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3227 NT_PRINTER_INFO_LEVEL *printer = NULL;
3228 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3230 ZERO_STRUCT(driver);
3232 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3233 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3235 return ERROR_INVALID_PRINTER_NAME;
3237 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3238 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3240 free_a_printer(&printer,2);
3241 return ERROR_UNKNOWN_PRINTER_DRIVER;
3244 fill_printer_driver_info_3(info, driver, servername);
3246 free_a_printer(&printer,2);
3248 return NT_STATUS_NO_PROBLEMO;
3251 /********************************************************************
3252 * construct_printer_info_6
3253 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3254 ********************************************************************/
3256 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3262 memset(&nullstr, '\0', sizeof(fstring));
3264 info->version=driver.info_3->cversion;
3266 init_unistr( &info->name, driver.info_3->name );
3267 init_unistr( &info->architecture, driver.info_3->environment );
3269 if (strlen(driver.info_3->driverpath)) {
3270 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3271 init_unistr( &info->driverpath, temp );
3273 init_unistr( &info->driverpath, "" );
3275 if (strlen(driver.info_3->datafile)) {
3276 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3277 init_unistr( &info->datafile, temp );
3279 init_unistr( &info->datafile, "" );
3281 if (strlen(driver.info_3->configfile)) {
3282 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3283 init_unistr( &info->configfile, temp );
3285 init_unistr( &info->configfile, "" );
3287 if (strlen(driver.info_3->helpfile)) {
3288 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3289 init_unistr( &info->helpfile, temp );
3291 init_unistr( &info->helpfile, "" );
3293 init_unistr( &info->monitorname, driver.info_3->monitorname );
3294 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3296 info->dependentfiles=NULL;
3297 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3299 info->previousdrivernames=NULL;
3300 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3302 info->driver_date.low=0;
3303 info->driver_date.high=0;
3306 info->driver_version_low=0;
3307 info->driver_version_high=0;
3309 init_unistr( &info->mfgname, "");
3310 init_unistr( &info->oem_url, "");
3311 init_unistr( &info->hardware_id, "");
3312 init_unistr( &info->provider, "");
3315 /********************************************************************
3316 * construct_printer_info_6
3317 * fill a printer_info_6 struct
3318 ********************************************************************/
3319 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3321 NT_PRINTER_INFO_LEVEL *printer = NULL;
3322 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3324 ZERO_STRUCT(driver);
3326 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3327 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3329 return ERROR_INVALID_PRINTER_NAME;
3331 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3332 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3335 * Is this a W2k client ?
3339 free_a_printer(&printer,2);
3340 return ERROR_UNKNOWN_PRINTER_DRIVER;
3343 /* Yes - try again with a WinNT driver. */
3345 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3346 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3348 free_a_printer(&printer,2);
3349 return ERROR_UNKNOWN_PRINTER_DRIVER;
3353 fill_printer_driver_info_6(info, driver, servername);
3355 free_a_printer(&printer,2);
3357 return NT_STATUS_NO_PROBLEMO;
3360 /****************************************************************************
3361 ****************************************************************************/
3363 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3365 safe_free(info->dependentfiles);
3368 /****************************************************************************
3369 ****************************************************************************/
3371 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3373 safe_free(info->dependentfiles);
3377 /****************************************************************************
3378 ****************************************************************************/
3379 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3381 DRIVER_INFO_1 *info=NULL;
3384 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3385 return ERROR_NOT_ENOUGH_MEMORY;
3387 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3388 if (status != NT_STATUS_NO_PROBLEMO) {
3393 /* check the required size. */
3394 *needed += spoolss_size_printer_driver_info_1(info);
3396 if (!alloc_buffer_size(buffer, *needed)) {
3398 return ERROR_INSUFFICIENT_BUFFER;
3401 /* fill the buffer with the structures */
3402 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3407 if (*needed > offered)
3408 return ERROR_INSUFFICIENT_BUFFER;
3410 return NT_STATUS_NO_PROBLEMO;
3413 /****************************************************************************
3414 ****************************************************************************/
3415 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3417 DRIVER_INFO_2 *info=NULL;
3420 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3421 return ERROR_NOT_ENOUGH_MEMORY;
3423 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3424 if (status != NT_STATUS_NO_PROBLEMO) {
3429 /* check the required size. */
3430 *needed += spoolss_size_printer_driver_info_2(info);
3432 if (!alloc_buffer_size(buffer, *needed)) {
3434 return ERROR_INSUFFICIENT_BUFFER;
3437 /* fill the buffer with the structures */
3438 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3443 if (*needed > offered)
3444 return ERROR_INSUFFICIENT_BUFFER;
3446 return NT_STATUS_NO_PROBLEMO;
3449 /****************************************************************************
3450 ****************************************************************************/
3451 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3458 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3459 if (status != NT_STATUS_NO_PROBLEMO) {
3463 /* check the required size. */
3464 *needed += spoolss_size_printer_driver_info_3(&info);
3466 if (!alloc_buffer_size(buffer, *needed)) {
3467 free_printer_driver_info_3(&info);
3468 return ERROR_INSUFFICIENT_BUFFER;
3471 /* fill the buffer with the structures */
3472 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3474 free_printer_driver_info_3(&info);
3476 if (*needed > offered)
3477 return ERROR_INSUFFICIENT_BUFFER;
3479 return NT_STATUS_NO_PROBLEMO;
3482 /****************************************************************************
3483 ****************************************************************************/
3484 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3491 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3492 if (status != NT_STATUS_NO_PROBLEMO) {
3496 /* check the required size. */
3497 *needed += spoolss_size_printer_driver_info_6(&info);
3499 if (!alloc_buffer_size(buffer, *needed)) {
3500 free_printer_driver_info_6(&info);
3501 return ERROR_INSUFFICIENT_BUFFER;
3504 /* fill the buffer with the structures */
3505 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3507 free_printer_driver_info_6(&info);
3509 if (*needed > offered)
3510 return ERROR_INSUFFICIENT_BUFFER;
3512 return NT_STATUS_NO_PROBLEMO;
3515 /****************************************************************************
3516 ****************************************************************************/
3517 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3518 uint32 clientmajorversion, uint32 clientminorversion,
3519 NEW_BUFFER *buffer, uint32 offered,
3520 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3523 fstring architecture;
3526 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3529 *servermajorversion=0;
3530 *serverminorversion=0;
3532 pstrcpy(servername, global_myname);
3533 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3535 if (!get_printer_snum(handle, &snum))
3536 return ERROR_INVALID_HANDLE;
3540 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3542 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3544 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3546 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3548 return ERROR_INVALID_LEVEL;
3552 /****************************************************************************
3553 ****************************************************************************/
3554 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3556 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3558 if (OPEN_HANDLE(Printer)) {
3559 Printer->page_started=True;
3563 DEBUG(3,("Error in startpageprinter printer handle\n"));
3564 return ERROR_INVALID_HANDLE;
3567 /****************************************************************************
3568 ****************************************************************************/
3569 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3571 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3573 if (!OPEN_HANDLE(Printer)) {
3574 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3575 return ERROR_INVALID_HANDLE;
3578 Printer->page_started=False;
3580 return NT_STATUS_NO_PROBLEMO;
3583 /****************************************************************************
3584 Return a user struct for a pipe user.
3585 ****************************************************************************/
3587 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3589 if (p->ntlmssp_auth_validated) {
3590 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3592 extern struct current_user current_user;
3593 memcpy(user, ¤t_user, sizeof(struct current_user));
3599 /********************************************************************
3600 * api_spoolss_getprinter
3601 * called from the spoolss dispatcher
3603 ********************************************************************/
3604 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3605 pipes_struct *p, DOC_INFO *docinfo,
3608 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3612 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3613 struct current_user user;
3615 if (!OPEN_HANDLE(Printer)) {
3616 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3617 return ERROR_INVALID_HANDLE;
3620 get_current_user(&user, p);
3623 * a nice thing with NT is it doesn't listen to what you tell it.
3624 * when asked to send _only_ RAW datas, it tries to send datas
3627 * So I add checks like in NT Server ...
3629 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3630 * there's a bug in NT client-side code, so we'll fix it in the
3631 * server-side code. *nnnnnggggh!*
3634 if (info_1->p_datatype != 0) {
3635 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3636 if (strcmp(datatype, "RAW") != 0) {
3638 return ERROR_INVALID_DATATYPE;
3642 /* get the share number of the printer */
3643 if (!get_printer_snum(handle, &snum)) {
3644 return ERROR_INVALID_HANDLE;
3647 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3649 Printer->jobid = print_job_start(&user, snum, jobname);
3651 /* An error occured in print_job_start() so return an appropriate
3654 if (Printer->jobid == -1) {
3655 return map_nt_error_from_unix(errno);
3658 Printer->document_started=True;
3659 (*jobid) = Printer->jobid;
3664 /********************************************************************
3665 * api_spoolss_getprinter
3666 * called from the spoolss dispatcher
3668 ********************************************************************/
3669 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3671 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3673 if (!OPEN_HANDLE(Printer)) {
3674 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3675 return ERROR_INVALID_HANDLE;
3678 Printer->document_started=False;
3679 print_job_end(Printer->jobid);
3680 /* error codes unhandled so far ... */
3685 /****************************************************************************
3686 ****************************************************************************/
3687 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3690 uint32 *buffer_written)
3692 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3694 if (!OPEN_HANDLE(Printer)) {
3695 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3696 return ERROR_INVALID_HANDLE;
3699 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3705 /********************************************************************
3706 * api_spoolss_getprinter
3707 * called from the spoolss dispatcher
3709 ********************************************************************/
3710 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3713 struct current_user user;
3714 int snum, errcode = ERROR_INVALID_FUNCTION;
3715 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3717 get_current_user(&user, p);
3719 if (!OPEN_HANDLE(Printer)) {
3720 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3721 return ERROR_INVALID_HANDLE;
3724 if (!get_printer_snum(handle, &snum))
3725 return ERROR_INVALID_HANDLE;
3728 case PRINTER_CONTROL_PAUSE:
3729 if (print_queue_pause(&user, snum, &errcode)) {
3733 case PRINTER_CONTROL_RESUME:
3734 case PRINTER_CONTROL_UNPAUSE:
3735 if (print_queue_resume(&user, snum, &errcode)) {
3739 case PRINTER_CONTROL_PURGE:
3740 if (print_queue_purge(&user, snum, &errcode)) {
3745 return ERROR_INVALID_LEVEL;
3751 /********************************************************************
3752 * api_spoolss_abortprinter
3753 ********************************************************************/
3755 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3757 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3760 /********************************************************************
3761 * called by spoolss_api_setprinter
3762 * when updating a printer description
3763 ********************************************************************/
3764 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3765 const SPOOL_PRINTER_INFO_LEVEL *info,
3766 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3768 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3769 struct current_user user;
3773 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3775 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3776 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3777 OUR_HANDLE(handle)));
3779 result = ERROR_INVALID_HANDLE;
3783 /* NT seems to like setting the security descriptor even though
3784 nothing may have actually changed. This causes annoying
3785 dialog boxes when the user doesn't have permission to change
3786 the security descriptor. */
3788 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3790 if (DEBUGLEVEL >= 10) {
3794 acl = old_secdesc_ctr->sec->dacl;
3795 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3796 PRINTERNAME(snum), acl->num_aces));
3798 for (i = 0; i < acl->num_aces; i++) {
3801 sid_to_string(sid_str, &acl->ace[i].sid);
3803 DEBUG(10, ("%s 0x%08x\n", sid_str,
3804 acl->ace[i].info.mask));
3807 acl = secdesc_ctr->sec->dacl;
3810 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3811 PRINTERNAME(snum), acl->num_aces));
3813 for (i = 0; i < acl->num_aces; i++) {
3816 sid_to_string(sid_str, &acl->ace[i].sid);
3818 DEBUG(10, ("%s 0x%08x\n", sid_str,
3819 acl->ace[i].info.mask));
3822 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3826 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3828 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3829 result = NT_STATUS_NO_PROBLEMO;
3833 /* Work out which user is performing the operation */
3835 get_current_user(&user, p);
3837 /* Check the user has permissions to change the security
3838 descriptor. By experimentation with two NT machines, the user
3839 requires Full Access to the printer to change security
3842 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3843 result = ERROR_ACCESS_DENIED;
3847 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3850 free_sec_desc_buf(&new_secdesc_ctr);
3851 free_sec_desc_buf(&old_secdesc_ctr);
3856 /********************************************************************
3857 Do Samba sanity checks on a printer info struct.
3858 this has changed purpose: it now "canonicalises" printer
3859 info from a client rather than just checking it is correct
3860 ********************************************************************/
3862 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3864 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3865 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3867 /* we force some elements to "correct" values */
3868 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3869 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3870 global_myname, lp_servicename(snum));
3871 fstrcpy(info->sharename, lp_servicename(snum));
3872 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3873 | PRINTER_ATTRIBUTE_LOCAL \
3874 | PRINTER_ATTRIBUTE_RAW_ONLY \
3875 | PRINTER_ATTRIBUTE_QUEUED ;
3880 /****************************************************************************
3881 ****************************************************************************/
3882 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3884 pid_t local_pid = sys_getpid();
3885 char *cmd = lp_addprinter_cmd();
3890 pstring driverlocation;
3894 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3895 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3899 /* build driver path... only 9X architecture is needed for legacy reasons */
3900 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3902 /* change \ to \\ for the shell */
3903 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3905 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3906 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3907 cmd, printer->info_2->printername, printer->info_2->sharename,
3908 printer->info_2->portname, printer->info_2->drivername,
3909 printer->info_2->location, driverlocation);
3913 /* Convert script args to unix-codepage */
3914 dos_to_unix(command, True);
3915 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3916 ret = smbrun(command, tmp_file, False);
3917 DEBUGADD(10,("returned [%d]\n", ret));
3925 /* Get lines and convert them back to dos-codepage */
3926 qlines = file_lines_load(tmp_file, &numlines, True);
3927 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3928 DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
3932 /* Set the portname to what the script says the portname should be. */
3933 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3934 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3936 /* Send SIGHUP to process group... is there a better way? */
3941 file_lines_free(qlines);
3945 /* Return true if two devicemodes are equal */
3947 #define DEVMODE_CHECK_INT(field) \
3948 if (d1->field != d2->field) { \
3949 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
3950 d1->field, d2->field)); \
3954 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3956 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
3959 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
3960 return False; /* if either is exclusively NULL are not equal */
3963 if (!strequal(d1->devicename, d2->devicename) ||
3964 !strequal(d1->formname, d2->formname)) {
3965 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
3969 DEVMODE_CHECK_INT(specversion);
3970 DEVMODE_CHECK_INT(driverversion);
3971 DEVMODE_CHECK_INT(driverextra);
3972 DEVMODE_CHECK_INT(orientation);
3973 DEVMODE_CHECK_INT(papersize);
3974 DEVMODE_CHECK_INT(paperlength);
3975 DEVMODE_CHECK_INT(paperwidth);
3976 DEVMODE_CHECK_INT(scale);
3977 DEVMODE_CHECK_INT(copies);
3978 DEVMODE_CHECK_INT(defaultsource);
3979 DEVMODE_CHECK_INT(printquality);
3980 DEVMODE_CHECK_INT(color);
3981 DEVMODE_CHECK_INT(duplex);
3982 DEVMODE_CHECK_INT(yresolution);
3983 DEVMODE_CHECK_INT(ttoption);
3984 DEVMODE_CHECK_INT(collate);
3985 DEVMODE_CHECK_INT(logpixels);
3987 DEVMODE_CHECK_INT(fields);
3988 DEVMODE_CHECK_INT(bitsperpel);
3989 DEVMODE_CHECK_INT(pelswidth);
3990 DEVMODE_CHECK_INT(pelsheight);
3991 DEVMODE_CHECK_INT(displayflags);
3992 DEVMODE_CHECK_INT(displayfrequency);
3993 DEVMODE_CHECK_INT(icmmethod);
3994 DEVMODE_CHECK_INT(icmintent);
3995 DEVMODE_CHECK_INT(mediatype);
3996 DEVMODE_CHECK_INT(dithertype);
3997 DEVMODE_CHECK_INT(reserved1);
3998 DEVMODE_CHECK_INT(reserved2);
3999 DEVMODE_CHECK_INT(panningwidth);
4000 DEVMODE_CHECK_INT(panningheight);
4002 /* compare the private data if it exists */
4003 if (!d1->driverextra && !d2->driverextra) goto equal;
4006 DEVMODE_CHECK_INT(driverextra);
4008 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4009 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4014 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4018 /* Return true if two NT_PRINTER_PARAM structures are equal */
4020 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4021 NT_PRINTER_PARAM *p2)
4023 if (!p1 && !p2) goto equal;
4025 if ((!p1 && p2) || (p1 && !p2)) {
4026 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4030 /* Compare lists of printer parameters */
4034 NT_PRINTER_PARAM *q = p1;
4036 /* Find the parameter in the second structure */
4040 if (strequal(p1->value, q->value)) {
4042 if (p1->type != q->type) {
4043 DEBUG(10, ("nt_printer_param_equal():"
4044 "types for %s differ (%d != %d)\n",
4045 p1->value, p1->type,
4050 if (p1->data_len != q->data_len) {
4051 DEBUG(10, ("nt_printer_param_equal():"
4052 "len for %s differs (%d != %d)\n",
4053 p1->value, p1->data_len,
4058 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4061 DEBUG(10, ("nt_printer_param_equal():"
4062 "data for %s differs\n", p1->value));
4072 DEBUG(10, ("nt_printer_param_equal(): param %s "
4073 "does not exist\n", p1->value));
4082 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4086 /********************************************************************
4087 * Called by update_printer when trying to work out whether to
4088 * actually update printer info.
4089 ********************************************************************/
4091 #define PI_CHECK_INT(field) \
4092 if (pi1->field != pi2->field) { \
4093 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4094 pi1->field, pi2->field)); \
4098 #define PI_CHECK_STR(field) \
4099 if (!strequal(pi1->field, pi2->field)) { \
4100 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4101 pi1->field, pi2->field)); \
4105 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4106 NT_PRINTER_INFO_LEVEL *p2)
4108 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4110 /* Trivial conditions */
4112 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4116 if ((!p1 && p2) || (p1 && !p2) ||
4117 (!p1->info_2 && p2->info_2) ||
4118 (p1->info_2 && !p2->info_2)) {
4119 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4124 /* Compare two nt_printer_info_level structures. Don't compare
4125 status or cjobs as they seem to have something to do with the
4131 PI_CHECK_INT(attributes);
4132 PI_CHECK_INT(priority);
4133 PI_CHECK_INT(default_priority);
4134 PI_CHECK_INT(starttime);
4135 PI_CHECK_INT(untiltime);
4136 PI_CHECK_INT(averageppm);
4138 /* Yuck - don't check the printername or servername as the
4139 add_a_printer() code plays games with them. You can't
4140 change the printername or the sharename through this interface
4143 PI_CHECK_STR(sharename);
4144 PI_CHECK_STR(portname);
4145 PI_CHECK_STR(drivername);
4146 PI_CHECK_STR(comment);
4147 PI_CHECK_STR(location);
4149 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4153 PI_CHECK_STR(sepfile);
4154 PI_CHECK_STR(printprocessor);
4155 PI_CHECK_STR(datatype);
4156 PI_CHECK_STR(parameters);
4158 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4162 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4166 PI_CHECK_INT(changeid);
4167 PI_CHECK_INT(c_setprinter);
4168 PI_CHECK_INT(setuptime);
4171 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4175 /********************************************************************
4176 * called by spoolss_api_setprinter
4177 * when updating a printer description
4178 ********************************************************************/
4180 static uint32 update_printer(POLICY_HND *handle, uint32 level,
4181 const SPOOL_PRINTER_INFO_LEVEL *info,
4182 DEVICEMODE *devmode)
4185 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4186 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4189 DEBUG(8,("update_printer\n"));
4191 result = NT_STATUS_NO_PROBLEMO;
4194 DEBUG(0,("Send a mail to samba@samba.org\n"));
4195 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4196 result = ERROR_INVALID_LEVEL;
4200 if (!OPEN_HANDLE(Printer)) {
4201 result = ERROR_INVALID_HANDLE;
4205 if (!get_printer_snum(handle, &snum)) {
4206 result = ERROR_INVALID_HANDLE;
4210 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4211 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4212 result = ERROR_INVALID_HANDLE;
4216 DEBUGADD(8,("Converting info_2 struct\n"));
4219 * convert_printer_info converts the incoming
4220 * info from the client and overwrites the info
4221 * just read from the tdb in the pointer 'printer'.
4224 convert_printer_info(info, printer, level);
4226 if (info->info_2->devmode_ptr != 0) {
4227 /* we have a valid devmode
4228 convert it and link it*/
4231 * Ensure printer->info_2->devmode is a valid pointer
4232 * as we will be overwriting it in convert_devicemode().
4235 if (printer->info_2->devmode == NULL)
4236 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
4238 DEBUGADD(8,("Converting the devicemode struct\n"));
4239 convert_devicemode(devmode, printer->info_2->devmode);
4242 if (printer->info_2->devmode != NULL)
4243 free_nt_devicemode(&printer->info_2->devmode);
4244 printer->info_2->devmode=NULL;
4247 /* Do sanity check on the requested changes for Samba */
4249 if (!check_printer_ok(printer->info_2, snum)) {
4250 result = ERROR_INVALID_PARAMETER;
4254 /* NT likes to call this function even though nothing has actually
4255 changed. Check this so the user doesn't end up with an
4256 annoying permission denied dialog box. */
4258 if (nt_printer_info_level_equal(printer, old_printer)) {
4259 DEBUG(3, ("printer info has not changed\n"));
4260 result = NT_STATUS_NO_PROBLEMO;
4264 /* Check calling user has permission to update printer description */
4266 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4267 DEBUG(3, ("printer property change denied by security "
4269 result = ERROR_ACCESS_DENIED;
4273 /* Call addprinter hook */
4275 if (*lp_addprinter_cmd() )
4276 if ( !add_printer_hook(printer) ) {
4277 result = ERROR_ACCESS_DENIED;
4281 /* Update printer info */
4283 if (add_a_printer(*printer, 2)!=0) {
4284 /* I don't really know what to return here !!! */
4285 result = ERROR_ACCESS_DENIED;
4290 free_a_printer(&printer, 2);
4291 free_a_printer(&old_printer, 2);
4293 srv_spoolss_sendnotify(handle);
4298 /****************************************************************************
4299 ****************************************************************************/
4300 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
4301 const SPOOL_PRINTER_INFO_LEVEL *info,
4302 DEVMODE_CTR devmode_ctr,
4303 SEC_DESC_BUF *secdesc_ctr,
4304 uint32 command, pipes_struct *p)
4306 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4308 if (!OPEN_HANDLE(Printer)) {
4309 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4310 return ERROR_INVALID_HANDLE;
4313 /* check the level */
4316 return control_printer(handle, command, p);
4318 return update_printer(handle, level, info, devmode_ctr.devmode);
4320 return update_printer_sec(handle, level, info, p,
4323 return ERROR_INVALID_LEVEL;
4327 /****************************************************************************
4328 ****************************************************************************/
4329 uint32 _spoolss_fcpn(POLICY_HND *handle)
4331 Printer_entry *Printer= find_printer_index_by_hnd(handle);
4333 if (!OPEN_HANDLE(Printer)) {
4334 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4335 return ERROR_INVALID_HANDLE;
4338 if (Printer->notify.client_connected==True)
4339 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4340 return ERROR_INVALID_HANDLE;
4342 Printer->notify.flags=0;
4343 Printer->notify.options=0;
4344 Printer->notify.localmachine[0]='\0';
4345 Printer->notify.printerlocal=0;
4346 if (Printer->notify.option)
4347 safe_free(Printer->notify.option->ctr.type);
4348 safe_free(Printer->notify.option);
4349 Printer->notify.option=NULL;
4350 Printer->notify.client_connected=False;
4352 return NT_STATUS_NO_PROBLEMO;
4355 /****************************************************************************
4356 ****************************************************************************/
4357 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
4358 NEW_BUFFER *buffer, uint32 offered,
4362 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4363 returns for AddJob. AddJob
4364 must fail on non-local
4368 /****************************************************************************
4369 ****************************************************************************/
4370 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4371 int position, int snum)
4377 t=gmtime(&queue->time);
4378 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4380 job_info->jobid=queue->job;
4381 init_unistr(&job_info->printername, lp_servicename(snum));
4382 init_unistr(&job_info->machinename, temp_name);
4383 init_unistr(&job_info->username, queue->user);
4384 init_unistr(&job_info->document, queue->file);
4385 init_unistr(&job_info->datatype, "RAW");
4386 init_unistr(&job_info->text_status, "");
4387 job_info->status=nt_printj_status(queue->status);
4388 job_info->priority=queue->priority;
4389 job_info->position=position;
4390 job_info->totalpages=0;
4391 job_info->pagesprinted=0;
4393 make_systemtime(&job_info->submitted, t);
4396 /****************************************************************************
4397 ****************************************************************************/
4398 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4399 int position, int snum,
4400 NT_PRINTER_INFO_LEVEL *ntprinter)
4406 t=gmtime(&queue->time);
4407 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4409 job_info->jobid=queue->job;
4411 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4413 init_unistr(&job_info->printername, chaine);
4415 init_unistr(&job_info->machinename, temp_name);
4416 init_unistr(&job_info->username, queue->user);
4417 init_unistr(&job_info->document, queue->file);
4418 init_unistr(&job_info->notifyname, queue->user);
4419 init_unistr(&job_info->datatype, "RAW");
4420 init_unistr(&job_info->printprocessor, "winprint");
4421 init_unistr(&job_info->parameters, "");
4422 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4423 init_unistr(&job_info->text_status, "");
4425 /* and here the security descriptor */
4427 job_info->status=nt_printj_status(queue->status);
4428 job_info->priority=queue->priority;
4429 job_info->position=position;
4430 job_info->starttime=0;
4431 job_info->untiltime=0;
4432 job_info->totalpages=0;
4433 job_info->size=queue->size;
4434 make_systemtime(&(job_info->submitted), t);
4435 job_info->timeelapsed=0;
4436 job_info->pagesprinted=0;
4438 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4445 /****************************************************************************
4446 Enumjobs at level 1.
4447 ****************************************************************************/
4448 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4449 NEW_BUFFER *buffer, uint32 offered,
4450 uint32 *needed, uint32 *returned)
4455 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4459 return ERROR_NOT_ENOUGH_MEMORY;
4462 for (i=0; i<*returned; i++)
4463 fill_job_info_1(&info[i], &queue[i], i, snum);
4467 /* check the required size. */
4468 for (i=0; i<*returned; i++)
4469 (*needed) += spoolss_size_job_info_1(&info[i]);
4471 if (!alloc_buffer_size(buffer, *needed)) {
4473 return ERROR_INSUFFICIENT_BUFFER;
4476 /* fill the buffer with the structures */
4477 for (i=0; i<*returned; i++)
4478 new_smb_io_job_info_1("", buffer, &info[i], 0);
4483 if (*needed > offered) {
4485 return ERROR_INSUFFICIENT_BUFFER;
4488 return NT_STATUS_NO_PROBLEMO;
4491 /****************************************************************************
4492 Enumjobs at level 2.
4493 ****************************************************************************/
4494 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4495 NEW_BUFFER *buffer, uint32 offered,
4496 uint32 *needed, uint32 *returned)
4498 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4502 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4505 return ERROR_NOT_ENOUGH_MEMORY;
4508 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4510 return ERROR_NOT_ENOUGH_MEMORY;
4513 for (i=0; i<*returned; i++)
4514 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4516 free_a_printer(&ntprinter, 2);
4519 /* check the required size. */
4520 for (i=0; i<*returned; i++)
4521 (*needed) += spoolss_size_job_info_2(&info[i]);
4523 if (!alloc_buffer_size(buffer, *needed)) {
4525 return ERROR_INSUFFICIENT_BUFFER;
4528 /* fill the buffer with the structures */
4529 for (i=0; i<*returned; i++)
4530 new_smb_io_job_info_2("", buffer, &info[i], 0);
4533 for (i = 0; i < *returned; i++)
4534 free_job_info_2(&info[i]);
4538 if (*needed > offered) {
4540 return ERROR_INSUFFICIENT_BUFFER;
4543 return NT_STATUS_NO_PROBLEMO;
4546 /****************************************************************************
4548 ****************************************************************************/
4549 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4550 NEW_BUFFER *buffer, uint32 offered,
4551 uint32 *needed, uint32 *returned)
4554 print_queue_struct *queue=NULL;
4555 print_status_struct prt_status;
4557 DEBUG(4,("_spoolss_enumjobs\n"));
4559 ZERO_STRUCT(prt_status);
4564 if (!get_printer_snum(handle, &snum))
4565 return ERROR_INVALID_HANDLE;
4567 *returned = print_queue_status(snum, &queue, &prt_status);
4568 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4570 if (*returned == 0) {
4572 return NT_STATUS_NO_PROBLEMO;
4577 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4579 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4583 return ERROR_INVALID_LEVEL;
4588 /****************************************************************************
4589 ****************************************************************************/
4590 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4595 /****************************************************************************
4596 ****************************************************************************/
4597 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4598 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4600 struct current_user user;
4601 print_status_struct prt_status;
4602 int snum, errcode = ERROR_INVALID_FUNCTION;
4604 memset(&prt_status, 0, sizeof(prt_status));
4606 if (!get_printer_snum(handle, &snum)) {
4607 return ERROR_INVALID_HANDLE;
4610 if (!print_job_exists(jobid)) {
4611 return ERROR_INVALID_PRINTER_NAME;
4614 get_current_user(&user, p);
4617 case JOB_CONTROL_CANCEL:
4618 case JOB_CONTROL_DELETE:
4619 if (print_job_delete(&user, jobid, &errcode)) {
4623 case JOB_CONTROL_PAUSE:
4624 if (print_job_pause(&user, jobid, &errcode)) {
4628 case JOB_CONTROL_RESTART:
4629 case JOB_CONTROL_RESUME:
4630 if (print_job_resume(&user, jobid, &errcode)) {
4635 return ERROR_INVALID_LEVEL;
4641 /****************************************************************************
4642 Enumerates all printer drivers at level 1.
4643 ****************************************************************************/
4644 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4649 fstring *list = NULL;
4651 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4652 DRIVER_INFO_1 *driver_info_1=NULL;
4656 #define MAX_VERSION 4
4658 for (version=0; version<MAX_VERSION; version++) {
4660 ndrivers=get_ntdrivers(&list, architecture, version);
4661 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4664 return ERROR_NOT_ENOUGH_MEMORY;
4667 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4669 return ERROR_NOT_ENOUGH_MEMORY;
4673 for (i=0; i<ndrivers; i++) {
4675 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4676 ZERO_STRUCT(driver);
4677 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4681 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4682 free_a_printer_driver(driver, 3);
4685 *returned+=ndrivers;
4689 /* check the required size. */
4690 for (i=0; i<*returned; i++) {
4691 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4692 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4695 if (!alloc_buffer_size(buffer, *needed)) {
4696 safe_free(driver_info_1);
4697 return ERROR_INSUFFICIENT_BUFFER;
4700 /* fill the buffer with the form structures */
4701 for (i=0; i<*returned; i++) {
4702 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4703 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4706 safe_free(driver_info_1);
4708 if (*needed > offered) {
4710 return ERROR_INSUFFICIENT_BUFFER;
4713 return NT_STATUS_NO_PROBLEMO;
4716 /****************************************************************************
4717 Enumerates all printer drivers at level 2.
4718 ****************************************************************************/
4719 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4724 fstring *list = NULL;
4726 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4727 DRIVER_INFO_2 *driver_info_2=NULL;
4731 #define MAX_VERSION 4
4733 for (version=0; version<MAX_VERSION; version++) {
4735 ndrivers=get_ntdrivers(&list, architecture, version);
4736 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4739 return ERROR_NOT_ENOUGH_MEMORY;
4742 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4744 return ERROR_NOT_ENOUGH_MEMORY;
4748 for (i=0; i<ndrivers; i++) {
4751 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4752 ZERO_STRUCT(driver);
4753 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4757 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4758 free_a_printer_driver(driver, 3);
4761 *returned+=ndrivers;
4765 /* check the required size. */
4766 for (i=0; i<*returned; i++) {
4767 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4768 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4771 if (!alloc_buffer_size(buffer, *needed)) {
4772 safe_free(driver_info_2);
4773 return ERROR_INSUFFICIENT_BUFFER;
4776 /* fill the buffer with the form structures */
4777 for (i=0; i<*returned; i++) {
4778 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4779 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4782 safe_free(driver_info_2);
4784 if (*needed > offered) {
4786 return ERROR_INSUFFICIENT_BUFFER;
4789 return NT_STATUS_NO_PROBLEMO;
4792 /****************************************************************************
4793 Enumerates all printer drivers at level 3.
4794 ****************************************************************************/
4795 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4800 fstring *list = NULL;
4802 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4803 DRIVER_INFO_3 *driver_info_3=NULL;
4807 #define MAX_VERSION 4
4809 for (version=0; version<MAX_VERSION; version++) {
4811 ndrivers=get_ntdrivers(&list, architecture, version);
4812 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4815 return ERROR_NOT_ENOUGH_MEMORY;
4818 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4820 return ERROR_NOT_ENOUGH_MEMORY;
4824 for (i=0; i<ndrivers; i++) {
4827 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4828 ZERO_STRUCT(driver);
4829 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4833 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4834 free_a_printer_driver(driver, 3);
4837 *returned+=ndrivers;
4841 /* check the required size. */
4842 for (i=0; i<*returned; i++) {
4843 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4844 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4847 if (!alloc_buffer_size(buffer, *needed)) {
4848 safe_free(driver_info_3);
4849 return ERROR_INSUFFICIENT_BUFFER;
4852 /* fill the buffer with the driver structures */
4853 for (i=0; i<*returned; i++) {
4854 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4855 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4858 for (i=0; i<*returned; i++)
4859 safe_free(driver_info_3[i].dependentfiles);
4861 safe_free(driver_info_3);
4863 if (*needed > offered) {
4865 return ERROR_INSUFFICIENT_BUFFER;
4868 return NT_STATUS_NO_PROBLEMO;
4871 /****************************************************************************
4872 Enumerates all printer drivers.
4873 ****************************************************************************/
4874 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4875 NEW_BUFFER *buffer, uint32 offered,
4876 uint32 *needed, uint32 *returned)
4878 fstring *list = NULL;
4880 fstring architecture;
4882 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4883 fstrcpy(servername, global_myname);
4887 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4891 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4893 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4895 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4899 return ERROR_INVALID_LEVEL;
4903 /****************************************************************************
4904 ****************************************************************************/
4905 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4907 form->flag=list->flag;
4908 init_unistr(&form->name, list->name);
4909 form->width=list->width;
4910 form->length=list->length;
4911 form->left=list->left;
4912 form->top=list->top;
4913 form->right=list->right;
4914 form->bottom=list->bottom;
4917 /****************************************************************************
4918 ****************************************************************************/
4919 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4920 NEW_BUFFER *buffer, uint32 offered,
4921 uint32 *needed, uint32 *numofforms)
4923 nt_forms_struct *list=NULL;
4928 DEBUG(4,("_new_spoolss_enumforms\n"));
4929 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4930 DEBUGADD(5,("Info level [%d]\n", level));
4932 *numofforms = get_ntforms(&list);
4933 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4935 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4939 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4941 return ERROR_NOT_ENOUGH_MEMORY;
4944 /* construct the list of form structures */
4945 for (i=0; i<*numofforms; i++) {
4946 DEBUGADD(6,("Filling form number [%d]\n",i));
4947 fill_form_1(&forms_1[i], &list[i]);
4952 /* check the required size. */
4953 for (i=0; i<*numofforms; i++) {
4954 DEBUGADD(6,("adding form [%d]'s size\n",i));
4955 buffer_size += spoolss_size_form_1(&forms_1[i]);
4958 *needed=buffer_size;
4960 if (!alloc_buffer_size(buffer, buffer_size)){
4962 return ERROR_INSUFFICIENT_BUFFER;
4965 /* fill the buffer with the form structures */
4966 for (i=0; i<*numofforms; i++) {
4967 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4968 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4973 if (*needed > offered) {
4975 return ERROR_INSUFFICIENT_BUFFER;
4978 return NT_STATUS_NO_PROBLEMO;
4982 return ERROR_INVALID_LEVEL;
4987 /****************************************************************************
4988 ****************************************************************************/
4989 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4991 nt_forms_struct *list=NULL;
4997 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
4999 DEBUG(4,("_spoolss_getform\n"));
5000 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5001 DEBUGADD(5,("Info level [%d]\n", level));
5003 numofforms = get_ntforms(&list);
5004 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5006 if (numofforms == 0)
5007 return ERROR_NO_MORE_ITEMS;
5012 /* Check if the requested name is in the list of form structures */
5013 for (i=0; i<numofforms; i++) {
5015 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5017 if (strequal(form_name, list[i].name)) {
5018 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5019 fill_form_1(&form_1, &list[i]);
5026 /* check the required size. */
5028 *needed=spoolss_size_form_1(&form_1);
5030 if (!alloc_buffer_size(buffer, buffer_size)){
5031 return ERROR_INSUFFICIENT_BUFFER;
5034 if (*needed > offered) {
5035 return ERROR_INSUFFICIENT_BUFFER;
5038 /* fill the buffer with the form structures */
5039 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5040 new_smb_io_form_1("", buffer, &form_1, 0);
5042 return NT_STATUS_NO_PROBLEMO;
5046 return ERROR_INVALID_LEVEL;
5050 /****************************************************************************
5051 ****************************************************************************/
5052 static void fill_port_1(PORT_INFO_1 *port, char *name)
5054 init_unistr(&port->port_name, name);
5057 /****************************************************************************
5058 ****************************************************************************/
5059 static void fill_port_2(PORT_INFO_2 *port, char *name)
5061 init_unistr(&port->port_name, name);
5062 init_unistr(&port->monitor_name, "Local Monitor");
5063 init_unistr(&port->description, "Local Port");
5064 #define PORT_TYPE_WRITE 1
5065 port->port_type=PORT_TYPE_WRITE;
5069 /****************************************************************************
5071 ****************************************************************************/
5072 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5074 PORT_INFO_1 *ports=NULL;
5077 if (*lp_enumports_cmd()) {
5078 pid_t local_pid = sys_getpid();
5079 char *cmd = lp_enumports_cmd();
5087 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5088 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5092 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5093 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
5096 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5097 ret = smbrun(command, tmp_file, False);
5098 DEBUG(10,("Returned [%d]\n", ret));
5101 /* Is this the best error to return here? */
5102 return ERROR_ACCESS_DENIED;
5106 qlines = file_lines_load(tmp_file, &numlines,True);
5107 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5108 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5112 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5113 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5114 file_lines_free(qlines);
5115 return ERROR_NOT_ENOUGH_MEMORY;
5118 for (i=0; i<numlines; i++) {
5119 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5120 fill_port_1(&ports[i], qlines[i]);
5123 file_lines_free(qlines);
5126 *returned = numlines;
5129 *returned = 1; /* Sole Samba port returned. */
5131 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5132 return ERROR_NOT_ENOUGH_MEMORY;
5134 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5136 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5139 /* check the required size. */
5140 for (i=0; i<*returned; i++) {
5141 DEBUGADD(6,("adding port [%d]'s size\n", i));
5142 *needed += spoolss_size_port_info_1(&ports[i]);
5145 if (!alloc_buffer_size(buffer, *needed)) {
5147 return ERROR_INSUFFICIENT_BUFFER;
5150 /* fill the buffer with the ports structures */
5151 for (i=0; i<*returned; i++) {
5152 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5153 new_smb_io_port_1("", buffer, &ports[i], 0);
5158 if (*needed > offered) {
5160 return ERROR_INSUFFICIENT_BUFFER;
5163 return NT_STATUS_NO_PROBLEMO;
5166 /****************************************************************************
5168 ****************************************************************************/
5170 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5172 PORT_INFO_2 *ports=NULL;
5175 if (*lp_enumports_cmd()) {
5176 pid_t local_pid = sys_getpid();
5177 char *cmd = lp_enumports_cmd();
5185 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5186 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5190 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5191 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
5194 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5195 ret = smbrun(command, tmp_file, False);
5196 DEBUGADD(10,("returned [%d]\n", ret));
5199 /* Is this the best error to return here? */
5200 return ERROR_ACCESS_DENIED;
5204 qlines = file_lines_load(tmp_file, &numlines,True);
5205 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5206 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5210 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5211 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5212 file_lines_free(qlines);
5213 return ERROR_NOT_ENOUGH_MEMORY;
5216 for (i=0; i<numlines; i++) {
5217 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5218 fill_port_2(&(ports[i]), qlines[i]);
5221 file_lines_free(qlines);
5224 *returned = numlines;
5230 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5231 return ERROR_NOT_ENOUGH_MEMORY;
5233 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5235 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5238 /* check the required size. */
5239 for (i=0; i<*returned; i++) {
5240 DEBUGADD(6,("adding port [%d]'s size\n", i));
5241 *needed += spoolss_size_port_info_2(&ports[i]);
5244 if (!alloc_buffer_size(buffer, *needed)) {
5246 return ERROR_INSUFFICIENT_BUFFER;
5249 /* fill the buffer with the ports structures */
5250 for (i=0; i<*returned; i++) {
5251 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5252 new_smb_io_port_2("", buffer, &ports[i], 0);
5257 if (*needed > offered) {
5259 return ERROR_INSUFFICIENT_BUFFER;
5262 return NT_STATUS_NO_PROBLEMO;
5265 /****************************************************************************
5267 ****************************************************************************/
5268 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
5269 NEW_BUFFER *buffer, uint32 offered,
5270 uint32 *needed, uint32 *returned)
5272 DEBUG(4,("_spoolss_enumports\n"));
5279 return enumports_level_1(buffer, offered, needed, returned);
5281 return enumports_level_2(buffer, offered, needed, returned);
5283 return ERROR_INVALID_LEVEL;
5287 /****************************************************************************
5288 ****************************************************************************/
5289 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5290 const SPOOL_PRINTER_INFO_LEVEL *info,
5291 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5292 uint32 user_switch, const SPOOL_USER_CTR *user,
5295 NT_PRINTER_INFO_LEVEL *printer = NULL;
5299 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5300 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5301 return ERROR_NOT_ENOUGH_MEMORY;
5304 ZERO_STRUCTP(printer);
5306 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5307 convert_printer_info(info, printer, 2);
5309 if (*lp_addprinter_cmd() )
5310 if ( !add_printer_hook(printer) ) {
5311 free_a_printer(&printer,2);
5312 return ERROR_ACCESS_DENIED;
5315 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5316 printer->info_2->sharename);
5318 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5319 free_a_printer(&printer,2);
5320 return ERROR_ACCESS_DENIED;
5323 /* you must be a printer admin to add a new printer */
5324 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5325 free_a_printer(&printer,2);
5326 return ERROR_ACCESS_DENIED;
5330 * Do sanity check on the requested changes for Samba.
5333 if (!check_printer_ok(printer->info_2, snum)) {
5334 free_a_printer(&printer,2);
5335 return ERROR_INVALID_PARAMETER;
5338 /* write the ASCII on disk */
5339 if (add_a_printer(*printer, 2) != 0) {
5340 free_a_printer(&printer,2);
5341 return ERROR_ACCESS_DENIED;
5344 if (!open_printer_hnd(handle, name)) {
5345 /* Handle open failed - remove addition. */
5346 del_a_printer(printer->info_2->sharename);
5347 free_a_printer(&printer,2);
5348 return ERROR_ACCESS_DENIED;
5351 free_a_printer(&printer,2);
5353 srv_spoolss_sendnotify(handle);
5355 return NT_STATUS_NO_PROBLEMO;
5358 /****************************************************************************
5359 ****************************************************************************/
5360 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5361 const SPOOL_PRINTER_INFO_LEVEL *info,
5362 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5363 uint32 user_switch, const SPOOL_USER_CTR *user,
5368 /* we don't handle yet */
5369 /* but I know what to do ... */
5370 return ERROR_INVALID_LEVEL;
5372 return spoolss_addprinterex_level_2(uni_srv_name, info,
5373 unk0, unk1, unk2, unk3,
5374 user_switch, user, handle);
5376 return ERROR_INVALID_LEVEL;
5380 /****************************************************************************
5381 ****************************************************************************/
5382 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5383 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5385 uint32 err = NT_STATUS_NO_PROBLEMO;
5386 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5387 struct current_user user;
5389 ZERO_STRUCT(driver);
5391 get_current_user(&user, p);
5393 convert_printer_driver_info(info, &driver, level);
5395 DEBUG(5,("Cleaning driver's information\n"));
5396 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5399 DEBUG(5,("Moving driver to final destination\n"));
5400 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5402 err = ERROR_ACCESS_DENIED;
5406 if (add_a_printer_driver(driver, level)!=0) {
5407 err = ERROR_ACCESS_DENIED;
5412 free_a_printer_driver(driver, level);
5416 /****************************************************************************
5417 ****************************************************************************/
5418 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5420 init_unistr(&info->name, name);
5423 /****************************************************************************
5424 ****************************************************************************/
5425 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5429 pstring short_archi;
5430 DRIVER_DIRECTORY_1 *info=NULL;
5432 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5434 if (get_short_archi(short_archi, long_archi)==FALSE)
5435 return ERROR_INVALID_ENVIRONMENT;
5437 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5438 return ERROR_NOT_ENOUGH_MEMORY;
5440 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5442 DEBUG(4,("printer driver directory: [%s]\n", path));
5444 fill_driverdir_1(info, path);
5446 *needed += spoolss_size_driverdir_info_1(info);
5448 if (!alloc_buffer_size(buffer, *needed)) {
5450 return ERROR_INSUFFICIENT_BUFFER;
5453 new_smb_io_driverdir_1("", buffer, info, 0);
5457 if (*needed > offered)
5458 return ERROR_INSUFFICIENT_BUFFER;
5460 return NT_STATUS_NO_PROBLEMO;
5463 /****************************************************************************
5464 ****************************************************************************/
5465 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5466 NEW_BUFFER *buffer, uint32 offered,
5469 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5475 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5477 return ERROR_INVALID_LEVEL;
5481 /****************************************************************************
5482 ****************************************************************************/
5483 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5484 uint32 in_value_len, uint32 in_data_len,
5485 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5487 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5489 NT_PRINTER_INFO_LEVEL *printer = NULL;
5494 uint32 biggest_valuesize;
5495 uint32 biggest_datasize;
5497 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5502 ZERO_STRUCT(printer);
5504 *out_max_value_len=0;
5510 *out_max_data_len=0;
5514 DEBUG(5,("spoolss_enumprinterdata\n"));
5516 if (!OPEN_HANDLE(Printer)) {
5517 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5518 return ERROR_INVALID_HANDLE;
5521 if (!get_printer_snum(handle, &snum))
5522 return ERROR_INVALID_HANDLE;
5524 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5525 return ERROR_INVALID_HANDLE;
5528 * The NT machine wants to know the biggest size of value and data
5530 * cf: MSDN EnumPrinterData remark section
5532 if ( (in_value_len==0) && (in_data_len==0) ) {
5533 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5537 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5538 * if this parameter size doesn't exist.
5539 * Ok - my opinion here is that the client is not asking for the greatest
5540 * possible size of all the parameters, but is asking specifically for the size needed
5541 * for this specific parameter. In that case we can remove the loop below and
5542 * simplify this lookup code considerably. JF - comments welcome. JRA.
5545 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5547 free_a_printer(&printer, 2);
5548 return ERROR_NO_MORE_ITEMS;
5556 biggest_valuesize=0;
5559 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5560 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5561 if (data_len > biggest_datasize) biggest_datasize=data_len;
5563 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5571 * I think this is correct, it doesn't break APW and
5572 * allows Gerald's Win32 test programs to work correctly,
5573 * but may need altering.... JRA.
5576 if (param_index == 0) {
5577 /* No parameters found. */
5578 free_a_printer(&printer, 2);
5579 return ERROR_NO_MORE_ITEMS;
5582 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5583 *out_value_len=2*(1+biggest_valuesize);
5584 *out_data_len=biggest_datasize;
5586 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5588 free_a_printer(&printer, 2);
5589 return NT_STATUS_NO_PROBLEMO;
5593 * the value len is wrong in NT sp3
5594 * that's the number of bytes not the number of unicode chars
5597 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5599 free_a_printer(&printer, 2);
5600 return ERROR_NO_MORE_ITEMS;
5603 free_a_printer(&printer, 2);
5607 * - counted in bytes in the request
5608 * - counted in UNICODE chars in the max reply
5609 * - counted in bytes in the real size
5611 * take a pause *before* coding not *during* coding
5614 *out_max_value_len=(in_value_len/sizeof(uint16));
5615 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5617 return ERROR_NOT_ENOUGH_MEMORY;
5620 ZERO_STRUCTP(*out_value);
5621 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5625 /* the data is counted in bytes */
5626 *out_max_data_len=in_data_len;
5627 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5629 return ERROR_NOT_ENOUGH_MEMORY;
5632 memset(*data_out,'\0',in_data_len);
5633 memcpy(*data_out, data, (size_t)data_len);
5634 *out_data_len=data_len;
5638 return NT_STATUS_NO_PROBLEMO;
5641 /****************************************************************************
5642 ****************************************************************************/
5643 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5644 const UNISTR2 *value,
5649 uint32 numeric_data)
5651 NT_PRINTER_INFO_LEVEL *printer = NULL;
5652 NT_PRINTER_PARAM *param = NULL, old_param;
5654 uint32 status = 0x0;
5655 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5657 DEBUG(5,("spoolss_setprinterdata\n"));
5659 if (!OPEN_HANDLE(Printer)) {
5660 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5661 return ERROR_INVALID_HANDLE;
5664 if (!get_printer_snum(handle, &snum))
5665 return ERROR_INVALID_HANDLE;
5667 status = get_a_printer(&printer, 2, lp_servicename(snum));
5669 return ERROR_INVALID_NAME;
5671 convert_specific_param(¶m, value , type, data, real_len);
5673 /* Check if we are making any changes or not. Return true if
5674 nothing is actually changing. */
5676 ZERO_STRUCT(old_param);
5678 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5679 &old_param.type, (unsigned int *)&old_param.data_len)) {
5681 if (param->type == old_param.type &&
5682 param->data_len == old_param.data_len &&
5683 memcmp(param->data, old_param.data,
5684 old_param.data_len) == 0) {
5686 DEBUG(3, ("setprinterdata hasn't changed\n"));
5687 status = NT_STATUS_NO_PROBLEMO;
5694 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5695 DEBUG(3, ("security descriptor change denied by existing "
5696 "security descriptor\n"));
5697 status = ERROR_ACCESS_DENIED;
5701 unlink_specific_param_if_exist(printer->info_2, param);
5703 add_a_specific_param(printer->info_2, ¶m);
5704 status = mod_a_printer(*printer, 2);
5707 free_a_printer(&printer, 2);
5709 free_nt_printer_param(¶m);
5710 safe_free(old_param.data);
5715 /****************************************************************************
5716 ****************************************************************************/
5717 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5719 NT_PRINTER_INFO_LEVEL *printer = NULL;
5720 NT_PRINTER_PARAM param;
5722 uint32 status = 0x0;
5723 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5725 DEBUG(5,("spoolss_deleteprinterdata\n"));
5727 if (!OPEN_HANDLE(Printer)) {
5728 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5729 return ERROR_INVALID_HANDLE;
5732 if (!get_printer_snum(handle, &snum))
5733 return ERROR_INVALID_HANDLE;
5735 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5736 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
5737 "change denied by existing security descriptor\n"));
5738 return ERROR_ACCESS_DENIED;
5741 status = get_a_printer(&printer, 2, lp_servicename(snum));
5743 return ERROR_INVALID_NAME;
5745 ZERO_STRUCTP(¶m);
5746 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5748 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5749 status = ERROR_INVALID_PARAMETER;
5751 status = mod_a_printer(*printer, 2);
5753 free_a_printer(&printer, 2);
5757 /****************************************************************************
5758 ****************************************************************************/
5759 uint32 _spoolss_addform( POLICY_HND *handle,
5764 nt_forms_struct *list=NULL;
5765 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5767 DEBUG(5,("spoolss_addform\n"));
5769 if (!OPEN_HANDLE(Printer)) {
5770 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5771 return ERROR_INVALID_HANDLE;
5774 count=get_ntforms(&list);
5775 if(!add_a_form(&list, form, &count))
5776 return ERROR_NOT_ENOUGH_MEMORY;
5777 write_ntforms(&list, count);
5784 /****************************************************************************
5785 ****************************************************************************/
5786 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5790 nt_forms_struct *list=NULL;
5791 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5793 DEBUG(5,("spoolss_deleteform\n"));
5795 if (!OPEN_HANDLE(Printer)) {
5796 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5797 return ERROR_INVALID_HANDLE;
5800 count = get_ntforms(&list);
5801 if(!delete_a_form(&list, form_name, &count, &ret))
5802 return ERROR_INVALID_PARAMETER;
5809 /****************************************************************************
5810 ****************************************************************************/
5811 uint32 _spoolss_setform( POLICY_HND *handle,
5812 const UNISTR2 *uni_name,
5817 nt_forms_struct *list=NULL;
5818 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5820 DEBUG(5,("spoolss_setform\n"));
5822 if (!OPEN_HANDLE(Printer)) {
5823 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5824 return ERROR_INVALID_HANDLE;
5826 count=get_ntforms(&list);
5827 update_a_form(&list, form, count);
5828 write_ntforms(&list, count);
5835 /****************************************************************************
5836 enumprintprocessors level 1.
5837 ****************************************************************************/
5838 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5840 PRINTPROCESSOR_1 *info_1=NULL;
5842 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5843 return ERROR_NOT_ENOUGH_MEMORY;
5847 init_unistr(&info_1->name, "winprint");
5849 *needed += spoolss_size_printprocessor_info_1(info_1);
5851 if (!alloc_buffer_size(buffer, *needed))
5852 return ERROR_INSUFFICIENT_BUFFER;
5854 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5858 if (*needed > offered) {
5860 return ERROR_INSUFFICIENT_BUFFER;
5863 return NT_STATUS_NO_PROBLEMO;
5866 /****************************************************************************
5867 ****************************************************************************/
5868 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5869 NEW_BUFFER *buffer, uint32 offered,
5870 uint32 *needed, uint32 *returned)
5872 DEBUG(5,("spoolss_enumprintprocessors\n"));
5875 * Enumerate the print processors ...
5877 * Just reply with "winprint", to keep NT happy
5878 * and I can use my nice printer checker.
5886 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5888 return ERROR_INVALID_LEVEL;
5892 /****************************************************************************
5893 enumprintprocdatatypes level 1.
5894 ****************************************************************************/
5895 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5897 PRINTPROCDATATYPE_1 *info_1=NULL;
5899 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5900 return ERROR_NOT_ENOUGH_MEMORY;
5904 init_unistr(&info_1->name, "RAW");
5906 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5908 if (!alloc_buffer_size(buffer, *needed))
5909 return ERROR_INSUFFICIENT_BUFFER;
5911 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5915 if (*needed > offered) {
5917 return ERROR_INSUFFICIENT_BUFFER;
5920 return NT_STATUS_NO_PROBLEMO;
5923 /****************************************************************************
5924 ****************************************************************************/
5925 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5926 NEW_BUFFER *buffer, uint32 offered,
5927 uint32 *needed, uint32 *returned)
5929 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5936 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5938 return ERROR_INVALID_LEVEL;
5942 /****************************************************************************
5943 enumprintmonitors level 1.
5944 ****************************************************************************/
5945 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5947 PRINTMONITOR_1 *info_1=NULL;
5949 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5950 return ERROR_NOT_ENOUGH_MEMORY;
5954 init_unistr(&info_1->name, "Local Port");
5956 *needed += spoolss_size_printmonitor_info_1(info_1);
5958 if (!alloc_buffer_size(buffer, *needed))
5959 return ERROR_INSUFFICIENT_BUFFER;
5961 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5965 if (*needed > offered) {
5967 return ERROR_INSUFFICIENT_BUFFER;
5970 return NT_STATUS_NO_PROBLEMO;
5973 /****************************************************************************
5974 enumprintmonitors level 2.
5975 ****************************************************************************/
5976 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5978 PRINTMONITOR_2 *info_2=NULL;
5980 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5981 return ERROR_NOT_ENOUGH_MEMORY;
5985 init_unistr(&info_2->name, "Local Port");
5986 init_unistr(&info_2->environment, "Windows NT X86");
5987 init_unistr(&info_2->dll_name, "localmon.dll");
5989 *needed += spoolss_size_printmonitor_info_2(info_2);
5991 if (!alloc_buffer_size(buffer, *needed))
5992 return ERROR_INSUFFICIENT_BUFFER;
5994 smb_io_printmonitor_info_2("", buffer, info_2, 0);
5998 if (*needed > offered) {
6000 return ERROR_INSUFFICIENT_BUFFER;
6003 return NT_STATUS_NO_PROBLEMO;
6006 /****************************************************************************
6007 ****************************************************************************/
6008 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
6009 NEW_BUFFER *buffer, uint32 offered,
6010 uint32 *needed, uint32 *returned)
6012 DEBUG(5,("spoolss_enumprintmonitors\n"));
6015 * Enumerate the print monitors ...
6017 * Just reply with "Local Port", to keep NT happy
6018 * and I can use my nice printer checker.
6026 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6028 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6030 return ERROR_INVALID_LEVEL;
6034 /****************************************************************************
6035 ****************************************************************************/
6036 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6040 JOB_INFO_1 *info_1=NULL;
6042 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6044 if (info_1 == NULL) {
6046 return ERROR_NOT_ENOUGH_MEMORY;
6049 for (i=0; i<count && found==False; i++) {
6050 if (queue[i].job==(int)jobid)
6057 /* I shoud reply something else ... I can't find the good one */
6058 return NT_STATUS_NO_PROBLEMO;
6061 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6065 *needed += spoolss_size_job_info_1(info_1);
6067 if (!alloc_buffer_size(buffer, *needed)) {
6069 return ERROR_INSUFFICIENT_BUFFER;
6072 new_smb_io_job_info_1("", buffer, info_1, 0);
6076 if (*needed > offered)
6077 return ERROR_INSUFFICIENT_BUFFER;
6079 return NT_STATUS_NO_PROBLEMO;
6083 /****************************************************************************
6084 ****************************************************************************/
6085 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6090 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6092 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6094 ZERO_STRUCTP(info_2);
6096 if (info_2 == NULL) {
6098 return ERROR_NOT_ENOUGH_MEMORY;
6101 for (i=0; i<count && found==False; i++) {
6102 if (queue[i].job==(int)jobid)
6109 /* I shoud reply something else ... I can't find the good one */
6110 return NT_STATUS_NO_PROBLEMO;
6113 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6115 return ERROR_NOT_ENOUGH_MEMORY;
6118 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6120 free_a_printer(&ntprinter, 2);
6123 *needed += spoolss_size_job_info_2(info_2);
6125 if (!alloc_buffer_size(buffer, *needed)) {
6127 return ERROR_INSUFFICIENT_BUFFER;
6130 new_smb_io_job_info_2("", buffer, info_2, 0);
6132 free_job_info_2(info_2);
6135 if (*needed > offered)
6136 return ERROR_INSUFFICIENT_BUFFER;
6138 return NT_STATUS_NO_PROBLEMO;
6141 /****************************************************************************
6142 ****************************************************************************/
6143 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
6144 NEW_BUFFER *buffer, uint32 offered,
6149 print_queue_struct *queue=NULL;
6150 print_status_struct prt_status;
6152 DEBUG(5,("spoolss_getjob\n"));
6154 memset(&prt_status, 0, sizeof(prt_status));
6158 if (!get_printer_snum(handle, &snum))
6159 return ERROR_INVALID_HANDLE;
6161 count = print_queue_status(snum, &queue, &prt_status);
6163 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6164 count, prt_status.status, prt_status.message));
6168 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6170 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6173 return ERROR_INVALID_LEVEL;