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;
3661 srv_spoolss_sendnotify(handle);
3665 /********************************************************************
3666 * api_spoolss_getprinter
3667 * called from the spoolss dispatcher
3669 ********************************************************************/
3670 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3672 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3674 if (!OPEN_HANDLE(Printer)) {
3675 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3676 return ERROR_INVALID_HANDLE;
3679 Printer->document_started=False;
3680 print_job_end(Printer->jobid);
3681 /* error codes unhandled so far ... */
3683 srv_spoolss_sendnotify(handle);
3688 /****************************************************************************
3689 ****************************************************************************/
3690 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3693 uint32 *buffer_written)
3695 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3697 if (!OPEN_HANDLE(Printer)) {
3698 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3699 return ERROR_INVALID_HANDLE;
3702 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3708 /********************************************************************
3709 * api_spoolss_getprinter
3710 * called from the spoolss dispatcher
3712 ********************************************************************/
3713 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3716 struct current_user user;
3717 int snum, errcode = ERROR_INVALID_FUNCTION;
3718 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3720 get_current_user(&user, p);
3722 if (!OPEN_HANDLE(Printer)) {
3723 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3724 return ERROR_INVALID_HANDLE;
3727 if (!get_printer_snum(handle, &snum))
3728 return ERROR_INVALID_HANDLE;
3731 case PRINTER_CONTROL_PAUSE:
3732 if (print_queue_pause(&user, snum, &errcode)) {
3736 case PRINTER_CONTROL_RESUME:
3737 case PRINTER_CONTROL_UNPAUSE:
3738 if (print_queue_resume(&user, snum, &errcode)) {
3742 case PRINTER_CONTROL_PURGE:
3743 if (print_queue_purge(&user, snum, &errcode)) {
3748 return ERROR_INVALID_LEVEL;
3754 /********************************************************************
3755 * api_spoolss_abortprinter
3756 ********************************************************************/
3758 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3760 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3763 /********************************************************************
3764 * called by spoolss_api_setprinter
3765 * when updating a printer description
3766 ********************************************************************/
3767 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3768 const SPOOL_PRINTER_INFO_LEVEL *info,
3769 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3771 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3772 struct current_user user;
3776 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3778 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3779 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3780 OUR_HANDLE(handle)));
3782 result = ERROR_INVALID_HANDLE;
3786 /* NT seems to like setting the security descriptor even though
3787 nothing may have actually changed. This causes annoying
3788 dialog boxes when the user doesn't have permission to change
3789 the security descriptor. */
3791 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3793 if (DEBUGLEVEL >= 10) {
3797 acl = old_secdesc_ctr->sec->dacl;
3798 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3799 PRINTERNAME(snum), acl->num_aces));
3801 for (i = 0; i < acl->num_aces; i++) {
3804 sid_to_string(sid_str, &acl->ace[i].sid);
3806 DEBUG(10, ("%s 0x%08x\n", sid_str,
3807 acl->ace[i].info.mask));
3810 acl = secdesc_ctr->sec->dacl;
3813 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3814 PRINTERNAME(snum), acl->num_aces));
3816 for (i = 0; i < acl->num_aces; i++) {
3819 sid_to_string(sid_str, &acl->ace[i].sid);
3821 DEBUG(10, ("%s 0x%08x\n", sid_str,
3822 acl->ace[i].info.mask));
3825 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3829 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3831 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3832 result = NT_STATUS_NO_PROBLEMO;
3836 /* Work out which user is performing the operation */
3838 get_current_user(&user, p);
3840 /* Check the user has permissions to change the security
3841 descriptor. By experimentation with two NT machines, the user
3842 requires Full Access to the printer to change security
3845 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3846 result = ERROR_ACCESS_DENIED;
3850 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3853 free_sec_desc_buf(&new_secdesc_ctr);
3854 free_sec_desc_buf(&old_secdesc_ctr);
3859 /********************************************************************
3860 Do Samba sanity checks on a printer info struct.
3861 this has changed purpose: it now "canonicalises" printer
3862 info from a client rather than just checking it is correct
3863 ********************************************************************/
3865 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3867 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3868 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3870 /* we force some elements to "correct" values */
3871 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3872 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3873 global_myname, lp_servicename(snum));
3874 fstrcpy(info->sharename, lp_servicename(snum));
3875 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3876 | PRINTER_ATTRIBUTE_LOCAL \
3877 | PRINTER_ATTRIBUTE_RAW_ONLY \
3878 | PRINTER_ATTRIBUTE_QUEUED ;
3883 /****************************************************************************
3884 ****************************************************************************/
3885 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3887 pid_t local_pid = sys_getpid();
3888 char *cmd = lp_addprinter_cmd();
3893 pstring driverlocation;
3897 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3898 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3902 /* build driver path... only 9X architecture is needed for legacy reasons */
3903 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3905 /* change \ to \\ for the shell */
3906 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3908 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3909 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3910 cmd, printer->info_2->printername, printer->info_2->sharename,
3911 printer->info_2->portname, printer->info_2->drivername,
3912 printer->info_2->location, driverlocation);
3916 /* Convert script args to unix-codepage */
3917 dos_to_unix(command, True);
3918 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3919 ret = smbrun(command, tmp_file, False);
3920 DEBUGADD(10,("returned [%d]\n", ret));
3928 /* Get lines and convert them back to dos-codepage */
3929 qlines = file_lines_load(tmp_file, &numlines, True);
3930 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3931 DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
3935 /* Set the portname to what the script says the portname should be. */
3936 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3937 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3939 /* Send SIGHUP to process group... is there a better way? */
3944 file_lines_free(qlines);
3948 /* Return true if two devicemodes are equal */
3950 #define DEVMODE_CHECK_INT(field) \
3951 if (d1->field != d2->field) { \
3952 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
3953 d1->field, d2->field)); \
3957 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3959 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
3962 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
3963 return False; /* if either is exclusively NULL are not equal */
3966 if (!strequal(d1->devicename, d2->devicename) ||
3967 !strequal(d1->formname, d2->formname)) {
3968 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
3972 DEVMODE_CHECK_INT(specversion);
3973 DEVMODE_CHECK_INT(driverversion);
3974 DEVMODE_CHECK_INT(driverextra);
3975 DEVMODE_CHECK_INT(orientation);
3976 DEVMODE_CHECK_INT(papersize);
3977 DEVMODE_CHECK_INT(paperlength);
3978 DEVMODE_CHECK_INT(paperwidth);
3979 DEVMODE_CHECK_INT(scale);
3980 DEVMODE_CHECK_INT(copies);
3981 DEVMODE_CHECK_INT(defaultsource);
3982 DEVMODE_CHECK_INT(printquality);
3983 DEVMODE_CHECK_INT(color);
3984 DEVMODE_CHECK_INT(duplex);
3985 DEVMODE_CHECK_INT(yresolution);
3986 DEVMODE_CHECK_INT(ttoption);
3987 DEVMODE_CHECK_INT(collate);
3988 DEVMODE_CHECK_INT(logpixels);
3990 DEVMODE_CHECK_INT(fields);
3991 DEVMODE_CHECK_INT(bitsperpel);
3992 DEVMODE_CHECK_INT(pelswidth);
3993 DEVMODE_CHECK_INT(pelsheight);
3994 DEVMODE_CHECK_INT(displayflags);
3995 DEVMODE_CHECK_INT(displayfrequency);
3996 DEVMODE_CHECK_INT(icmmethod);
3997 DEVMODE_CHECK_INT(icmintent);
3998 DEVMODE_CHECK_INT(mediatype);
3999 DEVMODE_CHECK_INT(dithertype);
4000 DEVMODE_CHECK_INT(reserved1);
4001 DEVMODE_CHECK_INT(reserved2);
4002 DEVMODE_CHECK_INT(panningwidth);
4003 DEVMODE_CHECK_INT(panningheight);
4005 /* compare the private data if it exists */
4006 if (!d1->driverextra && !d2->driverextra) goto equal;
4009 DEVMODE_CHECK_INT(driverextra);
4011 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4012 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4017 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4021 /* Return true if two NT_PRINTER_PARAM structures are equal */
4023 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4024 NT_PRINTER_PARAM *p2)
4026 if (!p1 && !p2) goto equal;
4028 if ((!p1 && p2) || (p1 && !p2)) {
4029 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4033 /* Compare lists of printer parameters */
4037 NT_PRINTER_PARAM *q = p1;
4039 /* Find the parameter in the second structure */
4043 if (strequal(p1->value, q->value)) {
4045 if (p1->type != q->type) {
4046 DEBUG(10, ("nt_printer_param_equal():"
4047 "types for %s differ (%d != %d)\n",
4048 p1->value, p1->type,
4053 if (p1->data_len != q->data_len) {
4054 DEBUG(10, ("nt_printer_param_equal():"
4055 "len for %s differs (%d != %d)\n",
4056 p1->value, p1->data_len,
4061 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4064 DEBUG(10, ("nt_printer_param_equal():"
4065 "data for %s differs\n", p1->value));
4075 DEBUG(10, ("nt_printer_param_equal(): param %s "
4076 "does not exist\n", p1->value));
4085 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4089 /********************************************************************
4090 * Called by update_printer when trying to work out whether to
4091 * actually update printer info.
4092 ********************************************************************/
4094 #define PI_CHECK_INT(field) \
4095 if (pi1->field != pi2->field) { \
4096 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4097 pi1->field, pi2->field)); \
4101 #define PI_CHECK_STR(field) \
4102 if (!strequal(pi1->field, pi2->field)) { \
4103 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4104 pi1->field, pi2->field)); \
4108 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4109 NT_PRINTER_INFO_LEVEL *p2)
4111 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4113 /* Trivial conditions */
4115 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4119 if ((!p1 && p2) || (p1 && !p2) ||
4120 (!p1->info_2 && p2->info_2) ||
4121 (p1->info_2 && !p2->info_2)) {
4122 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4127 /* Compare two nt_printer_info_level structures. Don't compare
4128 status or cjobs as they seem to have something to do with the
4134 PI_CHECK_INT(attributes);
4135 PI_CHECK_INT(priority);
4136 PI_CHECK_INT(default_priority);
4137 PI_CHECK_INT(starttime);
4138 PI_CHECK_INT(untiltime);
4139 PI_CHECK_INT(averageppm);
4141 /* Yuck - don't check the printername or servername as the
4142 add_a_printer() code plays games with them. You can't
4143 change the printername or the sharename through this interface
4146 PI_CHECK_STR(sharename);
4147 PI_CHECK_STR(portname);
4148 PI_CHECK_STR(drivername);
4149 PI_CHECK_STR(comment);
4150 PI_CHECK_STR(location);
4152 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4156 PI_CHECK_STR(sepfile);
4157 PI_CHECK_STR(printprocessor);
4158 PI_CHECK_STR(datatype);
4159 PI_CHECK_STR(parameters);
4161 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4165 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4169 PI_CHECK_INT(changeid);
4170 PI_CHECK_INT(c_setprinter);
4171 PI_CHECK_INT(setuptime);
4174 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4178 /********************************************************************
4179 * called by spoolss_api_setprinter
4180 * when updating a printer description
4181 ********************************************************************/
4183 static uint32 update_printer(POLICY_HND *handle, uint32 level,
4184 const SPOOL_PRINTER_INFO_LEVEL *info,
4185 DEVICEMODE *devmode)
4188 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4189 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4192 DEBUG(8,("update_printer\n"));
4194 result = NT_STATUS_NO_PROBLEMO;
4197 DEBUG(0,("Send a mail to samba@samba.org\n"));
4198 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4199 result = ERROR_INVALID_LEVEL;
4203 if (!OPEN_HANDLE(Printer)) {
4204 result = ERROR_INVALID_HANDLE;
4208 if (!get_printer_snum(handle, &snum)) {
4209 result = ERROR_INVALID_HANDLE;
4213 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4214 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4215 result = ERROR_INVALID_HANDLE;
4219 DEBUGADD(8,("Converting info_2 struct\n"));
4222 * convert_printer_info converts the incoming
4223 * info from the client and overwrites the info
4224 * just read from the tdb in the pointer 'printer'.
4227 convert_printer_info(info, printer, level);
4229 if (info->info_2->devmode_ptr != 0) {
4230 /* we have a valid devmode
4231 convert it and link it*/
4234 * Ensure printer->info_2->devmode is a valid pointer
4235 * as we will be overwriting it in convert_devicemode().
4238 if (printer->info_2->devmode == NULL)
4239 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
4241 DEBUGADD(8,("Converting the devicemode struct\n"));
4242 convert_devicemode(devmode, printer->info_2->devmode);
4245 if (printer->info_2->devmode != NULL)
4246 free_nt_devicemode(&printer->info_2->devmode);
4247 printer->info_2->devmode=NULL;
4250 /* Do sanity check on the requested changes for Samba */
4252 if (!check_printer_ok(printer->info_2, snum)) {
4253 result = ERROR_INVALID_PARAMETER;
4257 /* NT likes to call this function even though nothing has actually
4258 changed. Check this so the user doesn't end up with an
4259 annoying permission denied dialog box. */
4261 if (nt_printer_info_level_equal(printer, old_printer)) {
4262 DEBUG(3, ("printer info has not changed\n"));
4263 result = NT_STATUS_NO_PROBLEMO;
4267 /* Check calling user has permission to update printer description */
4269 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4270 DEBUG(3, ("printer property change denied by security "
4272 result = ERROR_ACCESS_DENIED;
4276 /* Call addprinter hook */
4278 if (*lp_addprinter_cmd() )
4279 if ( !add_printer_hook(printer) ) {
4280 result = ERROR_ACCESS_DENIED;
4284 /* Update printer info */
4286 if (add_a_printer(*printer, 2)!=0) {
4287 /* I don't really know what to return here !!! */
4288 result = ERROR_ACCESS_DENIED;
4293 free_a_printer(&printer, 2);
4294 free_a_printer(&old_printer, 2);
4296 srv_spoolss_sendnotify(handle);
4301 /****************************************************************************
4302 ****************************************************************************/
4303 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
4304 const SPOOL_PRINTER_INFO_LEVEL *info,
4305 DEVMODE_CTR devmode_ctr,
4306 SEC_DESC_BUF *secdesc_ctr,
4307 uint32 command, pipes_struct *p)
4309 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4311 if (!OPEN_HANDLE(Printer)) {
4312 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4313 return ERROR_INVALID_HANDLE;
4316 /* check the level */
4319 return control_printer(handle, command, p);
4321 return update_printer(handle, level, info, devmode_ctr.devmode);
4323 return update_printer_sec(handle, level, info, p,
4326 return ERROR_INVALID_LEVEL;
4330 /****************************************************************************
4331 ****************************************************************************/
4332 uint32 _spoolss_fcpn(POLICY_HND *handle)
4334 Printer_entry *Printer= find_printer_index_by_hnd(handle);
4336 if (!OPEN_HANDLE(Printer)) {
4337 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4338 return ERROR_INVALID_HANDLE;
4341 if (Printer->notify.client_connected==True)
4342 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4343 return ERROR_INVALID_HANDLE;
4345 Printer->notify.flags=0;
4346 Printer->notify.options=0;
4347 Printer->notify.localmachine[0]='\0';
4348 Printer->notify.printerlocal=0;
4349 if (Printer->notify.option)
4350 safe_free(Printer->notify.option->ctr.type);
4351 safe_free(Printer->notify.option);
4352 Printer->notify.option=NULL;
4353 Printer->notify.client_connected=False;
4355 return NT_STATUS_NO_PROBLEMO;
4358 /****************************************************************************
4359 ****************************************************************************/
4360 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
4361 NEW_BUFFER *buffer, uint32 offered,
4365 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4366 returns for AddJob. AddJob
4367 must fail on non-local
4371 /****************************************************************************
4372 ****************************************************************************/
4373 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4374 int position, int snum)
4380 t=gmtime(&queue->time);
4381 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4383 job_info->jobid=queue->job;
4384 init_unistr(&job_info->printername, lp_servicename(snum));
4385 init_unistr(&job_info->machinename, temp_name);
4386 init_unistr(&job_info->username, queue->user);
4387 init_unistr(&job_info->document, queue->file);
4388 init_unistr(&job_info->datatype, "RAW");
4389 init_unistr(&job_info->text_status, "");
4390 job_info->status=nt_printj_status(queue->status);
4391 job_info->priority=queue->priority;
4392 job_info->position=position;
4393 job_info->totalpages=0;
4394 job_info->pagesprinted=0;
4396 make_systemtime(&job_info->submitted, t);
4399 /****************************************************************************
4400 ****************************************************************************/
4401 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4402 int position, int snum,
4403 NT_PRINTER_INFO_LEVEL *ntprinter)
4409 t=gmtime(&queue->time);
4410 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4412 job_info->jobid=queue->job;
4414 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4416 init_unistr(&job_info->printername, chaine);
4418 init_unistr(&job_info->machinename, temp_name);
4419 init_unistr(&job_info->username, queue->user);
4420 init_unistr(&job_info->document, queue->file);
4421 init_unistr(&job_info->notifyname, queue->user);
4422 init_unistr(&job_info->datatype, "RAW");
4423 init_unistr(&job_info->printprocessor, "winprint");
4424 init_unistr(&job_info->parameters, "");
4425 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4426 init_unistr(&job_info->text_status, "");
4428 /* and here the security descriptor */
4430 job_info->status=nt_printj_status(queue->status);
4431 job_info->priority=queue->priority;
4432 job_info->position=position;
4433 job_info->starttime=0;
4434 job_info->untiltime=0;
4435 job_info->totalpages=0;
4436 job_info->size=queue->size;
4437 make_systemtime(&(job_info->submitted), t);
4438 job_info->timeelapsed=0;
4439 job_info->pagesprinted=0;
4441 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4448 /****************************************************************************
4449 Enumjobs at level 1.
4450 ****************************************************************************/
4451 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4452 NEW_BUFFER *buffer, uint32 offered,
4453 uint32 *needed, uint32 *returned)
4458 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4462 return ERROR_NOT_ENOUGH_MEMORY;
4465 for (i=0; i<*returned; i++)
4466 fill_job_info_1(&info[i], &queue[i], i, snum);
4470 /* check the required size. */
4471 for (i=0; i<*returned; i++)
4472 (*needed) += spoolss_size_job_info_1(&info[i]);
4474 if (!alloc_buffer_size(buffer, *needed)) {
4476 return ERROR_INSUFFICIENT_BUFFER;
4479 /* fill the buffer with the structures */
4480 for (i=0; i<*returned; i++)
4481 new_smb_io_job_info_1("", buffer, &info[i], 0);
4486 if (*needed > offered) {
4488 return ERROR_INSUFFICIENT_BUFFER;
4491 return NT_STATUS_NO_PROBLEMO;
4494 /****************************************************************************
4495 Enumjobs at level 2.
4496 ****************************************************************************/
4497 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4498 NEW_BUFFER *buffer, uint32 offered,
4499 uint32 *needed, uint32 *returned)
4501 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4505 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4508 return ERROR_NOT_ENOUGH_MEMORY;
4511 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4513 return ERROR_NOT_ENOUGH_MEMORY;
4516 for (i=0; i<*returned; i++)
4517 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4519 free_a_printer(&ntprinter, 2);
4522 /* check the required size. */
4523 for (i=0; i<*returned; i++)
4524 (*needed) += spoolss_size_job_info_2(&info[i]);
4526 if (!alloc_buffer_size(buffer, *needed)) {
4528 return ERROR_INSUFFICIENT_BUFFER;
4531 /* fill the buffer with the structures */
4532 for (i=0; i<*returned; i++)
4533 new_smb_io_job_info_2("", buffer, &info[i], 0);
4536 for (i = 0; i < *returned; i++)
4537 free_job_info_2(&info[i]);
4541 if (*needed > offered) {
4543 return ERROR_INSUFFICIENT_BUFFER;
4546 return NT_STATUS_NO_PROBLEMO;
4549 /****************************************************************************
4551 ****************************************************************************/
4552 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4553 NEW_BUFFER *buffer, uint32 offered,
4554 uint32 *needed, uint32 *returned)
4557 print_queue_struct *queue=NULL;
4558 print_status_struct prt_status;
4560 DEBUG(4,("_spoolss_enumjobs\n"));
4562 ZERO_STRUCT(prt_status);
4567 if (!get_printer_snum(handle, &snum))
4568 return ERROR_INVALID_HANDLE;
4570 *returned = print_queue_status(snum, &queue, &prt_status);
4571 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4573 if (*returned == 0) {
4575 return NT_STATUS_NO_PROBLEMO;
4580 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4582 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4586 return ERROR_INVALID_LEVEL;
4591 /****************************************************************************
4592 ****************************************************************************/
4593 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4598 /****************************************************************************
4599 ****************************************************************************/
4600 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4601 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4603 struct current_user user;
4604 print_status_struct prt_status;
4605 int snum, errcode = ERROR_INVALID_FUNCTION;
4607 memset(&prt_status, 0, sizeof(prt_status));
4609 if (!get_printer_snum(handle, &snum)) {
4610 return ERROR_INVALID_HANDLE;
4613 if (!print_job_exists(jobid)) {
4614 return ERROR_INVALID_PRINTER_NAME;
4617 get_current_user(&user, p);
4620 case JOB_CONTROL_CANCEL:
4621 case JOB_CONTROL_DELETE:
4622 if (print_job_delete(&user, jobid, &errcode)) {
4626 case JOB_CONTROL_PAUSE:
4627 if (print_job_pause(&user, jobid, &errcode)) {
4631 case JOB_CONTROL_RESTART:
4632 case JOB_CONTROL_RESUME:
4633 if (print_job_resume(&user, jobid, &errcode)) {
4638 return ERROR_INVALID_LEVEL;
4644 /****************************************************************************
4645 Enumerates all printer drivers at level 1.
4646 ****************************************************************************/
4647 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4652 fstring *list = NULL;
4654 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4655 DRIVER_INFO_1 *driver_info_1=NULL;
4659 #define MAX_VERSION 4
4661 for (version=0; version<MAX_VERSION; version++) {
4663 ndrivers=get_ntdrivers(&list, architecture, version);
4664 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4667 return ERROR_NOT_ENOUGH_MEMORY;
4670 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4672 return ERROR_NOT_ENOUGH_MEMORY;
4676 for (i=0; i<ndrivers; i++) {
4678 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4679 ZERO_STRUCT(driver);
4680 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4684 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4685 free_a_printer_driver(driver, 3);
4688 *returned+=ndrivers;
4692 /* check the required size. */
4693 for (i=0; i<*returned; i++) {
4694 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4695 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4698 if (!alloc_buffer_size(buffer, *needed)) {
4699 safe_free(driver_info_1);
4700 return ERROR_INSUFFICIENT_BUFFER;
4703 /* fill the buffer with the form structures */
4704 for (i=0; i<*returned; i++) {
4705 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4706 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4709 safe_free(driver_info_1);
4711 if (*needed > offered) {
4713 return ERROR_INSUFFICIENT_BUFFER;
4716 return NT_STATUS_NO_PROBLEMO;
4719 /****************************************************************************
4720 Enumerates all printer drivers at level 2.
4721 ****************************************************************************/
4722 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4727 fstring *list = NULL;
4729 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4730 DRIVER_INFO_2 *driver_info_2=NULL;
4734 #define MAX_VERSION 4
4736 for (version=0; version<MAX_VERSION; version++) {
4738 ndrivers=get_ntdrivers(&list, architecture, version);
4739 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4742 return ERROR_NOT_ENOUGH_MEMORY;
4745 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4747 return ERROR_NOT_ENOUGH_MEMORY;
4751 for (i=0; i<ndrivers; i++) {
4754 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4755 ZERO_STRUCT(driver);
4756 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4760 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4761 free_a_printer_driver(driver, 3);
4764 *returned+=ndrivers;
4768 /* check the required size. */
4769 for (i=0; i<*returned; i++) {
4770 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4771 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4774 if (!alloc_buffer_size(buffer, *needed)) {
4775 safe_free(driver_info_2);
4776 return ERROR_INSUFFICIENT_BUFFER;
4779 /* fill the buffer with the form structures */
4780 for (i=0; i<*returned; i++) {
4781 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4782 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4785 safe_free(driver_info_2);
4787 if (*needed > offered) {
4789 return ERROR_INSUFFICIENT_BUFFER;
4792 return NT_STATUS_NO_PROBLEMO;
4795 /****************************************************************************
4796 Enumerates all printer drivers at level 3.
4797 ****************************************************************************/
4798 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4803 fstring *list = NULL;
4805 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4806 DRIVER_INFO_3 *driver_info_3=NULL;
4810 #define MAX_VERSION 4
4812 for (version=0; version<MAX_VERSION; version++) {
4814 ndrivers=get_ntdrivers(&list, architecture, version);
4815 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4818 return ERROR_NOT_ENOUGH_MEMORY;
4821 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4823 return ERROR_NOT_ENOUGH_MEMORY;
4827 for (i=0; i<ndrivers; i++) {
4830 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4831 ZERO_STRUCT(driver);
4832 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4836 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4837 free_a_printer_driver(driver, 3);
4840 *returned+=ndrivers;
4844 /* check the required size. */
4845 for (i=0; i<*returned; i++) {
4846 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4847 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4850 if (!alloc_buffer_size(buffer, *needed)) {
4851 safe_free(driver_info_3);
4852 return ERROR_INSUFFICIENT_BUFFER;
4855 /* fill the buffer with the driver structures */
4856 for (i=0; i<*returned; i++) {
4857 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4858 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4861 for (i=0; i<*returned; i++)
4862 safe_free(driver_info_3[i].dependentfiles);
4864 safe_free(driver_info_3);
4866 if (*needed > offered) {
4868 return ERROR_INSUFFICIENT_BUFFER;
4871 return NT_STATUS_NO_PROBLEMO;
4874 /****************************************************************************
4875 Enumerates all printer drivers.
4876 ****************************************************************************/
4877 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4878 NEW_BUFFER *buffer, uint32 offered,
4879 uint32 *needed, uint32 *returned)
4881 fstring *list = NULL;
4883 fstring architecture;
4885 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4886 fstrcpy(servername, global_myname);
4890 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4894 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4896 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4898 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4902 return ERROR_INVALID_LEVEL;
4906 /****************************************************************************
4907 ****************************************************************************/
4908 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4910 form->flag=list->flag;
4911 init_unistr(&form->name, list->name);
4912 form->width=list->width;
4913 form->length=list->length;
4914 form->left=list->left;
4915 form->top=list->top;
4916 form->right=list->right;
4917 form->bottom=list->bottom;
4920 /****************************************************************************
4921 ****************************************************************************/
4922 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4923 NEW_BUFFER *buffer, uint32 offered,
4924 uint32 *needed, uint32 *numofforms)
4926 nt_forms_struct *list=NULL;
4931 DEBUG(4,("_new_spoolss_enumforms\n"));
4932 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4933 DEBUGADD(5,("Info level [%d]\n", level));
4935 *numofforms = get_ntforms(&list);
4936 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4938 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4942 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4944 return ERROR_NOT_ENOUGH_MEMORY;
4947 /* construct the list of form structures */
4948 for (i=0; i<*numofforms; i++) {
4949 DEBUGADD(6,("Filling form number [%d]\n",i));
4950 fill_form_1(&forms_1[i], &list[i]);
4955 /* check the required size. */
4956 for (i=0; i<*numofforms; i++) {
4957 DEBUGADD(6,("adding form [%d]'s size\n",i));
4958 buffer_size += spoolss_size_form_1(&forms_1[i]);
4961 *needed=buffer_size;
4963 if (!alloc_buffer_size(buffer, buffer_size)){
4965 return ERROR_INSUFFICIENT_BUFFER;
4968 /* fill the buffer with the form structures */
4969 for (i=0; i<*numofforms; i++) {
4970 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4971 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4976 if (*needed > offered) {
4978 return ERROR_INSUFFICIENT_BUFFER;
4981 return NT_STATUS_NO_PROBLEMO;
4985 return ERROR_INVALID_LEVEL;
4990 /****************************************************************************
4991 ****************************************************************************/
4992 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4994 nt_forms_struct *list=NULL;
5000 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5002 DEBUG(4,("_spoolss_getform\n"));
5003 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5004 DEBUGADD(5,("Info level [%d]\n", level));
5006 numofforms = get_ntforms(&list);
5007 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5009 if (numofforms == 0)
5010 return ERROR_NO_MORE_ITEMS;
5015 /* Check if the requested name is in the list of form structures */
5016 for (i=0; i<numofforms; i++) {
5018 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5020 if (strequal(form_name, list[i].name)) {
5021 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5022 fill_form_1(&form_1, &list[i]);
5029 /* check the required size. */
5031 *needed=spoolss_size_form_1(&form_1);
5033 if (!alloc_buffer_size(buffer, buffer_size)){
5034 return ERROR_INSUFFICIENT_BUFFER;
5037 if (*needed > offered) {
5038 return ERROR_INSUFFICIENT_BUFFER;
5041 /* fill the buffer with the form structures */
5042 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5043 new_smb_io_form_1("", buffer, &form_1, 0);
5045 return NT_STATUS_NO_PROBLEMO;
5049 return ERROR_INVALID_LEVEL;
5053 /****************************************************************************
5054 ****************************************************************************/
5055 static void fill_port_1(PORT_INFO_1 *port, char *name)
5057 init_unistr(&port->port_name, name);
5060 /****************************************************************************
5061 ****************************************************************************/
5062 static void fill_port_2(PORT_INFO_2 *port, char *name)
5064 init_unistr(&port->port_name, name);
5065 init_unistr(&port->monitor_name, "Local Monitor");
5066 init_unistr(&port->description, "Local Port");
5067 #define PORT_TYPE_WRITE 1
5068 port->port_type=PORT_TYPE_WRITE;
5072 /****************************************************************************
5074 ****************************************************************************/
5075 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5077 PORT_INFO_1 *ports=NULL;
5080 if (*lp_enumports_cmd()) {
5081 pid_t local_pid = sys_getpid();
5082 char *cmd = lp_enumports_cmd();
5090 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5091 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5095 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5096 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
5099 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5100 ret = smbrun(command, tmp_file, False);
5101 DEBUG(10,("Returned [%d]\n", ret));
5104 /* Is this the best error to return here? */
5105 return ERROR_ACCESS_DENIED;
5109 qlines = file_lines_load(tmp_file, &numlines,True);
5110 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5111 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5115 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5116 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5117 file_lines_free(qlines);
5118 return ERROR_NOT_ENOUGH_MEMORY;
5121 for (i=0; i<numlines; i++) {
5122 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5123 fill_port_1(&ports[i], qlines[i]);
5126 file_lines_free(qlines);
5129 *returned = numlines;
5132 *returned = 1; /* Sole Samba port returned. */
5134 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5135 return ERROR_NOT_ENOUGH_MEMORY;
5137 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5139 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5142 /* check the required size. */
5143 for (i=0; i<*returned; i++) {
5144 DEBUGADD(6,("adding port [%d]'s size\n", i));
5145 *needed += spoolss_size_port_info_1(&ports[i]);
5148 if (!alloc_buffer_size(buffer, *needed)) {
5150 return ERROR_INSUFFICIENT_BUFFER;
5153 /* fill the buffer with the ports structures */
5154 for (i=0; i<*returned; i++) {
5155 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5156 new_smb_io_port_1("", buffer, &ports[i], 0);
5161 if (*needed > offered) {
5163 return ERROR_INSUFFICIENT_BUFFER;
5166 return NT_STATUS_NO_PROBLEMO;
5169 /****************************************************************************
5171 ****************************************************************************/
5173 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5175 PORT_INFO_2 *ports=NULL;
5178 if (*lp_enumports_cmd()) {
5179 pid_t local_pid = sys_getpid();
5180 char *cmd = lp_enumports_cmd();
5188 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5189 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5193 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5194 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
5197 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5198 ret = smbrun(command, tmp_file, False);
5199 DEBUGADD(10,("returned [%d]\n", ret));
5202 /* Is this the best error to return here? */
5203 return ERROR_ACCESS_DENIED;
5207 qlines = file_lines_load(tmp_file, &numlines,True);
5208 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5209 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5213 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5214 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5215 file_lines_free(qlines);
5216 return ERROR_NOT_ENOUGH_MEMORY;
5219 for (i=0; i<numlines; i++) {
5220 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5221 fill_port_2(&(ports[i]), qlines[i]);
5224 file_lines_free(qlines);
5227 *returned = numlines;
5233 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5234 return ERROR_NOT_ENOUGH_MEMORY;
5236 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5238 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5241 /* check the required size. */
5242 for (i=0; i<*returned; i++) {
5243 DEBUGADD(6,("adding port [%d]'s size\n", i));
5244 *needed += spoolss_size_port_info_2(&ports[i]);
5247 if (!alloc_buffer_size(buffer, *needed)) {
5249 return ERROR_INSUFFICIENT_BUFFER;
5252 /* fill the buffer with the ports structures */
5253 for (i=0; i<*returned; i++) {
5254 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5255 new_smb_io_port_2("", buffer, &ports[i], 0);
5260 if (*needed > offered) {
5262 return ERROR_INSUFFICIENT_BUFFER;
5265 return NT_STATUS_NO_PROBLEMO;
5268 /****************************************************************************
5270 ****************************************************************************/
5271 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
5272 NEW_BUFFER *buffer, uint32 offered,
5273 uint32 *needed, uint32 *returned)
5275 DEBUG(4,("_spoolss_enumports\n"));
5282 return enumports_level_1(buffer, offered, needed, returned);
5284 return enumports_level_2(buffer, offered, needed, returned);
5286 return ERROR_INVALID_LEVEL;
5290 /****************************************************************************
5291 ****************************************************************************/
5292 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5293 const SPOOL_PRINTER_INFO_LEVEL *info,
5294 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5295 uint32 user_switch, const SPOOL_USER_CTR *user,
5298 NT_PRINTER_INFO_LEVEL *printer = NULL;
5302 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5303 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5304 return ERROR_NOT_ENOUGH_MEMORY;
5307 ZERO_STRUCTP(printer);
5309 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5310 convert_printer_info(info, printer, 2);
5312 if (*lp_addprinter_cmd() )
5313 if ( !add_printer_hook(printer) ) {
5314 free_a_printer(&printer,2);
5315 return ERROR_ACCESS_DENIED;
5318 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5319 printer->info_2->sharename);
5321 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5322 free_a_printer(&printer,2);
5323 return ERROR_ACCESS_DENIED;
5326 /* you must be a printer admin to add a new printer */
5327 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5328 free_a_printer(&printer,2);
5329 return ERROR_ACCESS_DENIED;
5333 * Do sanity check on the requested changes for Samba.
5336 if (!check_printer_ok(printer->info_2, snum)) {
5337 free_a_printer(&printer,2);
5338 return ERROR_INVALID_PARAMETER;
5341 /* write the ASCII on disk */
5342 if (add_a_printer(*printer, 2) != 0) {
5343 free_a_printer(&printer,2);
5344 return ERROR_ACCESS_DENIED;
5347 if (!open_printer_hnd(handle, name)) {
5348 /* Handle open failed - remove addition. */
5349 del_a_printer(printer->info_2->sharename);
5350 free_a_printer(&printer,2);
5351 return ERROR_ACCESS_DENIED;
5354 free_a_printer(&printer,2);
5356 srv_spoolss_sendnotify(handle);
5358 return NT_STATUS_NO_PROBLEMO;
5361 /****************************************************************************
5362 ****************************************************************************/
5363 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5364 const SPOOL_PRINTER_INFO_LEVEL *info,
5365 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5366 uint32 user_switch, const SPOOL_USER_CTR *user,
5371 /* we don't handle yet */
5372 /* but I know what to do ... */
5373 return ERROR_INVALID_LEVEL;
5375 return spoolss_addprinterex_level_2(uni_srv_name, info,
5376 unk0, unk1, unk2, unk3,
5377 user_switch, user, handle);
5379 return ERROR_INVALID_LEVEL;
5383 /****************************************************************************
5384 ****************************************************************************/
5385 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5386 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5388 uint32 err = NT_STATUS_NO_PROBLEMO;
5389 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5390 struct current_user user;
5392 ZERO_STRUCT(driver);
5394 get_current_user(&user, p);
5396 convert_printer_driver_info(info, &driver, level);
5398 DEBUG(5,("Cleaning driver's information\n"));
5399 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5402 DEBUG(5,("Moving driver to final destination\n"));
5403 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5405 err = ERROR_ACCESS_DENIED;
5409 if (add_a_printer_driver(driver, level)!=0) {
5410 err = ERROR_ACCESS_DENIED;
5415 free_a_printer_driver(driver, level);
5419 /****************************************************************************
5420 ****************************************************************************/
5421 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5423 init_unistr(&info->name, name);
5426 /****************************************************************************
5427 ****************************************************************************/
5428 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5432 pstring short_archi;
5433 DRIVER_DIRECTORY_1 *info=NULL;
5435 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5437 if (get_short_archi(short_archi, long_archi)==FALSE)
5438 return ERROR_INVALID_ENVIRONMENT;
5440 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5441 return ERROR_NOT_ENOUGH_MEMORY;
5443 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5445 DEBUG(4,("printer driver directory: [%s]\n", path));
5447 fill_driverdir_1(info, path);
5449 *needed += spoolss_size_driverdir_info_1(info);
5451 if (!alloc_buffer_size(buffer, *needed)) {
5453 return ERROR_INSUFFICIENT_BUFFER;
5456 new_smb_io_driverdir_1("", buffer, info, 0);
5460 if (*needed > offered)
5461 return ERROR_INSUFFICIENT_BUFFER;
5463 return NT_STATUS_NO_PROBLEMO;
5466 /****************************************************************************
5467 ****************************************************************************/
5468 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5469 NEW_BUFFER *buffer, uint32 offered,
5472 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5478 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5480 return ERROR_INVALID_LEVEL;
5484 /****************************************************************************
5485 ****************************************************************************/
5486 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5487 uint32 in_value_len, uint32 in_data_len,
5488 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5490 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5492 NT_PRINTER_INFO_LEVEL *printer = NULL;
5497 uint32 biggest_valuesize;
5498 uint32 biggest_datasize;
5500 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5505 ZERO_STRUCT(printer);
5507 *out_max_value_len=0;
5513 *out_max_data_len=0;
5517 DEBUG(5,("spoolss_enumprinterdata\n"));
5519 if (!OPEN_HANDLE(Printer)) {
5520 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5521 return ERROR_INVALID_HANDLE;
5524 if (!get_printer_snum(handle, &snum))
5525 return ERROR_INVALID_HANDLE;
5527 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5528 return ERROR_INVALID_HANDLE;
5531 * The NT machine wants to know the biggest size of value and data
5533 * cf: MSDN EnumPrinterData remark section
5535 if ( (in_value_len==0) && (in_data_len==0) ) {
5536 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5540 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5541 * if this parameter size doesn't exist.
5542 * Ok - my opinion here is that the client is not asking for the greatest
5543 * possible size of all the parameters, but is asking specifically for the size needed
5544 * for this specific parameter. In that case we can remove the loop below and
5545 * simplify this lookup code considerably. JF - comments welcome. JRA.
5548 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5550 free_a_printer(&printer, 2);
5551 return ERROR_NO_MORE_ITEMS;
5559 biggest_valuesize=0;
5562 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5563 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5564 if (data_len > biggest_datasize) biggest_datasize=data_len;
5566 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5574 * I think this is correct, it doesn't break APW and
5575 * allows Gerald's Win32 test programs to work correctly,
5576 * but may need altering.... JRA.
5579 if (param_index == 0) {
5580 /* No parameters found. */
5581 free_a_printer(&printer, 2);
5582 return ERROR_NO_MORE_ITEMS;
5585 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5586 *out_value_len=2*(1+biggest_valuesize);
5587 *out_data_len=biggest_datasize;
5589 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5591 free_a_printer(&printer, 2);
5592 return NT_STATUS_NO_PROBLEMO;
5596 * the value len is wrong in NT sp3
5597 * that's the number of bytes not the number of unicode chars
5600 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5602 free_a_printer(&printer, 2);
5603 return ERROR_NO_MORE_ITEMS;
5606 free_a_printer(&printer, 2);
5610 * - counted in bytes in the request
5611 * - counted in UNICODE chars in the max reply
5612 * - counted in bytes in the real size
5614 * take a pause *before* coding not *during* coding
5617 *out_max_value_len=(in_value_len/sizeof(uint16));
5618 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5620 return ERROR_NOT_ENOUGH_MEMORY;
5623 ZERO_STRUCTP(*out_value);
5624 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5628 /* the data is counted in bytes */
5629 *out_max_data_len=in_data_len;
5630 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5632 return ERROR_NOT_ENOUGH_MEMORY;
5635 memset(*data_out,'\0',in_data_len);
5636 memcpy(*data_out, data, (size_t)data_len);
5637 *out_data_len=data_len;
5641 return NT_STATUS_NO_PROBLEMO;
5644 /****************************************************************************
5645 ****************************************************************************/
5646 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5647 const UNISTR2 *value,
5652 uint32 numeric_data)
5654 NT_PRINTER_INFO_LEVEL *printer = NULL;
5655 NT_PRINTER_PARAM *param = NULL, old_param;
5657 uint32 status = 0x0;
5658 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5660 DEBUG(5,("spoolss_setprinterdata\n"));
5662 if (!OPEN_HANDLE(Printer)) {
5663 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5664 return ERROR_INVALID_HANDLE;
5667 if (!get_printer_snum(handle, &snum))
5668 return ERROR_INVALID_HANDLE;
5670 status = get_a_printer(&printer, 2, lp_servicename(snum));
5672 return ERROR_INVALID_NAME;
5674 convert_specific_param(¶m, value , type, data, real_len);
5676 /* Check if we are making any changes or not. Return true if
5677 nothing is actually changing. */
5679 ZERO_STRUCT(old_param);
5681 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5682 &old_param.type, (unsigned int *)&old_param.data_len)) {
5684 if (param->type == old_param.type &&
5685 param->data_len == old_param.data_len &&
5686 memcmp(param->data, old_param.data,
5687 old_param.data_len) == 0) {
5689 DEBUG(3, ("setprinterdata hasn't changed\n"));
5690 status = NT_STATUS_NO_PROBLEMO;
5697 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5698 DEBUG(3, ("security descriptor change denied by existing "
5699 "security descriptor\n"));
5700 status = ERROR_ACCESS_DENIED;
5704 unlink_specific_param_if_exist(printer->info_2, param);
5706 add_a_specific_param(printer->info_2, ¶m);
5707 status = mod_a_printer(*printer, 2);
5710 free_a_printer(&printer, 2);
5712 free_nt_printer_param(¶m);
5713 safe_free(old_param.data);
5718 /****************************************************************************
5719 ****************************************************************************/
5720 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5722 NT_PRINTER_INFO_LEVEL *printer = NULL;
5723 NT_PRINTER_PARAM param;
5725 uint32 status = 0x0;
5726 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5728 DEBUG(5,("spoolss_deleteprinterdata\n"));
5730 if (!OPEN_HANDLE(Printer)) {
5731 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5732 return ERROR_INVALID_HANDLE;
5735 if (!get_printer_snum(handle, &snum))
5736 return ERROR_INVALID_HANDLE;
5738 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5739 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
5740 "change denied by existing security descriptor\n"));
5741 return ERROR_ACCESS_DENIED;
5744 status = get_a_printer(&printer, 2, lp_servicename(snum));
5746 return ERROR_INVALID_NAME;
5748 ZERO_STRUCTP(¶m);
5749 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5751 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5752 status = ERROR_INVALID_PARAMETER;
5754 status = mod_a_printer(*printer, 2);
5756 free_a_printer(&printer, 2);
5760 /****************************************************************************
5761 ****************************************************************************/
5762 uint32 _spoolss_addform( POLICY_HND *handle,
5767 nt_forms_struct *list=NULL;
5768 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5770 DEBUG(5,("spoolss_addform\n"));
5772 if (!OPEN_HANDLE(Printer)) {
5773 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5774 return ERROR_INVALID_HANDLE;
5777 count=get_ntforms(&list);
5778 if(!add_a_form(&list, form, &count))
5779 return ERROR_NOT_ENOUGH_MEMORY;
5780 write_ntforms(&list, count);
5787 /****************************************************************************
5788 ****************************************************************************/
5789 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5793 nt_forms_struct *list=NULL;
5794 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5796 DEBUG(5,("spoolss_deleteform\n"));
5798 if (!OPEN_HANDLE(Printer)) {
5799 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5800 return ERROR_INVALID_HANDLE;
5803 count = get_ntforms(&list);
5804 if(!delete_a_form(&list, form_name, &count, &ret))
5805 return ERROR_INVALID_PARAMETER;
5812 /****************************************************************************
5813 ****************************************************************************/
5814 uint32 _spoolss_setform( POLICY_HND *handle,
5815 const UNISTR2 *uni_name,
5820 nt_forms_struct *list=NULL;
5821 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5823 DEBUG(5,("spoolss_setform\n"));
5825 if (!OPEN_HANDLE(Printer)) {
5826 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5827 return ERROR_INVALID_HANDLE;
5829 count=get_ntforms(&list);
5830 update_a_form(&list, form, count);
5831 write_ntforms(&list, count);
5838 /****************************************************************************
5839 enumprintprocessors level 1.
5840 ****************************************************************************/
5841 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5843 PRINTPROCESSOR_1 *info_1=NULL;
5845 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5846 return ERROR_NOT_ENOUGH_MEMORY;
5850 init_unistr(&info_1->name, "winprint");
5852 *needed += spoolss_size_printprocessor_info_1(info_1);
5854 if (!alloc_buffer_size(buffer, *needed))
5855 return ERROR_INSUFFICIENT_BUFFER;
5857 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5861 if (*needed > offered) {
5863 return ERROR_INSUFFICIENT_BUFFER;
5866 return NT_STATUS_NO_PROBLEMO;
5869 /****************************************************************************
5870 ****************************************************************************/
5871 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5872 NEW_BUFFER *buffer, uint32 offered,
5873 uint32 *needed, uint32 *returned)
5875 DEBUG(5,("spoolss_enumprintprocessors\n"));
5878 * Enumerate the print processors ...
5880 * Just reply with "winprint", to keep NT happy
5881 * and I can use my nice printer checker.
5889 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5891 return ERROR_INVALID_LEVEL;
5895 /****************************************************************************
5896 enumprintprocdatatypes level 1.
5897 ****************************************************************************/
5898 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5900 PRINTPROCDATATYPE_1 *info_1=NULL;
5902 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5903 return ERROR_NOT_ENOUGH_MEMORY;
5907 init_unistr(&info_1->name, "RAW");
5909 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5911 if (!alloc_buffer_size(buffer, *needed))
5912 return ERROR_INSUFFICIENT_BUFFER;
5914 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5918 if (*needed > offered) {
5920 return ERROR_INSUFFICIENT_BUFFER;
5923 return NT_STATUS_NO_PROBLEMO;
5926 /****************************************************************************
5927 ****************************************************************************/
5928 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5929 NEW_BUFFER *buffer, uint32 offered,
5930 uint32 *needed, uint32 *returned)
5932 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5939 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5941 return ERROR_INVALID_LEVEL;
5945 /****************************************************************************
5946 enumprintmonitors level 1.
5947 ****************************************************************************/
5948 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5950 PRINTMONITOR_1 *info_1=NULL;
5952 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5953 return ERROR_NOT_ENOUGH_MEMORY;
5957 init_unistr(&info_1->name, "Local Port");
5959 *needed += spoolss_size_printmonitor_info_1(info_1);
5961 if (!alloc_buffer_size(buffer, *needed))
5962 return ERROR_INSUFFICIENT_BUFFER;
5964 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5968 if (*needed > offered) {
5970 return ERROR_INSUFFICIENT_BUFFER;
5973 return NT_STATUS_NO_PROBLEMO;
5976 /****************************************************************************
5977 enumprintmonitors level 2.
5978 ****************************************************************************/
5979 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5981 PRINTMONITOR_2 *info_2=NULL;
5983 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5984 return ERROR_NOT_ENOUGH_MEMORY;
5988 init_unistr(&info_2->name, "Local Port");
5989 init_unistr(&info_2->environment, "Windows NT X86");
5990 init_unistr(&info_2->dll_name, "localmon.dll");
5992 *needed += spoolss_size_printmonitor_info_2(info_2);
5994 if (!alloc_buffer_size(buffer, *needed))
5995 return ERROR_INSUFFICIENT_BUFFER;
5997 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6001 if (*needed > offered) {
6003 return ERROR_INSUFFICIENT_BUFFER;
6006 return NT_STATUS_NO_PROBLEMO;
6009 /****************************************************************************
6010 ****************************************************************************/
6011 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
6012 NEW_BUFFER *buffer, uint32 offered,
6013 uint32 *needed, uint32 *returned)
6015 DEBUG(5,("spoolss_enumprintmonitors\n"));
6018 * Enumerate the print monitors ...
6020 * Just reply with "Local Port", to keep NT happy
6021 * and I can use my nice printer checker.
6029 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6031 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6033 return ERROR_INVALID_LEVEL;
6037 /****************************************************************************
6038 ****************************************************************************/
6039 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6043 JOB_INFO_1 *info_1=NULL;
6045 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6047 if (info_1 == NULL) {
6049 return ERROR_NOT_ENOUGH_MEMORY;
6052 for (i=0; i<count && found==False; i++) {
6053 if (queue[i].job==(int)jobid)
6060 /* I shoud reply something else ... I can't find the good one */
6061 return NT_STATUS_NO_PROBLEMO;
6064 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6068 *needed += spoolss_size_job_info_1(info_1);
6070 if (!alloc_buffer_size(buffer, *needed)) {
6072 return ERROR_INSUFFICIENT_BUFFER;
6075 new_smb_io_job_info_1("", buffer, info_1, 0);
6079 if (*needed > offered)
6080 return ERROR_INSUFFICIENT_BUFFER;
6082 return NT_STATUS_NO_PROBLEMO;
6086 /****************************************************************************
6087 ****************************************************************************/
6088 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6093 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6095 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6097 ZERO_STRUCTP(info_2);
6099 if (info_2 == NULL) {
6101 return ERROR_NOT_ENOUGH_MEMORY;
6104 for (i=0; i<count && found==False; i++) {
6105 if (queue[i].job==(int)jobid)
6112 /* I shoud reply something else ... I can't find the good one */
6113 return NT_STATUS_NO_PROBLEMO;
6116 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6118 return ERROR_NOT_ENOUGH_MEMORY;
6121 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6123 free_a_printer(&ntprinter, 2);
6126 *needed += spoolss_size_job_info_2(info_2);
6128 if (!alloc_buffer_size(buffer, *needed)) {
6130 return ERROR_INSUFFICIENT_BUFFER;
6133 new_smb_io_job_info_2("", buffer, info_2, 0);
6135 free_job_info_2(info_2);
6138 if (*needed > offered)
6139 return ERROR_INSUFFICIENT_BUFFER;
6141 return NT_STATUS_NO_PROBLEMO;
6144 /****************************************************************************
6145 ****************************************************************************/
6146 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
6147 NEW_BUFFER *buffer, uint32 offered,
6152 print_queue_struct *queue=NULL;
6153 print_status_struct prt_status;
6155 DEBUG(5,("spoolss_getjob\n"));
6157 memset(&prt_status, 0, sizeof(prt_status));
6161 if (!get_printer_snum(handle, &snum))
6162 return ERROR_INVALID_HANDLE;
6164 count = print_queue_status(snum, &queue, &prt_status);
6166 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6167 count, prt_status.status, prt_status.message));
6171 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6173 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6176 return ERROR_INVALID_LEVEL;