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 uint32 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)));
249 return ERROR_INVALID_HANDLE;
252 if (del_a_printer(Printer->dev.handlename) != 0) {
253 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
254 return ERROR_INVALID_HANDLE;
257 /* Check calling user has permission to delete printer. Note that
258 since we set the snum parameter to -1 only administrators can
259 delete the printer. This stops people with the Full Control
260 permission from deleting the printer. */
262 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
263 DEBUG(3, ("printer delete denied by security descriptor\n"));
264 return ERROR_ACCESS_DENIED;
267 if (*lp_deleteprinter_cmd()) {
269 pid_t local_pid = sys_getpid();
270 char *cmd = lp_deleteprinter_cmd();
277 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
278 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
282 /* Printer->dev.handlename equals portname equals sharename */
283 slprintf(command, sizeof(command), "%s \"%s\"", cmd,
284 Printer->dev.handlename);
285 dos_to_unix(command, True); /* Convert printername to unix-codepage */
286 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
289 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
290 ret = smbrun(command, tmp_file, False);
293 return ERROR_INVALID_HANDLE; /* What to return here? */
295 DEBUGADD(10,("returned [%d]\n", ret));
296 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
299 /* Send SIGHUP to process group... is there a better way? */
302 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
304 return ERROR_SUCCESS;
306 return ERROR_ACCESS_DENIED;
309 return ERROR_SUCCESS;
312 /****************************************************************************
313 return the snum of a printer corresponding to an handle
314 ****************************************************************************/
315 static BOOL get_printer_snum(POLICY_HND *hnd, int *number)
317 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
319 if (!OPEN_HANDLE(Printer)) {
320 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
324 switch (Printer->printer_type) {
325 case PRINTER_HANDLE_IS_PRINTER:
326 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
327 *number = print_queue_snum(Printer->dev.handlename);
328 return (*number != -1);
329 case PRINTER_HANDLE_IS_PRINTSERVER:
336 /****************************************************************************
337 set printer handle type.
338 ****************************************************************************/
339 static BOOL set_printer_hnd_accesstype(POLICY_HND *hnd, uint32 access_required)
341 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
343 if (!OPEN_HANDLE(Printer)) {
344 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
348 DEBUG(4,("Setting printer access=%x\n", access_required));
349 Printer->access = access_required;
353 /****************************************************************************
354 Set printer handle type.
355 Check if it's \\server or \\server\printer
356 ****************************************************************************/
358 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
360 DEBUG(3,("Setting printer type=%s\n", handlename));
362 if ( strlen(handlename) < 3 ) {
363 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
367 /* it's a print server */
368 if (!strchr(handlename+2, '\\')) {
369 DEBUGADD(4,("Printer is a print server\n"));
370 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
374 DEBUGADD(4,("Printer is a printer\n"));
375 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
381 /****************************************************************************
382 Set printer handle name.
383 ****************************************************************************/
385 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
387 NT_PRINTER_INFO_LEVEL *printer = NULL;
389 int n_services=lp_numservices();
393 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
395 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
396 ZERO_STRUCT(Printer->dev.printerservername);
397 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
401 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
404 aprinter=strchr(handlename+2, '\\');
407 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
410 * store the Samba share name in it
411 * in back we have the long printer name
412 * need to iterate all the snum and do a
413 * get_a_printer each time to find the printer
414 * faster to do it here than later.
417 for (snum=0;snum<n_services && found==False;snum++) {
420 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
423 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
425 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
428 printername=strchr(printer->info_2->printername+2, '\\');
431 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
432 printer->info_2->printername, aprinter ));
434 if ( strlen(printername) != strlen(aprinter) ) {
435 free_a_printer(&printer, 2);
439 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
440 free_a_printer(&printer, 2);
448 * if we haven't found a printer with the given handlename
449 * then it can be a share name as you can open both \\server\printer and
454 * we still check if the printer description file exists as NT won't be happy
455 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
459 DEBUGADD(5,("Printer not found, checking for share now\n"));
461 for (snum=0;snum<n_services && found==False;snum++) {
463 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
466 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
468 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
471 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
472 printer->info_2->printername, aprinter ));
474 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
475 free_a_printer(&printer, 2);
479 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
480 free_a_printer(&printer, 2);
489 DEBUGADD(4,("Printer not found\n"));
494 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
495 printer->info_2->printername, lp_servicename(snum),snum));
497 ZERO_STRUCT(Printer->dev.handlename);
498 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
500 free_a_printer(&printer, 2);
505 /****************************************************************************
506 find first available printer slot. creates a printer handle for you.
507 ****************************************************************************/
509 static BOOL open_printer_hnd(POLICY_HND *hnd, char *name)
511 Printer_entry *new_printer;
513 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
515 create_printer_hnd(hnd);
517 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
520 ZERO_STRUCTP(new_printer);
522 new_printer->open = True;
523 new_printer->notify.option=NULL;
525 memcpy(&new_printer->printer_hnd, hnd, sizeof(*hnd));
527 ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
529 if (!set_printer_hnd_printertype(new_printer, name)) {
530 close_printer_handle(hnd);
534 if (!set_printer_hnd_name(new_printer, name)) {
535 close_printer_handle(hnd);
539 DEBUG(5, ("%d printer handles active\n",
540 (int)ubi_dlCount(&Printer_list)));
545 /********************************************************************
546 Return True is the handle is a print server.
547 ********************************************************************/
548 static BOOL handle_is_printserver(const POLICY_HND *handle)
550 Printer_entry *Printer=find_printer_index_by_hnd(handle);
552 if (!OPEN_HANDLE(Printer))
555 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
561 /****************************************************************************
562 allocate more memory for a BUFFER.
563 ****************************************************************************/
564 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
572 /* damn, I'm doing the reverse operation of prs_grow() :) */
573 if (buffer_size < prs_data_size(ps))
576 extra_space = buffer_size - prs_data_size(ps);
579 * save the offset and move to the end of the buffer
580 * prs_grow() checks the extra_space against the offset
582 old_offset=prs_offset(ps);
583 prs_set_offset(ps, prs_data_size(ps));
585 if (!prs_grow(ps, extra_space))
588 prs_set_offset(ps, old_offset);
590 buffer->string_at_end=prs_data_size(ps);
595 /***************************************************************************
596 receive the notify message
597 ****************************************************************************/
598 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
602 Printer_entry *find_printer;
605 fstrcpy(printer,buf);
608 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
612 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
614 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
616 /* Iterate the printer list. */
617 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
620 * if the entry is the given printer or if it's a printerserver
621 * we send the message
624 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
625 if (strcmp(find_printer->dev.handlename, printer))
628 if (find_printer->notify.client_connected==True)
629 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
634 /***************************************************************************
636 ****************************************************************************/
637 static BOOL srv_spoolss_sendnotify(POLICY_HND *handle)
641 Printer_entry *Printer=find_printer_index_by_hnd(handle);
643 if (!OPEN_HANDLE(Printer)) {
644 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
648 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
649 fstrcpy(printer, Printer->dev.handlename);
651 fstrcpy(printer, "");
653 /*srv_spoolss_receive_message(printer);*/
654 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
656 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
661 /********************************************************************
662 * spoolss_open_printer
664 * called from the spoolss dispatcher
665 ********************************************************************/
666 uint32 _spoolss_open_printer_ex( const UNISTR2 *printername,
667 const PRINTER_DEFAULT *printer_default,
668 uint32 user_switch, SPOOL_USER_CTR user_ctr,
671 uint32 result = NT_STATUS_NO_PROBLEMO;
672 SEC_DESC_BUF *sec_desc = NULL;
673 uint32 acc_granted, status;
675 extern struct current_user current_user;
677 if (printername == NULL) {
678 result = ERROR_INVALID_PRINTER_NAME;
682 /* some sanity check because you can open a printer or a print server */
683 /* aka: \\server\printer or \\server */
684 unistr2_to_ascii(name, printername, sizeof(name)-1);
686 DEBUGADD(3,("checking name: %s\n",name));
688 if (!open_printer_hnd(handle, name)) {
689 result = ERROR_INVALID_PRINTER_NAME;
694 if (printer_default->datatype_ptr != NULL)
696 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
697 set_printer_hnd_datatype(handle, datatype);
700 set_printer_hnd_datatype(handle, "");
703 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
704 close_printer_handle(handle);
705 result = ERROR_ACCESS_DENIED;
709 /* Disallow MS AddPrinterWizard if parameter disables it. A Win2k
710 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
711 Then both Win2k and WinNT clients try an OpenPrinterEx with
712 SERVER_ALL_ACCESS, which we force to fail. Then they try
713 OpenPrinterEx with SERVER_READ which we allow. This lets the
714 client view printer folder, but does not show the MSAPW.
716 Note: this test needs code to check access rights here too. Jeremy
717 could you look at this? */
719 if (handle_is_printserver(handle) &&
720 !lp_ms_add_printer_wizard()) {
721 if (printer_default->access_required == 0) {
724 else if (printer_default->access_required != (SERVER_READ)) {
725 close_printer_handle(handle);
726 result = ERROR_ACCESS_DENIED;
731 /* NT doesn't let us connect to a printer if the connecting user
732 doesn't have print permission. If no security descriptor just
735 if (!nt_printing_getsec(name, &sec_desc)) {
739 /* Yuck - we should use the pipe_user rather than current_user but
740 it doesn't seem to be filled in correctly. )-: */
742 map_printer_permissions(sec_desc->sec);
744 if (!se_access_check(sec_desc->sec, ¤t_user, PRINTER_ACCESS_USE,
745 &acc_granted, &status)) {
746 DEBUG(3, ("access DENIED for printer open\n"));
747 close_printer_handle(handle);
748 result = ERROR_ACCESS_DENIED;
753 free_sec_desc_buf(&sec_desc);
758 /****************************************************************************
759 ****************************************************************************/
760 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
761 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
765 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
774 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
775 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
779 printer->info_3=NULL;
780 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
783 printer->info_6=NULL;
784 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
793 static BOOL convert_devicemode(const DEVICEMODE *devmode, NT_DEVICEMODE *nt_devmode)
795 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
796 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
798 nt_devmode->specversion=devmode->specversion;
799 nt_devmode->driverversion=devmode->driverversion;
800 nt_devmode->size=devmode->size;
801 nt_devmode->driverextra=devmode->driverextra;
802 nt_devmode->fields=devmode->fields;
803 nt_devmode->orientation=devmode->orientation;
804 nt_devmode->papersize=devmode->papersize;
805 nt_devmode->paperlength=devmode->paperlength;
806 nt_devmode->paperwidth=devmode->paperwidth;
807 nt_devmode->scale=devmode->scale;
808 nt_devmode->copies=devmode->copies;
809 nt_devmode->defaultsource=devmode->defaultsource;
810 nt_devmode->printquality=devmode->printquality;
811 nt_devmode->color=devmode->color;
812 nt_devmode->duplex=devmode->duplex;
813 nt_devmode->yresolution=devmode->yresolution;
814 nt_devmode->ttoption=devmode->ttoption;
815 nt_devmode->collate=devmode->collate;
817 nt_devmode->logpixels=devmode->logpixels;
818 nt_devmode->bitsperpel=devmode->bitsperpel;
819 nt_devmode->pelswidth=devmode->pelswidth;
820 nt_devmode->pelsheight=devmode->pelsheight;
821 nt_devmode->displayflags=devmode->displayflags;
822 nt_devmode->displayfrequency=devmode->displayfrequency;
823 nt_devmode->icmmethod=devmode->icmmethod;
824 nt_devmode->icmintent=devmode->icmintent;
825 nt_devmode->mediatype=devmode->mediatype;
826 nt_devmode->dithertype=devmode->dithertype;
827 nt_devmode->reserved1=devmode->reserved1;
828 nt_devmode->reserved2=devmode->reserved2;
829 nt_devmode->panningwidth=devmode->panningwidth;
830 nt_devmode->panningheight=devmode->panningheight;
832 safe_free(nt_devmode->private);
833 if (nt_devmode->driverextra != 0) {
834 /* if we had a previous private delete it and make a new one */
835 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
837 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
840 nt_devmode->private = NULL;
846 /********************************************************************
847 * api_spoolss_closeprinter
848 ********************************************************************/
849 uint32 _spoolss_closeprinter(POLICY_HND *handle)
851 Printer_entry *Printer=find_printer_index_by_hnd(handle);
853 if (Printer && Printer->document_started)
854 _spoolss_enddocprinter(handle); /* print job was not closed */
856 if (!close_printer_handle(handle))
857 return ERROR_INVALID_HANDLE;
859 return NT_STATUS_NO_PROBLEMO;
862 /********************************************************************
863 * api_spoolss_deleteprinter
864 ********************************************************************/
865 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
867 Printer_entry *Printer=find_printer_index_by_hnd(handle);
870 if (Printer && Printer->document_started)
871 _spoolss_enddocprinter(handle); /* print job was not closed */
873 result = delete_printer_handle(handle);
875 if (result == ERROR_SUCCESS) {
876 srv_spoolss_sendnotify(handle);
882 /********************************************************************
883 GetPrinterData on a printer server Handle.
884 ********************************************************************/
885 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
889 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
891 if (!strcmp(value, "BeepEnabled")) {
893 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
895 SIVAL(*data, 0, 0x01);
900 if (!strcmp(value, "EventLog")) {
902 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
904 SIVAL(*data, 0, 0x1B);
909 if (!strcmp(value, "NetPopup")) {
911 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
913 SIVAL(*data, 0, 0x01);
918 if (!strcmp(value, "MajorVersion")) {
920 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
922 SIVAL(*data, 0, 0x02);
927 if (!strcmp(value, "DefaultSpoolDirectory")) {
928 pstring string="You are using a Samba server";
930 *needed = 2*(strlen(string)+1);
931 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
933 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
935 /* it's done by hand ready to go on the wire */
936 for (i=0; i<strlen(string); i++) {
937 (*data)[2*i]=string[i];
943 if (!strcmp(value, "Architecture")) {
944 pstring string="Windows NT x86";
946 *needed = 2*(strlen(string)+1);
947 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
949 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
950 for (i=0; i<strlen(string); i++) {
951 (*data)[2*i]=string[i];
960 /********************************************************************
961 GetPrinterData on a printer Handle.
962 ********************************************************************/
963 static BOOL getprinterdata_printer(POLICY_HND *handle,
964 fstring value, uint32 *type,
965 uint8 **data, uint32 *needed, uint32 in_size )
967 NT_PRINTER_INFO_LEVEL *printer = NULL;
971 Printer_entry *Printer = find_printer_index_by_hnd(handle);
973 DEBUG(5,("getprinterdata_printer\n"));
975 if (!OPEN_HANDLE(Printer)) {
976 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
980 if(!get_printer_snum(handle, &snum))
983 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
986 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
987 free_a_printer(&printer, 2);
991 free_a_printer(&printer, 2);
993 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
996 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
1000 memset(*data, 0, in_size *sizeof(uint8));
1001 /* copy the min(in_size, len) */
1002 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1009 DEBUG(5,("getprinterdata_printer:copy done\n"));
1016 /********************************************************************
1017 * spoolss_getprinterdata
1018 ********************************************************************/
1019 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
1028 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1031 * Reminder: when it's a string, the length is in BYTES
1032 * even if UNICODE is negociated.
1039 /* in case of problem, return some default values */
1043 DEBUG(4,("_spoolss_getprinterdata\n"));
1045 if (!OPEN_HANDLE(Printer)) {
1046 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1047 return ERROR_NOT_ENOUGH_MEMORY;
1048 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1049 return ERROR_INVALID_HANDLE;
1052 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1054 if (handle_is_printserver(handle))
1055 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1057 found=getprinterdata_printer(handle, value, type, data, needed, *out_size);
1060 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1061 /* reply this param doesn't exist */
1063 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
1064 return ERROR_NOT_ENOUGH_MEMORY;
1065 memset(*data, '\0', *out_size*sizeof(uint8));
1070 return ERROR_INVALID_PARAMETER;
1073 if (*needed > *out_size)
1074 return ERROR_MORE_DATA;
1076 return NT_STATUS_NO_PROBLEMO;
1079 /***************************************************************************
1080 connect to the client
1081 ****************************************************************************/
1082 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1087 * If it's the first connection, contact the client
1088 * and connect to the IPC$ share anonumously
1090 if (smb_connections==0) {
1091 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1093 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1099 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1105 /********************************************************************
1107 * ReplyFindFirstPrinterChangeNotifyEx
1109 * jfmxxxx: before replying OK: status=0
1110 * should do a rpc call to the workstation asking ReplyOpenPrinter
1111 * have to code it, later.
1113 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1114 * called from api_spoolss_rffpcnex
1115 ********************************************************************/
1116 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1117 const UNISTR2 *localmachine, uint32 printerlocal,
1118 SPOOL_NOTIFY_OPTION *option)
1120 /* store the notify value in the printer struct */
1122 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1124 if (!OPEN_HANDLE(Printer)) {
1125 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1126 return ERROR_INVALID_HANDLE;
1129 Printer->notify.flags=flags;
1130 Printer->notify.options=options;
1131 Printer->notify.printerlocal=printerlocal;
1132 Printer->notify.option=option;
1133 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1135 /* connect to the client machine and send a ReplyOpenPrinter */
1136 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1137 Printer->notify.printerlocal, 1,
1138 &Printer->notify.client_hnd))
1139 Printer->notify.client_connected=True;
1141 return NT_STATUS_NO_PROBLEMO;
1144 /*******************************************************************
1145 * fill a notify_info_data with the servername
1146 ********************************************************************/
1147 static void spoolss_notify_server_name(int snum,
1148 SPOOL_NOTIFY_INFO_DATA *data,
1149 print_queue_struct *queue,
1150 NT_PRINTER_INFO_LEVEL *printer,
1151 TALLOC_CTX *mem_ctx)
1153 pstring temp_name, temp;
1156 snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1158 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1160 data->notify_data.data.length = len / 2 - 1;
1161 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1163 if (!data->notify_data.data.string) {
1164 data->notify_data.data.length = 0;
1168 memcpy(data->notify_data.data.string, temp, len);
1171 /*******************************************************************
1172 * fill a notify_info_data with the printername (not including the servername).
1173 ********************************************************************/
1174 static void spoolss_notify_printer_name(int snum,
1175 SPOOL_NOTIFY_INFO_DATA *data,
1176 print_queue_struct *queue,
1177 NT_PRINTER_INFO_LEVEL *printer,
1178 TALLOC_CTX *mem_ctx)
1183 /* the notify name should not contain the \\server\ part */
1184 char *p = strrchr(printer->info_2->printername, '\\');
1187 p = printer->info_2->printername;
1192 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1194 data->notify_data.data.length = len / 2 - 1;
1195 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1197 if (!data->notify_data.data.string) {
1198 data->notify_data.data.length = 0;
1202 memcpy(data->notify_data.data.string, temp, len);
1205 /*******************************************************************
1206 * fill a notify_info_data with the servicename
1207 ********************************************************************/
1208 static void spoolss_notify_share_name(int snum,
1209 SPOOL_NOTIFY_INFO_DATA *data,
1210 print_queue_struct *queue,
1211 NT_PRINTER_INFO_LEVEL *printer,
1212 TALLOC_CTX *mem_ctx)
1217 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1218 sizeof(temp) - 2, True);
1220 data->notify_data.data.length = len / 2 - 1;
1221 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1223 if (!data->notify_data.data.string) {
1224 data->notify_data.data.length = 0;
1228 memcpy(data->notify_data.data.string, temp, len);
1231 /*******************************************************************
1232 * fill a notify_info_data with the port name
1233 ********************************************************************/
1234 static void spoolss_notify_port_name(int snum,
1235 SPOOL_NOTIFY_INFO_DATA *data,
1236 print_queue_struct *queue,
1237 NT_PRINTER_INFO_LEVEL *printer,
1238 TALLOC_CTX *mem_ctx)
1243 /* even if it's strange, that's consistant in all the code */
1245 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1246 sizeof(temp) - 2, True);
1248 data->notify_data.data.length = len / 2 - 1;
1249 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1251 if (!data->notify_data.data.string) {
1252 data->notify_data.data.length = 0;
1256 memcpy(data->notify_data.data.string, temp, len);
1259 /*******************************************************************
1260 * fill a notify_info_data with the printername
1261 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1262 * but it doesn't exist, have to see what to do
1263 ********************************************************************/
1264 static void spoolss_notify_driver_name(int snum,
1265 SPOOL_NOTIFY_INFO_DATA *data,
1266 print_queue_struct *queue,
1267 NT_PRINTER_INFO_LEVEL *printer,
1268 TALLOC_CTX *mem_ctx)
1273 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1274 sizeof(temp) - 2, True);
1276 data->notify_data.data.length = len / 2 - 1;
1277 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1279 if (!data->notify_data.data.string) {
1280 data->notify_data.data.length = 0;
1284 memcpy(data->notify_data.data.string, temp, len);
1287 /*******************************************************************
1288 * fill a notify_info_data with the comment
1289 ********************************************************************/
1290 static void spoolss_notify_comment(int snum,
1291 SPOOL_NOTIFY_INFO_DATA *data,
1292 print_queue_struct *queue,
1293 NT_PRINTER_INFO_LEVEL *printer,
1294 TALLOC_CTX *mem_ctx)
1299 if (*printer->info_2->comment == '\0')
1300 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1301 sizeof(temp) - 2, True);
1303 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1304 sizeof(temp) - 2, True);
1306 data->notify_data.data.length = len / 2 - 1;
1307 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1309 if (!data->notify_data.data.string) {
1310 data->notify_data.data.length = 0;
1314 memcpy(data->notify_data.data.string, temp, len);
1317 /*******************************************************************
1318 * fill a notify_info_data with the comment
1319 * jfm:xxxx incorrect, have to create a new smb.conf option
1320 * location = "Room 1, floor 2, building 3"
1321 ********************************************************************/
1322 static void spoolss_notify_location(int snum,
1323 SPOOL_NOTIFY_INFO_DATA *data,
1324 print_queue_struct *queue,
1325 NT_PRINTER_INFO_LEVEL *printer,
1326 TALLOC_CTX *mem_ctx)
1331 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1332 sizeof(temp) - 2, True);
1334 data->notify_data.data.length = len / 2 - 1;
1335 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1337 if (!data->notify_data.data.string) {
1338 data->notify_data.data.length = 0;
1342 memcpy(data->notify_data.data.string, temp, len);
1345 /*******************************************************************
1346 * fill a notify_info_data with the device mode
1347 * jfm:xxxx don't to it for know but that's a real problem !!!
1348 ********************************************************************/
1349 static void spoolss_notify_devmode(int snum,
1350 SPOOL_NOTIFY_INFO_DATA *data,
1351 print_queue_struct *queue,
1352 NT_PRINTER_INFO_LEVEL *printer,
1353 TALLOC_CTX *mem_ctx)
1357 /*******************************************************************
1358 * fill a notify_info_data with the separator file name
1359 * jfm:xxxx just return no file could add an option to smb.conf
1360 * separator file = "separator.txt"
1361 ********************************************************************/
1362 static void spoolss_notify_sepfile(int snum,
1363 SPOOL_NOTIFY_INFO_DATA *data,
1364 print_queue_struct *queue,
1365 NT_PRINTER_INFO_LEVEL *printer,
1366 TALLOC_CTX *mem_ctx)
1371 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1372 sizeof(temp) - 2, True);
1374 data->notify_data.data.length = len / 2 - 1;
1375 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1377 if (!data->notify_data.data.string) {
1378 data->notify_data.data.length = 0;
1382 memcpy(data->notify_data.data.string, temp, len);
1385 /*******************************************************************
1386 * fill a notify_info_data with the print processor
1387 * jfm:xxxx return always winprint to indicate we don't do anything to it
1388 ********************************************************************/
1389 static void spoolss_notify_print_processor(int snum,
1390 SPOOL_NOTIFY_INFO_DATA *data,
1391 print_queue_struct *queue,
1392 NT_PRINTER_INFO_LEVEL *printer,
1393 TALLOC_CTX *mem_ctx)
1398 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
1399 sizeof(temp) - 2, True);
1401 data->notify_data.data.length = len / 2 - 1;
1402 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1404 if (!data->notify_data.data.string) {
1405 data->notify_data.data.length = 0;
1409 memcpy(data->notify_data.data.string, temp, len);
1412 /*******************************************************************
1413 * fill a notify_info_data with the print processor options
1414 * jfm:xxxx send an empty string
1415 ********************************************************************/
1416 static void spoolss_notify_parameters(int snum,
1417 SPOOL_NOTIFY_INFO_DATA *data,
1418 print_queue_struct *queue,
1419 NT_PRINTER_INFO_LEVEL *printer,
1420 TALLOC_CTX *mem_ctx)
1425 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1426 sizeof(temp) - 2, True);
1428 data->notify_data.data.length = len / 2 - 1;
1429 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1431 if (!data->notify_data.data.string) {
1432 data->notify_data.data.length = 0;
1436 memcpy(data->notify_data.data.string, temp, len);
1439 /*******************************************************************
1440 * fill a notify_info_data with the data type
1441 * jfm:xxxx always send RAW as data type
1442 ********************************************************************/
1443 static void spoolss_notify_datatype(int snum,
1444 SPOOL_NOTIFY_INFO_DATA *data,
1445 print_queue_struct *queue,
1446 NT_PRINTER_INFO_LEVEL *printer,
1447 TALLOC_CTX *mem_ctx)
1452 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1453 sizeof(pstring) - 2, True);
1455 data->notify_data.data.length = len / 2 - 1;
1456 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1458 if (!data->notify_data.data.string) {
1459 data->notify_data.data.length = 0;
1463 memcpy(data->notify_data.data.string, temp, len);
1466 /*******************************************************************
1467 * fill a notify_info_data with the security descriptor
1468 * jfm:xxxx send an null pointer to say no security desc
1469 * have to implement security before !
1470 ********************************************************************/
1471 static void spoolss_notify_security_desc(int snum,
1472 SPOOL_NOTIFY_INFO_DATA *data,
1473 print_queue_struct *queue,
1474 NT_PRINTER_INFO_LEVEL *printer,
1475 TALLOC_CTX *mem_ctx)
1477 data->notify_data.data.length=0;
1478 data->notify_data.data.string = NULL;
1481 /*******************************************************************
1482 * fill a notify_info_data with the attributes
1483 * jfm:xxxx a samba printer is always shared
1484 ********************************************************************/
1485 static void spoolss_notify_attributes(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->attributes;
1494 /*******************************************************************
1495 * fill a notify_info_data with the priority
1496 ********************************************************************/
1497 static void spoolss_notify_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->priority;
1506 /*******************************************************************
1507 * fill a notify_info_data with the default priority
1508 ********************************************************************/
1509 static void spoolss_notify_default_priority(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->default_priority;
1518 /*******************************************************************
1519 * fill a notify_info_data with the start time
1520 ********************************************************************/
1521 static void spoolss_notify_start_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->starttime;
1530 /*******************************************************************
1531 * fill a notify_info_data with the until time
1532 ********************************************************************/
1533 static void spoolss_notify_until_time(int snum,
1534 SPOOL_NOTIFY_INFO_DATA *data,
1535 print_queue_struct *queue,
1536 NT_PRINTER_INFO_LEVEL *printer,
1537 TALLOC_CTX *mem_ctx)
1539 data->notify_data.value[0] = printer->info_2->untiltime;
1542 /*******************************************************************
1543 * fill a notify_info_data with the status
1544 ********************************************************************/
1545 static void spoolss_notify_status(int snum,
1546 SPOOL_NOTIFY_INFO_DATA *data,
1547 print_queue_struct *queue,
1548 NT_PRINTER_INFO_LEVEL *printer,
1549 TALLOC_CTX *mem_ctx)
1553 print_queue_struct *q=NULL;
1554 print_status_struct status;
1556 memset(&status, 0, sizeof(status));
1557 count = print_queue_status(snum, &q, &status);
1558 data->notify_data.value[0]=(uint32) status.status;
1562 /*******************************************************************
1563 * fill a notify_info_data with the number of jobs queued
1564 ********************************************************************/
1565 static void spoolss_notify_cjobs(int snum,
1566 SPOOL_NOTIFY_INFO_DATA *data,
1567 print_queue_struct *queue,
1568 NT_PRINTER_INFO_LEVEL *printer,
1569 TALLOC_CTX *mem_ctx)
1571 print_queue_struct *q=NULL;
1572 print_status_struct status;
1574 memset(&status, 0, sizeof(status));
1575 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1579 /*******************************************************************
1580 * fill a notify_info_data with the average ppm
1581 ********************************************************************/
1582 static void spoolss_notify_average_ppm(int snum,
1583 SPOOL_NOTIFY_INFO_DATA *data,
1584 print_queue_struct *queue,
1585 NT_PRINTER_INFO_LEVEL *printer,
1586 TALLOC_CTX *mem_ctx)
1588 /* always respond 8 pages per minutes */
1589 /* a little hard ! */
1590 data->notify_data.value[0] = printer->info_2->averageppm;
1593 /*******************************************************************
1594 * fill a notify_info_data with username
1595 ********************************************************************/
1596 static void spoolss_notify_username(int snum,
1597 SPOOL_NOTIFY_INFO_DATA *data,
1598 print_queue_struct *queue,
1599 NT_PRINTER_INFO_LEVEL *printer,
1600 TALLOC_CTX *mem_ctx)
1605 len = (uint32)dos_PutUniCode(temp, queue->user,
1606 sizeof(temp) - 2, True);
1608 data->notify_data.data.length = len / 2 - 1;
1609 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1611 if (!data->notify_data.data.string) {
1612 data->notify_data.data.length = 0;
1616 memcpy(data->notify_data.data.string, temp, len);
1619 /*******************************************************************
1620 * fill a notify_info_data with job status
1621 ********************************************************************/
1622 static void spoolss_notify_job_status(int snum,
1623 SPOOL_NOTIFY_INFO_DATA *data,
1624 print_queue_struct *queue,
1625 NT_PRINTER_INFO_LEVEL *printer,
1626 TALLOC_CTX *mem_ctx)
1628 data->notify_data.value[0]=nt_printj_status(queue->status);
1631 /*******************************************************************
1632 * fill a notify_info_data with job name
1633 ********************************************************************/
1634 static void spoolss_notify_job_name(int snum,
1635 SPOOL_NOTIFY_INFO_DATA *data,
1636 print_queue_struct *queue,
1637 NT_PRINTER_INFO_LEVEL *printer,
1638 TALLOC_CTX *mem_ctx)
1643 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1646 data->notify_data.data.length = len / 2 - 1;
1647 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1649 if (!data->notify_data.data.string) {
1650 data->notify_data.data.length = 0;
1654 memcpy(data->notify_data.data.string, temp, len);
1657 /*******************************************************************
1658 * fill a notify_info_data with job status
1659 ********************************************************************/
1660 static void spoolss_notify_job_status_string(int snum,
1661 SPOOL_NOTIFY_INFO_DATA *data,
1662 print_queue_struct *queue,
1663 NT_PRINTER_INFO_LEVEL *printer,
1664 TALLOC_CTX *mem_ctx)
1666 char *p = "unknown";
1670 switch (queue->status) {
1675 p = ""; /* NT provides the paused string */
1685 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1687 data->notify_data.data.length = len / 2 - 1;
1688 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1690 if (!data->notify_data.data.string) {
1691 data->notify_data.data.length = 0;
1695 memcpy(data->notify_data.data.string, temp, len);
1698 /*******************************************************************
1699 * fill a notify_info_data with job time
1700 ********************************************************************/
1701 static void spoolss_notify_job_time(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]=0x0;
1710 /*******************************************************************
1711 * fill a notify_info_data with job size
1712 ********************************************************************/
1713 static void spoolss_notify_job_size(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->size;
1722 /*******************************************************************
1723 * fill a notify_info_data with job position
1724 ********************************************************************/
1725 static void spoolss_notify_job_position(int snum,
1726 SPOOL_NOTIFY_INFO_DATA *data,
1727 print_queue_struct *queue,
1728 NT_PRINTER_INFO_LEVEL *printer,
1729 TALLOC_CTX *mem_ctx)
1731 data->notify_data.value[0]=queue->job;
1734 /*******************************************************************
1735 * fill a notify_info_data with submitted time
1736 ********************************************************************/
1737 static void spoolss_notify_submitted_time(int snum,
1738 SPOOL_NOTIFY_INFO_DATA *data,
1739 print_queue_struct *queue,
1740 NT_PRINTER_INFO_LEVEL *printer,
1741 TALLOC_CTX *mem_ctx)
1746 t=gmtime(&queue->time);
1748 len = sizeof(SYSTEMTIME);
1750 data->notify_data.data.length = len;
1751 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1753 if (!data->notify_data.data.string) {
1754 data->notify_data.data.length = 0;
1758 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1763 struct s_notify_info_data_table
1769 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1770 print_queue_struct *queue,
1771 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
1774 struct s_notify_info_data_table notify_info_data_table[] =
1776 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1777 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1778 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1779 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1780 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1781 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1782 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1783 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1784 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1785 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1786 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1787 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1788 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1789 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1790 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1791 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1792 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1793 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1794 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1795 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1796 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1797 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1798 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1799 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1800 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1801 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1802 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1803 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1804 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1805 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1806 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1807 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1808 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1809 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1810 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1811 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1812 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1813 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1814 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1815 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1816 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1817 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1818 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1819 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1820 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1821 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1822 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1823 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1824 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1825 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1826 { END, END, "", END, NULL }
1829 /*******************************************************************
1830 return the size of info_data structure
1831 ********************************************************************/
1832 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1836 while (notify_info_data_table[i].type != END)
1838 if ( (notify_info_data_table[i].type == type ) &&
1839 (notify_info_data_table[i].field == field ) )
1841 return (notify_info_data_table[i].size);
1848 /*******************************************************************
1849 return the type of notify_info_data
1850 ********************************************************************/
1851 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1855 while (notify_info_data_table[i].type != END)
1857 if ( (notify_info_data_table[i].type == type ) &&
1858 (notify_info_data_table[i].field == field ) )
1860 if (notify_info_data_table[i].size == POINTER)
1874 /****************************************************************************
1875 ****************************************************************************/
1876 static int search_notify(uint16 type, uint16 field, int *value)
1881 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1883 if ( (notify_info_data_table[j].type == type ) &&
1884 (notify_info_data_table[j].field == field ) )
1889 if ( found && (notify_info_data_table[j].fn != NULL) )
1895 /****************************************************************************
1896 ****************************************************************************/
1897 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1899 info_data->type = type;
1900 info_data->field = field;
1901 info_data->reserved = 0;
1903 info_data->size = size_of_notify_info_data(type, field);
1904 info_data->enc_type = type_of_notify_info_data(type, field);
1908 /*******************************************************************
1910 * fill a notify_info struct with info asked
1912 ********************************************************************/
1913 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
1914 snum, SPOOL_NOTIFY_OPTION_TYPE
1915 *option_type, uint32 id,
1916 TALLOC_CTX *mem_ctx)
1922 SPOOL_NOTIFY_INFO_DATA *current_data;
1923 NT_PRINTER_INFO_LEVEL *printer = NULL;
1924 print_queue_struct *queue=NULL;
1926 type=option_type->type;
1928 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1929 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1930 option_type->count, lp_servicename(snum)));
1932 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1935 for(field_num=0; field_num<option_type->count; field_num++) {
1936 field = option_type->fields[field_num];
1937 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1939 if (!search_notify(type, field, &j) )
1942 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1945 current_data=&info->data[info->count];
1947 construct_info_data(current_data, type, field, id);
1949 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
1950 notify_info_data_table[j].name, snum, printer->info_2->printername ));
1952 notify_info_data_table[j].fn(snum, current_data, queue,
1958 free_a_printer(&printer, 2);
1962 /*******************************************************************
1964 * fill a notify_info struct with info asked
1966 ********************************************************************/
1967 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
1968 SPOOL_NOTIFY_INFO *info,
1969 NT_PRINTER_INFO_LEVEL *printer,
1970 int snum, SPOOL_NOTIFY_OPTION_TYPE
1971 *option_type, uint32 id,
1972 TALLOC_CTX *mem_ctx)
1978 SPOOL_NOTIFY_INFO_DATA *current_data;
1980 DEBUG(4,("construct_notify_jobs_info\n"));
1982 type = option_type->type;
1984 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1985 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1986 option_type->count));
1988 for(field_num=0; field_num<option_type->count; field_num++) {
1989 field = option_type->fields[field_num];
1991 if (!search_notify(type, field, &j) )
1994 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1998 current_data=&(info->data[info->count]);
2000 construct_info_data(current_data, type, field, id);
2001 notify_info_data_table[j].fn(snum, current_data, queue,
2010 * JFM: The enumeration is not that simple, it's even non obvious.
2012 * let's take an example: I want to monitor the PRINTER SERVER for
2013 * the printer's name and the number of jobs currently queued.
2014 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2015 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2017 * I have 3 printers on the back of my server.
2019 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2022 * 1 printer 1 name 1
2023 * 2 printer 1 cjob 1
2024 * 3 printer 2 name 2
2025 * 4 printer 2 cjob 2
2026 * 5 printer 3 name 3
2027 * 6 printer 3 name 3
2029 * that's the print server case, the printer case is even worse.
2034 /*******************************************************************
2036 * enumerate all printers on the printserver
2037 * fill a notify_info struct with info asked
2039 ********************************************************************/
2040 static uint32 printserver_notify_info(const POLICY_HND *hnd,
2041 SPOOL_NOTIFY_INFO *info,
2042 TALLOC_CTX *mem_ctx)
2045 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2046 int n_services=lp_numservices();
2049 SPOOL_NOTIFY_OPTION *option;
2050 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2052 DEBUG(4,("printserver_notify_info\n"));
2054 option=Printer->notify.option;
2060 for (i=0; i<option->count; i++) {
2061 option_type=&(option->ctr.type[i]);
2063 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2066 for (snum=0; snum<n_services; snum++)
2067 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2068 if (construct_notify_printer_info
2069 (info, snum, option_type, id, mem_ctx))
2074 * Debugging information, don't delete.
2077 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2078 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2079 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2081 for (i=0; i<info->count; i++) {
2082 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2083 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2084 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2088 return NT_STATUS_NO_PROBLEMO;
2091 /*******************************************************************
2093 * fill a notify_info struct with info asked
2095 ********************************************************************/
2096 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2097 TALLOC_CTX *mem_ctx)
2100 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2103 SPOOL_NOTIFY_OPTION *option;
2104 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2106 print_queue_struct *queue=NULL;
2107 print_status_struct status;
2109 DEBUG(4,("printer_notify_info\n"));
2111 option=Printer->notify.option;
2117 get_printer_snum(hnd, &snum);
2119 for (i=0; i<option->count; i++) {
2120 option_type=&option->ctr.type[i];
2122 switch ( option_type->type ) {
2123 case PRINTER_NOTIFY_TYPE:
2124 if(construct_notify_printer_info(info, snum,
2130 case JOB_NOTIFY_TYPE: {
2131 NT_PRINTER_INFO_LEVEL *printer = NULL;
2133 memset(&status, 0, sizeof(status));
2134 count = print_queue_status(snum, &queue, &status);
2136 if (get_a_printer(&printer, 2,
2137 lp_servicename(snum)) != 0)
2140 for (j=0; j<count; j++) {
2141 construct_notify_jobs_info(&queue[j], info,
2148 free_a_printer(&printer, 2);
2158 * Debugging information, don't delete.
2161 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2162 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2163 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2165 for (i=0; i<info->count; i++) {
2166 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2167 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2168 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2171 return NT_STATUS_NO_PROBLEMO;
2174 /********************************************************************
2176 ********************************************************************/
2177 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
2178 SPOOL_NOTIFY_OPTION *option, TALLOC_CTX *mem_ctx,
2179 SPOOL_NOTIFY_INFO *info)
2181 Printer_entry *Printer=find_printer_index_by_hnd(handle);
2182 uint32 result = ERROR_INVALID_HANDLE;
2184 if (!OPEN_HANDLE(Printer)) {
2185 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2186 OUR_HANDLE(handle)));
2190 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2192 /* jfm: the change value isn't used right now.
2193 * we will honour it when
2194 * a) we'll be able to send notification to the client
2195 * b) we'll have a way to communicate between the spoolss process.
2197 * same thing for option->flags
2198 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2199 * I don't have a global notification system, I'm sending back all the
2200 * informations even when _NOTHING_ has changed.
2203 /* just discard the SPOOL_NOTIFY_OPTION */
2205 safe_free(option->ctr.type);
2207 switch (Printer->printer_type) {
2208 case PRINTER_HANDLE_IS_PRINTSERVER:
2209 result = printserver_notify_info(handle, info,
2213 case PRINTER_HANDLE_IS_PRINTER:
2214 result = printer_notify_info(handle, info, mem_ctx);
2222 /********************************************************************
2223 * construct_printer_info_0
2224 * fill a printer_info_0 struct
2225 ********************************************************************/
2226 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2230 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2231 counter_printer_0 *session_counter;
2232 uint32 global_counter;
2236 print_queue_struct *queue=NULL;
2237 print_status_struct status;
2239 memset(&status, 0, sizeof(status));
2241 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2244 count = print_queue_status(snum, &queue, &status);
2246 /* check if we already have a counter for this printer */
2247 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2249 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2250 if (session_counter->snum == snum)
2254 /* it's the first time, add it to the list */
2255 if (session_counter==NULL) {
2256 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2257 free_a_printer(&ntprinter, 2);
2260 ZERO_STRUCTP(session_counter);
2261 session_counter->snum=snum;
2262 session_counter->counter=0;
2263 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2267 session_counter->counter++;
2270 * the global_counter should be stored in a TDB as it's common to all the clients
2271 * and should be zeroed on samba startup
2273 global_counter=session_counter->counter;
2275 pstrcpy(chaine,ntprinter->info_2->printername);
2277 init_unistr(&printer->printername, chaine);
2279 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2280 init_unistr(&printer->servername, chaine);
2282 printer->cjobs = count;
2283 printer->total_jobs = 0;
2284 printer->total_bytes = 0;
2286 setuptime = (time_t)ntprinter->info_2->setuptime;
2287 t=gmtime(&setuptime);
2289 printer->year = t->tm_year+1900;
2290 printer->month = t->tm_mon+1;
2291 printer->dayofweek = t->tm_wday;
2292 printer->day = t->tm_mday;
2293 printer->hour = t->tm_hour;
2294 printer->minute = t->tm_min;
2295 printer->second = t->tm_sec;
2296 printer->milliseconds = 0;
2298 printer->global_counter = global_counter;
2299 printer->total_pages = 0;
2300 printer->major_version = 0x0004; /* NT 4 */
2301 printer->build_version = 0x0565; /* build 1381 */
2302 printer->unknown7 = 0x1;
2303 printer->unknown8 = 0x0;
2304 printer->unknown9 = 0x0;
2305 printer->session_counter = session_counter->counter;
2306 printer->unknown11 = 0x0;
2307 printer->printer_errors = 0x0; /* number of print failure */
2308 printer->unknown13 = 0x0;
2309 printer->unknown14 = 0x1;
2310 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2311 printer->unknown16 = 0x0;
2312 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2313 printer->unknown18 = 0x0;
2314 printer->status = nt_printq_status(status.status);
2315 printer->unknown20 = 0x0;
2316 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2317 printer->unknown22 = 0x0;
2318 printer->unknown23 = 0x6; /* 6 ???*/
2319 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2320 printer->unknown25 = 0;
2321 printer->unknown26 = 0;
2322 printer->unknown27 = 0;
2323 printer->unknown28 = 0;
2324 printer->unknown29 = 0;
2327 free_a_printer(&ntprinter,2);
2331 /********************************************************************
2332 * construct_printer_info_1
2333 * fill a printer_info_1 struct
2334 ********************************************************************/
2335 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2339 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2341 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2344 printer->flags=flags;
2346 if (*ntprinter->info_2->comment == '\0') {
2347 init_unistr(&printer->comment, lp_comment(snum));
2348 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2349 ntprinter->info_2->drivername, lp_comment(snum));
2352 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2353 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2354 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2357 snprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2359 init_unistr(&printer->description, chaine);
2360 init_unistr(&printer->name, chaine2);
2362 free_a_printer(&ntprinter,2);
2367 /****************************************************************************
2368 Free a DEVMODE struct.
2369 ****************************************************************************/
2371 static void free_dev_mode(DEVICEMODE *dev)
2377 safe_free(dev->private);
2382 /****************************************************************************
2383 Create a DEVMODE struct. Returns malloced memory.
2384 ****************************************************************************/
2386 static DEVICEMODE *construct_dev_mode(int snum)
2390 NT_PRINTER_INFO_LEVEL *printer = NULL;
2391 NT_DEVICEMODE *ntdevmode = NULL;
2392 DEVICEMODE *devmode = NULL;
2394 DEBUG(7,("construct_dev_mode\n"));
2396 DEBUGADD(8,("getting printer characteristics\n"));
2398 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2399 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2403 ZERO_STRUCTP(devmode);
2405 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2408 if (printer->info_2->devmode)
2409 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2411 if (ntdevmode == NULL)
2414 DEBUGADD(8,("loading DEVICEMODE\n"));
2416 snprintf(adevice, sizeof(adevice), printer->info_2->printername);
2417 init_unistr(&devmode->devicename, adevice);
2419 snprintf(aform, sizeof(aform), ntdevmode->formname);
2420 init_unistr(&devmode->formname, aform);
2422 devmode->specversion = ntdevmode->specversion;
2423 devmode->driverversion = ntdevmode->driverversion;
2424 devmode->size = ntdevmode->size;
2425 devmode->driverextra = ntdevmode->driverextra;
2426 devmode->fields = ntdevmode->fields;
2428 devmode->orientation = ntdevmode->orientation;
2429 devmode->papersize = ntdevmode->papersize;
2430 devmode->paperlength = ntdevmode->paperlength;
2431 devmode->paperwidth = ntdevmode->paperwidth;
2432 devmode->scale = ntdevmode->scale;
2433 devmode->copies = ntdevmode->copies;
2434 devmode->defaultsource = ntdevmode->defaultsource;
2435 devmode->printquality = ntdevmode->printquality;
2436 devmode->color = ntdevmode->color;
2437 devmode->duplex = ntdevmode->duplex;
2438 devmode->yresolution = ntdevmode->yresolution;
2439 devmode->ttoption = ntdevmode->ttoption;
2440 devmode->collate = ntdevmode->collate;
2441 devmode->icmmethod = ntdevmode->icmmethod;
2442 devmode->icmintent = ntdevmode->icmintent;
2443 devmode->mediatype = ntdevmode->mediatype;
2444 devmode->dithertype = ntdevmode->dithertype;
2446 if (ntdevmode->private != NULL) {
2447 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2451 free_nt_devicemode(&ntdevmode);
2452 free_a_printer(&printer,2);
2459 free_nt_devicemode(&ntdevmode);
2461 free_a_printer(&printer,2);
2462 free_dev_mode(devmode);
2467 /********************************************************************
2468 * construct_printer_info_2
2469 * fill a printer_info_2 struct
2470 ********************************************************************/
2472 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2475 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2477 print_queue_struct *queue=NULL;
2478 print_status_struct status;
2479 memset(&status, 0, sizeof(status));
2481 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2484 memset(&status, 0, sizeof(status));
2485 count = print_queue_status(snum, &queue, &status);
2487 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2488 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2489 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2490 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2491 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2493 if (*ntprinter->info_2->comment == '\0')
2494 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2496 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2498 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2499 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2500 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2501 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2502 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2504 printer->attributes = ntprinter->info_2->attributes;
2506 printer->priority = ntprinter->info_2->priority; /* priority */
2507 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2508 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2509 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2510 printer->status = nt_printq_status(status.status); /* status */
2511 printer->cjobs = count; /* jobs */
2512 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2514 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2515 DEBUG(8, ("Returning NULL Devicemode!\n"));
2518 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2519 /* steal the printer info sec_desc structure. [badly done]. */
2520 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2521 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2522 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2523 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2526 printer->secdesc = NULL;
2529 free_a_printer(&ntprinter, 2);
2534 /********************************************************************
2535 * construct_printer_info_3
2536 * fill a printer_info_3 struct
2537 ********************************************************************/
2538 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2540 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2541 PRINTER_INFO_3 *printer = NULL;
2543 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2547 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2548 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2552 ZERO_STRUCTP(printer);
2554 printer->flags = 4; /* These are the components of the SD we are returning. */
2555 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2556 /* steal the printer info sec_desc structure. [badly done]. */
2557 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2561 * Set the flags for the components we are returning.
2564 if (printer->secdesc->owner_sid)
2565 printer->flags |= OWNER_SECURITY_INFORMATION;
2567 if (printer->secdesc->grp_sid)
2568 printer->flags |= GROUP_SECURITY_INFORMATION;
2570 if (printer->secdesc->dacl)
2571 printer->flags |= DACL_SECURITY_INFORMATION;
2573 if (printer->secdesc->sacl)
2574 printer->flags |= SACL_SECURITY_INFORMATION;
2577 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2578 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2579 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2582 free_a_printer(&ntprinter, 2);
2584 *pp_printer = printer;
2588 /********************************************************************
2589 Spoolss_enumprinters.
2590 ********************************************************************/
2591 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2595 int n_services=lp_numservices();
2596 PRINTER_INFO_1 *printers=NULL;
2597 PRINTER_INFO_1 current_prt;
2599 DEBUG(4,("enum_all_printers_info_1\n"));
2601 for (snum=0; snum<n_services; snum++) {
2602 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2603 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2605 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2606 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2608 return ERROR_NOT_ENOUGH_MEMORY;
2610 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2611 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2617 /* check the required size. */
2618 for (i=0; i<*returned; i++)
2619 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2621 if (!alloc_buffer_size(buffer, *needed))
2622 return ERROR_INSUFFICIENT_BUFFER;
2624 /* fill the buffer with the structures */
2625 for (i=0; i<*returned; i++)
2626 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2629 safe_free(printers);
2631 if (*needed > offered) {
2633 return ERROR_INSUFFICIENT_BUFFER;
2636 return NT_STATUS_NO_PROBLEMO;
2639 /********************************************************************
2640 enum_all_printers_info_1_local.
2641 *********************************************************************/
2642 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2644 DEBUG(4,("enum_all_printers_info_1_local\n"));
2646 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2649 /********************************************************************
2650 enum_all_printers_info_1_name.
2651 *********************************************************************/
2652 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2655 DEBUG(4,("enum_all_printers_info_1_name\n"));
2657 fstrcpy(temp, "\\\\");
2658 fstrcat(temp, global_myname);
2660 if (strequal(name, temp)) {
2661 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2664 return ERROR_INVALID_NAME;
2667 /********************************************************************
2668 enum_all_printers_info_1_remote.
2669 *********************************************************************/
2670 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2672 PRINTER_INFO_1 *printer;
2673 fstring printername;
2676 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2678 /* JFM: currently it's more a place holder than anything else.
2679 * In the spooler world there is a notion of server registration.
2680 * the print servers are registring (sp ?) on the PDC (in the same domain)
2682 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2685 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2686 return ERROR_NOT_ENOUGH_MEMORY;
2690 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2691 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2692 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2694 init_unistr(&printer->description, desc);
2695 init_unistr(&printer->name, printername);
2696 init_unistr(&printer->comment, comment);
2697 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2699 /* check the required size. */
2700 *needed += spoolss_size_printer_info_1(printer);
2702 if (!alloc_buffer_size(buffer, *needed)) {
2704 return ERROR_INSUFFICIENT_BUFFER;
2707 /* fill the buffer with the structures */
2708 new_smb_io_printer_info_1("", buffer, printer, 0);
2713 if (*needed > offered) {
2715 return ERROR_INSUFFICIENT_BUFFER;
2718 return NT_STATUS_NO_PROBLEMO;
2721 /********************************************************************
2722 enum_all_printers_info_1_network.
2723 *********************************************************************/
2724 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2726 DEBUG(4,("enum_all_printers_info_1_network\n"));
2728 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2731 /********************************************************************
2732 * api_spoolss_enumprinters
2734 * called from api_spoolss_enumprinters (see this to understand)
2735 ********************************************************************/
2736 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2740 int n_services=lp_numservices();
2741 PRINTER_INFO_2 *printers=NULL;
2742 PRINTER_INFO_2 current_prt;
2744 for (snum=0; snum<n_services; snum++) {
2745 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2746 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2748 if (construct_printer_info_2(¤t_prt, snum)) {
2749 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2750 return ERROR_NOT_ENOUGH_MEMORY;
2751 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2752 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2758 /* check the required size. */
2759 for (i=0; i<*returned; i++)
2760 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2762 if (!alloc_buffer_size(buffer, *needed)) {
2763 for (i=0; i<*returned; i++) {
2764 free_devmode(printers[i].devmode);
2765 free_sec_desc(&printers[i].secdesc);
2767 safe_free(printers);
2768 return ERROR_INSUFFICIENT_BUFFER;
2771 /* fill the buffer with the structures */
2772 for (i=0; i<*returned; i++)
2773 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2776 for (i=0; i<*returned; i++) {
2777 free_devmode(printers[i].devmode);
2778 free_sec_desc(&printers[i].secdesc);
2780 safe_free(printers);
2782 if (*needed > offered) {
2784 return ERROR_INSUFFICIENT_BUFFER;
2787 return NT_STATUS_NO_PROBLEMO;
2790 /********************************************************************
2791 * handle enumeration of printers at level 1
2792 ********************************************************************/
2793 static uint32 enumprinters_level1( uint32 flags, fstring name,
2794 NEW_BUFFER *buffer, uint32 offered,
2795 uint32 *needed, uint32 *returned)
2797 /* Not all the flags are equals */
2799 if (flags & PRINTER_ENUM_LOCAL)
2800 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2802 if (flags & PRINTER_ENUM_NAME)
2803 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2805 if (flags & PRINTER_ENUM_REMOTE)
2806 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2808 if (flags & PRINTER_ENUM_NETWORK)
2809 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
2811 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2814 /********************************************************************
2815 * handle enumeration of printers at level 2
2816 ********************************************************************/
2817 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2818 NEW_BUFFER *buffer, uint32 offered,
2819 uint32 *needed, uint32 *returned)
2823 fstrcpy(temp, "\\\\");
2824 fstrcat(temp, global_myname);
2826 if (flags & PRINTER_ENUM_LOCAL) {
2827 if (strequal(servername, temp))
2828 return enum_all_printers_info_2(buffer, offered, needed, returned);
2830 return enum_all_printers_info_2(buffer, offered, needed, returned);
2833 if (flags & PRINTER_ENUM_NAME) {
2834 if (strequal(servername, temp))
2835 return enum_all_printers_info_2(buffer, offered, needed, returned);
2837 return ERROR_INVALID_NAME;
2840 if (flags & PRINTER_ENUM_REMOTE)
2841 return ERROR_INVALID_LEVEL;
2843 return NT_STATUS_NO_PROBLEMO;
2846 /********************************************************************
2847 * handle enumeration of printers at level 5
2848 ********************************************************************/
2849 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2850 NEW_BUFFER *buffer, uint32 offered,
2851 uint32 *needed, uint32 *returned)
2853 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2854 return NT_STATUS_NO_PROBLEMO;
2857 /********************************************************************
2858 * api_spoolss_enumprinters
2860 * called from api_spoolss_enumprinters (see this to understand)
2861 ********************************************************************/
2862 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2863 NEW_BUFFER *buffer, uint32 offered,
2864 uint32 *needed, uint32 *returned)
2868 DEBUG(4,("_spoolss_enumprinters\n"));
2875 * flags==PRINTER_ENUM_NAME
2876 * if name=="" then enumerates all printers
2877 * if name!="" then enumerate the printer
2878 * flags==PRINTER_ENUM_REMOTE
2879 * name is NULL, enumerate printers
2880 * Level 2: name!="" enumerates printers, name can't be NULL
2881 * Level 3: doesn't exist
2882 * Level 4: does a local registry lookup
2883 * Level 5: same as Level 2
2886 unistr2_to_ascii(name, servername, sizeof(name)-1);
2891 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2893 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2895 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2899 return ERROR_INVALID_LEVEL;
2903 /****************************************************************************
2904 ****************************************************************************/
2905 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2907 PRINTER_INFO_0 *printer=NULL;
2909 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2910 return ERROR_NOT_ENOUGH_MEMORY;
2912 construct_printer_info_0(printer, snum);
2914 /* check the required size. */
2915 *needed += spoolss_size_printer_info_0(printer);
2917 if (!alloc_buffer_size(buffer, *needed)) {
2919 return ERROR_INSUFFICIENT_BUFFER;
2922 /* fill the buffer with the structures */
2923 new_smb_io_printer_info_0("", buffer, printer, 0);
2928 if (*needed > offered) {
2929 return ERROR_INSUFFICIENT_BUFFER;
2932 return NT_STATUS_NO_PROBLEMO;
2935 /****************************************************************************
2936 ****************************************************************************/
2937 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2939 PRINTER_INFO_1 *printer=NULL;
2941 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2942 return ERROR_NOT_ENOUGH_MEMORY;
2944 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
2946 /* check the required size. */
2947 *needed += spoolss_size_printer_info_1(printer);
2949 if (!alloc_buffer_size(buffer, *needed)) {
2951 return ERROR_INSUFFICIENT_BUFFER;
2954 /* fill the buffer with the structures */
2955 new_smb_io_printer_info_1("", buffer, printer, 0);
2960 if (*needed > offered) {
2961 return ERROR_INSUFFICIENT_BUFFER;
2964 return NT_STATUS_NO_PROBLEMO;
2967 /****************************************************************************
2968 ****************************************************************************/
2969 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2971 PRINTER_INFO_2 *printer=NULL;
2973 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2974 return ERROR_NOT_ENOUGH_MEMORY;
2976 construct_printer_info_2(printer, snum);
2978 /* check the required size. */
2979 *needed += spoolss_size_printer_info_2(printer);
2981 if (!alloc_buffer_size(buffer, *needed)) {
2982 free_printer_info_2(printer);
2983 return ERROR_INSUFFICIENT_BUFFER;
2986 /* fill the buffer with the structures */
2987 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2988 free_printer_info_2(printer);
2989 return ERROR_NOT_ENOUGH_MEMORY;
2993 free_printer_info_2(printer);
2995 if (*needed > offered) {
2996 return ERROR_INSUFFICIENT_BUFFER;
2999 return NT_STATUS_NO_PROBLEMO;
3002 /****************************************************************************
3003 ****************************************************************************/
3004 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3006 PRINTER_INFO_3 *printer=NULL;
3008 if (!construct_printer_info_3(&printer, snum))
3009 return ERROR_NOT_ENOUGH_MEMORY;
3011 /* check the required size. */
3012 *needed += spoolss_size_printer_info_3(printer);
3014 if (!alloc_buffer_size(buffer, *needed)) {
3015 free_printer_info_3(printer);
3016 return ERROR_INSUFFICIENT_BUFFER;
3019 /* fill the buffer with the structures */
3020 new_smb_io_printer_info_3("", buffer, printer, 0);
3023 free_printer_info_3(printer);
3025 if (*needed > offered) {
3026 return ERROR_INSUFFICIENT_BUFFER;
3029 return NT_STATUS_NO_PROBLEMO;
3032 /****************************************************************************
3033 ****************************************************************************/
3034 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
3035 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3041 if (!get_printer_snum(handle, &snum))
3042 return ERROR_INVALID_HANDLE;
3046 return getprinter_level_0(snum, buffer, offered, needed);
3048 return getprinter_level_1(snum, buffer, offered, needed);
3050 return getprinter_level_2(snum, buffer, offered, needed);
3052 return getprinter_level_3(snum, buffer, offered, needed);
3054 return ERROR_INVALID_LEVEL;
3058 /********************************************************************
3059 * fill a DRIVER_INFO_1 struct
3060 ********************************************************************/
3061 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3063 init_unistr( &info->name, driver.info_3->name);
3066 /********************************************************************
3067 * construct_printer_driver_info_1
3068 ********************************************************************/
3069 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3071 NT_PRINTER_INFO_LEVEL *printer = NULL;
3072 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3074 ZERO_STRUCT(driver);
3076 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3077 return ERROR_INVALID_PRINTER_NAME;
3079 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3080 return ERROR_UNKNOWN_PRINTER_DRIVER;
3082 fill_printer_driver_info_1(info, driver, servername, architecture);
3084 free_a_printer(&printer,2);
3086 return NT_STATUS_NO_PROBLEMO;
3089 /********************************************************************
3090 * construct_printer_driver_info_2
3091 * fill a printer_info_2 struct
3092 ********************************************************************/
3093 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3097 info->version=driver.info_3->cversion;
3099 init_unistr( &info->name, driver.info_3->name );
3100 init_unistr( &info->architecture, driver.info_3->environment );
3103 if (strlen(driver.info_3->driverpath)) {
3104 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3105 init_unistr( &info->driverpath, temp );
3107 init_unistr( &info->driverpath, "" );
3109 if (strlen(driver.info_3->datafile)) {
3110 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3111 init_unistr( &info->datafile, temp );
3113 init_unistr( &info->datafile, "" );
3115 if (strlen(driver.info_3->configfile)) {
3116 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3117 init_unistr( &info->configfile, temp );
3119 init_unistr( &info->configfile, "" );
3122 /********************************************************************
3123 * construct_printer_driver_info_2
3124 * fill a printer_info_2 struct
3125 ********************************************************************/
3126 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3128 NT_PRINTER_INFO_LEVEL *printer = NULL;
3129 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3131 ZERO_STRUCT(printer);
3132 ZERO_STRUCT(driver);
3134 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3135 return ERROR_INVALID_PRINTER_NAME;
3137 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3138 return ERROR_UNKNOWN_PRINTER_DRIVER;
3140 fill_printer_driver_info_2(info, driver, servername);
3142 free_a_printer(&printer,2);
3144 return NT_STATUS_NO_PROBLEMO;
3147 /********************************************************************
3148 * copy a strings array and convert to UNICODE
3150 * convert an array of ascii string to a UNICODE string
3151 ********************************************************************/
3152 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3159 DEBUG(6,("init_unistr_array\n"));
3163 if (char_array == NULL)
3167 if (!v) v = ""; /* hack to handle null lists */
3169 if (strlen(v) == 0) break;
3170 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3171 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3172 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3173 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3176 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3181 (*uni_array)[j]=0x0000;
3184 DEBUGADD(6,("last one:done\n"));
3187 /********************************************************************
3188 * construct_printer_info_3
3189 * fill a printer_info_3 struct
3190 ********************************************************************/
3191 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3197 info->version=driver.info_3->cversion;
3199 init_unistr( &info->name, driver.info_3->name );
3200 init_unistr( &info->architecture, driver.info_3->environment );
3202 if (strlen(driver.info_3->driverpath)) {
3203 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3204 init_unistr( &info->driverpath, temp );
3206 init_unistr( &info->driverpath, "" );
3208 if (strlen(driver.info_3->datafile)) {
3209 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3210 init_unistr( &info->datafile, temp );
3212 init_unistr( &info->datafile, "" );
3214 if (strlen(driver.info_3->configfile)) {
3215 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3216 init_unistr( &info->configfile, temp );
3218 init_unistr( &info->configfile, "" );
3220 if (strlen(driver.info_3->helpfile)) {
3221 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3222 init_unistr( &info->helpfile, temp );
3224 init_unistr( &info->helpfile, "" );
3226 init_unistr( &info->monitorname, driver.info_3->monitorname );
3227 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3229 info->dependentfiles=NULL;
3230 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3233 /********************************************************************
3234 * construct_printer_info_3
3235 * fill a printer_info_3 struct
3236 ********************************************************************/
3237 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3239 NT_PRINTER_INFO_LEVEL *printer = NULL;
3240 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3242 ZERO_STRUCT(driver);
3244 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3245 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3247 return ERROR_INVALID_PRINTER_NAME;
3249 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3250 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3252 free_a_printer(&printer,2);
3253 return ERROR_UNKNOWN_PRINTER_DRIVER;
3256 fill_printer_driver_info_3(info, driver, servername);
3258 free_a_printer(&printer,2);
3260 return NT_STATUS_NO_PROBLEMO;
3263 /********************************************************************
3264 * construct_printer_info_6
3265 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3266 ********************************************************************/
3268 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3274 memset(&nullstr, '\0', sizeof(fstring));
3276 info->version=driver.info_3->cversion;
3278 init_unistr( &info->name, driver.info_3->name );
3279 init_unistr( &info->architecture, driver.info_3->environment );
3281 if (strlen(driver.info_3->driverpath)) {
3282 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3283 init_unistr( &info->driverpath, temp );
3285 init_unistr( &info->driverpath, "" );
3287 if (strlen(driver.info_3->datafile)) {
3288 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3289 init_unistr( &info->datafile, temp );
3291 init_unistr( &info->datafile, "" );
3293 if (strlen(driver.info_3->configfile)) {
3294 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3295 init_unistr( &info->configfile, temp );
3297 init_unistr( &info->configfile, "" );
3299 if (strlen(driver.info_3->helpfile)) {
3300 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3301 init_unistr( &info->helpfile, temp );
3303 init_unistr( &info->helpfile, "" );
3305 init_unistr( &info->monitorname, driver.info_3->monitorname );
3306 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3308 info->dependentfiles=NULL;
3309 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3311 info->previousdrivernames=NULL;
3312 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3314 info->driver_date.low=0;
3315 info->driver_date.high=0;
3318 info->driver_version_low=0;
3319 info->driver_version_high=0;
3321 init_unistr( &info->mfgname, "");
3322 init_unistr( &info->oem_url, "");
3323 init_unistr( &info->hardware_id, "");
3324 init_unistr( &info->provider, "");
3327 /********************************************************************
3328 * construct_printer_info_6
3329 * fill a printer_info_6 struct
3330 ********************************************************************/
3331 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3333 NT_PRINTER_INFO_LEVEL *printer = NULL;
3334 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3336 ZERO_STRUCT(driver);
3338 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3339 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3341 return ERROR_INVALID_PRINTER_NAME;
3343 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3344 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3347 * Is this a W2k client ?
3351 free_a_printer(&printer,2);
3352 return ERROR_UNKNOWN_PRINTER_DRIVER;
3355 /* Yes - try again with a WinNT driver. */
3357 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3358 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3360 free_a_printer(&printer,2);
3361 return ERROR_UNKNOWN_PRINTER_DRIVER;
3365 fill_printer_driver_info_6(info, driver, servername);
3367 free_a_printer(&printer,2);
3369 return NT_STATUS_NO_PROBLEMO;
3372 /****************************************************************************
3373 ****************************************************************************/
3375 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3377 safe_free(info->dependentfiles);
3380 /****************************************************************************
3381 ****************************************************************************/
3383 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3385 safe_free(info->dependentfiles);
3389 /****************************************************************************
3390 ****************************************************************************/
3391 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3393 DRIVER_INFO_1 *info=NULL;
3396 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3397 return ERROR_NOT_ENOUGH_MEMORY;
3399 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3400 if (status != NT_STATUS_NO_PROBLEMO) {
3405 /* check the required size. */
3406 *needed += spoolss_size_printer_driver_info_1(info);
3408 if (!alloc_buffer_size(buffer, *needed)) {
3410 return ERROR_INSUFFICIENT_BUFFER;
3413 /* fill the buffer with the structures */
3414 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3419 if (*needed > offered)
3420 return ERROR_INSUFFICIENT_BUFFER;
3422 return NT_STATUS_NO_PROBLEMO;
3425 /****************************************************************************
3426 ****************************************************************************/
3427 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3429 DRIVER_INFO_2 *info=NULL;
3432 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3433 return ERROR_NOT_ENOUGH_MEMORY;
3435 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3436 if (status != NT_STATUS_NO_PROBLEMO) {
3441 /* check the required size. */
3442 *needed += spoolss_size_printer_driver_info_2(info);
3444 if (!alloc_buffer_size(buffer, *needed)) {
3446 return ERROR_INSUFFICIENT_BUFFER;
3449 /* fill the buffer with the structures */
3450 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3455 if (*needed > offered)
3456 return ERROR_INSUFFICIENT_BUFFER;
3458 return NT_STATUS_NO_PROBLEMO;
3461 /****************************************************************************
3462 ****************************************************************************/
3463 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3470 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3471 if (status != NT_STATUS_NO_PROBLEMO) {
3475 /* check the required size. */
3476 *needed += spoolss_size_printer_driver_info_3(&info);
3478 if (!alloc_buffer_size(buffer, *needed)) {
3479 free_printer_driver_info_3(&info);
3480 return ERROR_INSUFFICIENT_BUFFER;
3483 /* fill the buffer with the structures */
3484 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3486 free_printer_driver_info_3(&info);
3488 if (*needed > offered)
3489 return ERROR_INSUFFICIENT_BUFFER;
3491 return NT_STATUS_NO_PROBLEMO;
3494 /****************************************************************************
3495 ****************************************************************************/
3496 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3503 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3504 if (status != NT_STATUS_NO_PROBLEMO) {
3508 /* check the required size. */
3509 *needed += spoolss_size_printer_driver_info_6(&info);
3511 if (!alloc_buffer_size(buffer, *needed)) {
3512 free_printer_driver_info_6(&info);
3513 return ERROR_INSUFFICIENT_BUFFER;
3516 /* fill the buffer with the structures */
3517 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3519 free_printer_driver_info_6(&info);
3521 if (*needed > offered)
3522 return ERROR_INSUFFICIENT_BUFFER;
3524 return NT_STATUS_NO_PROBLEMO;
3527 /****************************************************************************
3528 ****************************************************************************/
3529 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3530 uint32 clientmajorversion, uint32 clientminorversion,
3531 NEW_BUFFER *buffer, uint32 offered,
3532 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3535 fstring architecture;
3538 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3541 *servermajorversion=0;
3542 *serverminorversion=0;
3544 pstrcpy(servername, global_myname);
3545 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3547 if (!get_printer_snum(handle, &snum))
3548 return ERROR_INVALID_HANDLE;
3552 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3554 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3556 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3558 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3560 return ERROR_INVALID_LEVEL;
3564 /****************************************************************************
3565 ****************************************************************************/
3566 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3568 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3570 if (OPEN_HANDLE(Printer)) {
3571 Printer->page_started=True;
3575 DEBUG(3,("Error in startpageprinter printer handle\n"));
3576 return ERROR_INVALID_HANDLE;
3579 /****************************************************************************
3580 ****************************************************************************/
3581 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3583 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3585 if (!OPEN_HANDLE(Printer)) {
3586 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3587 return ERROR_INVALID_HANDLE;
3590 Printer->page_started=False;
3592 return NT_STATUS_NO_PROBLEMO;
3595 /****************************************************************************
3596 Return a user struct for a pipe user.
3597 ****************************************************************************/
3599 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3601 if (p->ntlmssp_auth_validated) {
3602 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3604 extern struct current_user current_user;
3605 memcpy(user, ¤t_user, sizeof(struct current_user));
3611 /********************************************************************
3612 * api_spoolss_getprinter
3613 * called from the spoolss dispatcher
3615 ********************************************************************/
3616 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3617 pipes_struct *p, DOC_INFO *docinfo,
3620 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3624 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3625 struct current_user user;
3627 if (!OPEN_HANDLE(Printer)) {
3628 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3629 return ERROR_INVALID_HANDLE;
3632 get_current_user(&user, p);
3635 * a nice thing with NT is it doesn't listen to what you tell it.
3636 * when asked to send _only_ RAW datas, it tries to send datas
3639 * So I add checks like in NT Server ...
3641 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3642 * there's a bug in NT client-side code, so we'll fix it in the
3643 * server-side code. *nnnnnggggh!*
3646 if (info_1->p_datatype != 0) {
3647 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3648 if (strcmp(datatype, "RAW") != 0) {
3650 return ERROR_INVALID_DATATYPE;
3654 /* get the share number of the printer */
3655 if (!get_printer_snum(handle, &snum)) {
3656 return ERROR_INVALID_HANDLE;
3659 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3661 Printer->jobid = print_job_start(&user, snum, jobname);
3663 /* An error occured in print_job_start() so return an appropriate
3666 if (Printer->jobid == -1) {
3667 return map_nt_error_from_unix(errno);
3670 Printer->document_started=True;
3671 (*jobid) = Printer->jobid;
3676 /********************************************************************
3677 * api_spoolss_getprinter
3678 * called from the spoolss dispatcher
3680 ********************************************************************/
3681 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3683 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3685 if (!OPEN_HANDLE(Printer)) {
3686 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3687 return ERROR_INVALID_HANDLE;
3690 Printer->document_started=False;
3691 print_job_end(Printer->jobid);
3692 /* error codes unhandled so far ... */
3697 /****************************************************************************
3698 ****************************************************************************/
3699 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3702 uint32 *buffer_written)
3704 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3706 if (!OPEN_HANDLE(Printer)) {
3707 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3708 return ERROR_INVALID_HANDLE;
3711 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3717 /********************************************************************
3718 * api_spoolss_getprinter
3719 * called from the spoolss dispatcher
3721 ********************************************************************/
3722 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3725 struct current_user user;
3726 int snum, errcode = ERROR_INVALID_FUNCTION;
3727 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3729 get_current_user(&user, p);
3731 if (!OPEN_HANDLE(Printer)) {
3732 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3733 return ERROR_INVALID_HANDLE;
3736 if (!get_printer_snum(handle, &snum))
3737 return ERROR_INVALID_HANDLE;
3740 case PRINTER_CONTROL_PAUSE:
3741 if (print_queue_pause(&user, snum, &errcode)) {
3745 case PRINTER_CONTROL_RESUME:
3746 case PRINTER_CONTROL_UNPAUSE:
3747 if (print_queue_resume(&user, snum, &errcode)) {
3751 case PRINTER_CONTROL_PURGE:
3752 if (print_queue_purge(&user, snum, &errcode)) {
3757 return ERROR_INVALID_LEVEL;
3763 /********************************************************************
3764 * api_spoolss_abortprinter
3765 ********************************************************************/
3767 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3769 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3772 /********************************************************************
3773 * called by spoolss_api_setprinter
3774 * when updating a printer description
3775 ********************************************************************/
3776 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3777 const SPOOL_PRINTER_INFO_LEVEL *info,
3778 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3780 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3781 struct current_user user;
3785 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3787 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3788 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3789 OUR_HANDLE(handle)));
3791 result = ERROR_INVALID_HANDLE;
3795 /* NT seems to like setting the security descriptor even though
3796 nothing may have actually changed. This causes annoying
3797 dialog boxes when the user doesn't have permission to change
3798 the security descriptor. */
3800 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3802 if (DEBUGLEVEL >= 10) {
3806 acl = old_secdesc_ctr->sec->dacl;
3807 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3808 PRINTERNAME(snum), acl->num_aces));
3810 for (i = 0; i < acl->num_aces; i++) {
3813 sid_to_string(sid_str, &acl->ace[i].sid);
3815 DEBUG(10, ("%s 0x%08x\n", sid_str,
3816 acl->ace[i].info.mask));
3819 acl = secdesc_ctr->sec->dacl;
3822 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3823 PRINTERNAME(snum), acl->num_aces));
3825 for (i = 0; i < acl->num_aces; i++) {
3828 sid_to_string(sid_str, &acl->ace[i].sid);
3830 DEBUG(10, ("%s 0x%08x\n", sid_str,
3831 acl->ace[i].info.mask));
3834 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3838 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3840 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3841 result = NT_STATUS_NO_PROBLEMO;
3845 /* Work out which user is performing the operation */
3847 get_current_user(&user, p);
3849 /* Check the user has permissions to change the security
3850 descriptor. By experimentation with two NT machines, the user
3851 requires Full Access to the printer to change security
3854 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3855 result = ERROR_ACCESS_DENIED;
3859 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3862 free_sec_desc_buf(&new_secdesc_ctr);
3863 free_sec_desc_buf(&old_secdesc_ctr);
3868 /********************************************************************
3869 Do Samba sanity checks on a printer info struct.
3870 this has changed purpose: it now "canonicalises" printer
3871 info from a client rather than just checking it is correct
3872 ********************************************************************/
3874 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3876 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3877 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3879 /* we force some elements to "correct" values */
3880 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3881 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3882 global_myname, lp_servicename(snum));
3883 fstrcpy(info->sharename, lp_servicename(snum));
3884 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3885 | PRINTER_ATTRIBUTE_LOCAL \
3886 | PRINTER_ATTRIBUTE_RAW_ONLY \
3887 | PRINTER_ATTRIBUTE_QUEUED ;
3892 /****************************************************************************
3893 ****************************************************************************/
3894 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3896 pid_t local_pid = sys_getpid();
3897 char *cmd = lp_addprinter_cmd();
3902 pstring driverlocation;
3906 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3907 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3911 /* build driver path... only 9X architecture is needed for legacy reasons */
3912 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3914 /* change \ to \\ for the shell */
3915 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3917 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3918 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3919 cmd, printer->info_2->printername, printer->info_2->sharename,
3920 printer->info_2->portname, printer->info_2->drivername,
3921 printer->info_2->location, driverlocation);
3925 /* Convert script args to unix-codepage */
3926 dos_to_unix(command, True);
3927 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3928 ret = smbrun(command, tmp_file, False);
3929 DEBUGADD(10,("returned [%d]\n", ret));
3937 /* Get lines and convert them back to dos-codepage */
3938 qlines = file_lines_load(tmp_file, &numlines, True);
3939 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3940 DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
3944 /* Set the portname to what the script says the portname should be. */
3945 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3946 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3948 /* Send SIGHUP to process group... is there a better way? */
3953 file_lines_free(qlines);
3957 /* Return true if two devicemodes are equal */
3959 #define DEVMODE_CHECK_INT(field) \
3960 if (d1->field != d2->field) { \
3961 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
3962 d1->field, d2->field)); \
3966 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3968 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
3971 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
3972 return False; /* if either is exclusively NULL are not equal */
3975 if (!strequal(d1->devicename, d2->devicename) ||
3976 !strequal(d1->formname, d2->formname)) {
3977 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
3981 DEVMODE_CHECK_INT(specversion);
3982 DEVMODE_CHECK_INT(driverversion);
3983 DEVMODE_CHECK_INT(driverextra);
3984 DEVMODE_CHECK_INT(orientation);
3985 DEVMODE_CHECK_INT(papersize);
3986 DEVMODE_CHECK_INT(paperlength);
3987 DEVMODE_CHECK_INT(paperwidth);
3988 DEVMODE_CHECK_INT(scale);
3989 DEVMODE_CHECK_INT(copies);
3990 DEVMODE_CHECK_INT(defaultsource);
3991 DEVMODE_CHECK_INT(printquality);
3992 DEVMODE_CHECK_INT(color);
3993 DEVMODE_CHECK_INT(duplex);
3994 DEVMODE_CHECK_INT(yresolution);
3995 DEVMODE_CHECK_INT(ttoption);
3996 DEVMODE_CHECK_INT(collate);
3997 DEVMODE_CHECK_INT(logpixels);
3999 DEVMODE_CHECK_INT(fields);
4000 DEVMODE_CHECK_INT(bitsperpel);
4001 DEVMODE_CHECK_INT(pelswidth);
4002 DEVMODE_CHECK_INT(pelsheight);
4003 DEVMODE_CHECK_INT(displayflags);
4004 DEVMODE_CHECK_INT(displayfrequency);
4005 DEVMODE_CHECK_INT(icmmethod);
4006 DEVMODE_CHECK_INT(icmintent);
4007 DEVMODE_CHECK_INT(mediatype);
4008 DEVMODE_CHECK_INT(dithertype);
4009 DEVMODE_CHECK_INT(reserved1);
4010 DEVMODE_CHECK_INT(reserved2);
4011 DEVMODE_CHECK_INT(panningwidth);
4012 DEVMODE_CHECK_INT(panningheight);
4014 /* compare the private data if it exists */
4015 if (!d1->driverextra && !d2->driverextra) goto equal;
4018 DEVMODE_CHECK_INT(driverextra);
4020 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4021 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4026 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4030 /* Return true if two NT_PRINTER_PARAM structures are equal */
4032 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4033 NT_PRINTER_PARAM *p2)
4035 if (!p1 && !p2) goto equal;
4037 if ((!p1 && p2) || (p1 && !p2)) {
4038 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4042 /* Compare lists of printer parameters */
4046 NT_PRINTER_PARAM *q = p1;
4048 /* Find the parameter in the second structure */
4052 if (strequal(p1->value, q->value)) {
4054 if (p1->type != q->type) {
4055 DEBUG(10, ("nt_printer_param_equal():"
4056 "types for %s differ (%d != %d)\n",
4057 p1->value, p1->type,
4062 if (p1->data_len != q->data_len) {
4063 DEBUG(10, ("nt_printer_param_equal():"
4064 "len for %s differs (%d != %d)\n",
4065 p1->value, p1->data_len,
4070 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4073 DEBUG(10, ("nt_printer_param_equal():"
4074 "data for %s differs\n", p1->value));
4084 DEBUG(10, ("nt_printer_param_equal(): param %s "
4085 "does not exist\n", p1->value));
4094 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4098 /********************************************************************
4099 * Called by update_printer when trying to work out whether to
4100 * actually update printer info.
4101 ********************************************************************/
4103 #define PI_CHECK_INT(field) \
4104 if (pi1->field != pi2->field) { \
4105 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4106 pi1->field, pi2->field)); \
4110 #define PI_CHECK_STR(field) \
4111 if (!strequal(pi1->field, pi2->field)) { \
4112 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4113 pi1->field, pi2->field)); \
4117 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4118 NT_PRINTER_INFO_LEVEL *p2)
4120 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4122 /* Trivial conditions */
4124 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4128 if ((!p1 && p2) || (p1 && !p2) ||
4129 (!p1->info_2 && p2->info_2) ||
4130 (p1->info_2 && !p2->info_2)) {
4131 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4136 /* Compare two nt_printer_info_level structures. Don't compare
4137 status or cjobs as they seem to have something to do with the
4143 PI_CHECK_INT(attributes);
4144 PI_CHECK_INT(priority);
4145 PI_CHECK_INT(default_priority);
4146 PI_CHECK_INT(starttime);
4147 PI_CHECK_INT(untiltime);
4148 PI_CHECK_INT(averageppm);
4150 /* Yuck - don't check the printername or servername as the
4151 add_a_printer() code plays games with them. You can't
4152 change the printername or the sharename through this interface
4155 PI_CHECK_STR(sharename);
4156 PI_CHECK_STR(portname);
4157 PI_CHECK_STR(drivername);
4158 PI_CHECK_STR(comment);
4159 PI_CHECK_STR(location);
4161 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4165 PI_CHECK_STR(sepfile);
4166 PI_CHECK_STR(printprocessor);
4167 PI_CHECK_STR(datatype);
4168 PI_CHECK_STR(parameters);
4170 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4174 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4178 PI_CHECK_INT(changeid);
4179 PI_CHECK_INT(c_setprinter);
4180 PI_CHECK_INT(setuptime);
4183 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4187 /********************************************************************
4188 * called by spoolss_api_setprinter
4189 * when updating a printer description
4190 ********************************************************************/
4192 static uint32 update_printer(POLICY_HND *handle, uint32 level,
4193 const SPOOL_PRINTER_INFO_LEVEL *info,
4194 DEVICEMODE *devmode)
4197 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4198 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4201 DEBUG(8,("update_printer\n"));
4203 result = NT_STATUS_NO_PROBLEMO;
4206 DEBUG(0,("Send a mail to samba@samba.org\n"));
4207 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4208 result = ERROR_INVALID_LEVEL;
4212 if (!OPEN_HANDLE(Printer)) {
4213 result = ERROR_INVALID_HANDLE;
4217 if (!get_printer_snum(handle, &snum)) {
4218 result = ERROR_INVALID_HANDLE;
4222 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4223 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4224 result = ERROR_INVALID_HANDLE;
4228 DEBUGADD(8,("Converting info_2 struct\n"));
4231 * convert_printer_info converts the incoming
4232 * info from the client and overwrites the info
4233 * just read from the tdb in the pointer 'printer'.
4236 convert_printer_info(info, printer, level);
4238 if (info->info_2->devmode_ptr != 0) {
4239 /* we have a valid devmode
4240 convert it and link it*/
4243 * Ensure printer->info_2->devmode is a valid pointer
4244 * as we will be overwriting it in convert_devicemode().
4247 if (printer->info_2->devmode == NULL)
4248 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
4250 DEBUGADD(8,("Converting the devicemode struct\n"));
4251 convert_devicemode(devmode, printer->info_2->devmode);
4254 if (printer->info_2->devmode != NULL)
4255 free_nt_devicemode(&printer->info_2->devmode);
4256 printer->info_2->devmode=NULL;
4259 /* Do sanity check on the requested changes for Samba */
4261 if (!check_printer_ok(printer->info_2, snum)) {
4262 result = ERROR_INVALID_PARAMETER;
4266 /* NT likes to call this function even though nothing has actually
4267 changed. Check this so the user doesn't end up with an
4268 annoying permission denied dialog box. */
4270 if (nt_printer_info_level_equal(printer, old_printer)) {
4271 DEBUG(3, ("printer info has not changed\n"));
4272 result = NT_STATUS_NO_PROBLEMO;
4276 /* Check calling user has permission to update printer description */
4278 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4279 DEBUG(3, ("printer property change denied by security "
4281 result = ERROR_ACCESS_DENIED;
4285 /* Call addprinter hook */
4287 if (*lp_addprinter_cmd() )
4288 if ( !add_printer_hook(printer) ) {
4289 result = ERROR_ACCESS_DENIED;
4293 /* Update printer info */
4295 if (add_a_printer(*printer, 2)!=0) {
4296 /* I don't really know what to return here !!! */
4297 result = ERROR_ACCESS_DENIED;
4302 free_a_printer(&printer, 2);
4303 free_a_printer(&old_printer, 2);
4305 srv_spoolss_sendnotify(handle);
4310 /****************************************************************************
4311 ****************************************************************************/
4312 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
4313 const SPOOL_PRINTER_INFO_LEVEL *info,
4314 DEVMODE_CTR devmode_ctr,
4315 SEC_DESC_BUF *secdesc_ctr,
4316 uint32 command, pipes_struct *p)
4318 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4320 if (!OPEN_HANDLE(Printer)) {
4321 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4322 return ERROR_INVALID_HANDLE;
4325 /* check the level */
4328 return control_printer(handle, command, p);
4330 return update_printer(handle, level, info, devmode_ctr.devmode);
4332 return update_printer_sec(handle, level, info, p,
4335 return ERROR_INVALID_LEVEL;
4339 /****************************************************************************
4340 ****************************************************************************/
4341 uint32 _spoolss_fcpn(POLICY_HND *handle)
4343 Printer_entry *Printer= find_printer_index_by_hnd(handle);
4345 if (!OPEN_HANDLE(Printer)) {
4346 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4347 return ERROR_INVALID_HANDLE;
4350 if (Printer->notify.client_connected==True)
4351 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4352 return ERROR_INVALID_HANDLE;
4354 Printer->notify.flags=0;
4355 Printer->notify.options=0;
4356 Printer->notify.localmachine[0]='\0';
4357 Printer->notify.printerlocal=0;
4358 if (Printer->notify.option)
4359 safe_free(Printer->notify.option->ctr.type);
4360 safe_free(Printer->notify.option);
4361 Printer->notify.option=NULL;
4362 Printer->notify.client_connected=False;
4364 return NT_STATUS_NO_PROBLEMO;
4367 /****************************************************************************
4368 ****************************************************************************/
4369 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
4370 NEW_BUFFER *buffer, uint32 offered,
4374 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4375 returns for AddJob. AddJob
4376 must fail on non-local
4380 /****************************************************************************
4381 ****************************************************************************/
4382 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4383 int position, int snum)
4389 t=gmtime(&queue->time);
4390 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4392 job_info->jobid=queue->job;
4393 init_unistr(&job_info->printername, lp_servicename(snum));
4394 init_unistr(&job_info->machinename, temp_name);
4395 init_unistr(&job_info->username, queue->user);
4396 init_unistr(&job_info->document, queue->file);
4397 init_unistr(&job_info->datatype, "RAW");
4398 init_unistr(&job_info->text_status, "");
4399 job_info->status=nt_printj_status(queue->status);
4400 job_info->priority=queue->priority;
4401 job_info->position=position;
4402 job_info->totalpages=0;
4403 job_info->pagesprinted=0;
4405 make_systemtime(&job_info->submitted, t);
4408 /****************************************************************************
4409 ****************************************************************************/
4410 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4411 int position, int snum,
4412 NT_PRINTER_INFO_LEVEL *ntprinter)
4418 t=gmtime(&queue->time);
4419 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4421 job_info->jobid=queue->job;
4423 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4425 init_unistr(&job_info->printername, chaine);
4427 init_unistr(&job_info->machinename, temp_name);
4428 init_unistr(&job_info->username, queue->user);
4429 init_unistr(&job_info->document, queue->file);
4430 init_unistr(&job_info->notifyname, queue->user);
4431 init_unistr(&job_info->datatype, "RAW");
4432 init_unistr(&job_info->printprocessor, "winprint");
4433 init_unistr(&job_info->parameters, "");
4434 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4435 init_unistr(&job_info->text_status, "");
4437 /* and here the security descriptor */
4439 job_info->status=nt_printj_status(queue->status);
4440 job_info->priority=queue->priority;
4441 job_info->position=position;
4442 job_info->starttime=0;
4443 job_info->untiltime=0;
4444 job_info->totalpages=0;
4445 job_info->size=queue->size;
4446 make_systemtime(&(job_info->submitted), t);
4447 job_info->timeelapsed=0;
4448 job_info->pagesprinted=0;
4450 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4457 /****************************************************************************
4458 Enumjobs at level 1.
4459 ****************************************************************************/
4460 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4461 NEW_BUFFER *buffer, uint32 offered,
4462 uint32 *needed, uint32 *returned)
4467 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4471 return ERROR_NOT_ENOUGH_MEMORY;
4474 for (i=0; i<*returned; i++)
4475 fill_job_info_1(&info[i], &queue[i], i, snum);
4479 /* check the required size. */
4480 for (i=0; i<*returned; i++)
4481 (*needed) += spoolss_size_job_info_1(&info[i]);
4483 if (!alloc_buffer_size(buffer, *needed)) {
4485 return ERROR_INSUFFICIENT_BUFFER;
4488 /* fill the buffer with the structures */
4489 for (i=0; i<*returned; i++)
4490 new_smb_io_job_info_1("", buffer, &info[i], 0);
4495 if (*needed > offered) {
4497 return ERROR_INSUFFICIENT_BUFFER;
4500 return NT_STATUS_NO_PROBLEMO;
4503 /****************************************************************************
4504 Enumjobs at level 2.
4505 ****************************************************************************/
4506 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4507 NEW_BUFFER *buffer, uint32 offered,
4508 uint32 *needed, uint32 *returned)
4510 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4514 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4517 return ERROR_NOT_ENOUGH_MEMORY;
4520 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4522 return ERROR_NOT_ENOUGH_MEMORY;
4525 for (i=0; i<*returned; i++)
4526 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4528 free_a_printer(&ntprinter, 2);
4531 /* check the required size. */
4532 for (i=0; i<*returned; i++)
4533 (*needed) += spoolss_size_job_info_2(&info[i]);
4535 if (!alloc_buffer_size(buffer, *needed)) {
4537 return ERROR_INSUFFICIENT_BUFFER;
4540 /* fill the buffer with the structures */
4541 for (i=0; i<*returned; i++)
4542 new_smb_io_job_info_2("", buffer, &info[i], 0);
4545 for (i = 0; i < *returned; i++)
4546 free_job_info_2(&info[i]);
4550 if (*needed > offered) {
4552 return ERROR_INSUFFICIENT_BUFFER;
4555 return NT_STATUS_NO_PROBLEMO;
4558 /****************************************************************************
4560 ****************************************************************************/
4561 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4562 NEW_BUFFER *buffer, uint32 offered,
4563 uint32 *needed, uint32 *returned)
4566 print_queue_struct *queue=NULL;
4567 print_status_struct prt_status;
4569 DEBUG(4,("_spoolss_enumjobs\n"));
4571 ZERO_STRUCT(prt_status);
4576 if (!get_printer_snum(handle, &snum))
4577 return ERROR_INVALID_HANDLE;
4579 *returned = print_queue_status(snum, &queue, &prt_status);
4580 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4582 if (*returned == 0) {
4584 return NT_STATUS_NO_PROBLEMO;
4589 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4591 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4595 return ERROR_INVALID_LEVEL;
4600 /****************************************************************************
4601 ****************************************************************************/
4602 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4607 /****************************************************************************
4608 ****************************************************************************/
4609 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4610 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4612 struct current_user user;
4613 print_status_struct prt_status;
4614 int snum, errcode = ERROR_INVALID_FUNCTION;
4616 memset(&prt_status, 0, sizeof(prt_status));
4618 if (!get_printer_snum(handle, &snum)) {
4619 return ERROR_INVALID_HANDLE;
4622 if (!print_job_exists(jobid)) {
4623 return ERROR_INVALID_PRINTER_NAME;
4626 get_current_user(&user, p);
4629 case JOB_CONTROL_CANCEL:
4630 case JOB_CONTROL_DELETE:
4631 if (print_job_delete(&user, jobid, &errcode)) {
4635 case JOB_CONTROL_PAUSE:
4636 if (print_job_pause(&user, jobid, &errcode)) {
4640 case JOB_CONTROL_RESTART:
4641 case JOB_CONTROL_RESUME:
4642 if (print_job_resume(&user, jobid, &errcode)) {
4647 return ERROR_INVALID_LEVEL;
4653 /****************************************************************************
4654 Enumerates all printer drivers at level 1.
4655 ****************************************************************************/
4656 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4661 fstring *list = NULL;
4663 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4664 DRIVER_INFO_1 *driver_info_1=NULL;
4668 #define MAX_VERSION 4
4670 for (version=0; version<MAX_VERSION; version++) {
4672 ndrivers=get_ntdrivers(&list, architecture, version);
4673 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4676 return ERROR_NOT_ENOUGH_MEMORY;
4679 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4681 return ERROR_NOT_ENOUGH_MEMORY;
4685 for (i=0; i<ndrivers; i++) {
4687 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4688 ZERO_STRUCT(driver);
4689 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4693 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4694 free_a_printer_driver(driver, 3);
4697 *returned+=ndrivers;
4701 /* check the required size. */
4702 for (i=0; i<*returned; i++) {
4703 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4704 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4707 if (!alloc_buffer_size(buffer, *needed)) {
4708 safe_free(driver_info_1);
4709 return ERROR_INSUFFICIENT_BUFFER;
4712 /* fill the buffer with the form structures */
4713 for (i=0; i<*returned; i++) {
4714 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4715 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4718 safe_free(driver_info_1);
4720 if (*needed > offered) {
4722 return ERROR_INSUFFICIENT_BUFFER;
4725 return NT_STATUS_NO_PROBLEMO;
4728 /****************************************************************************
4729 Enumerates all printer drivers at level 2.
4730 ****************************************************************************/
4731 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4736 fstring *list = NULL;
4738 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4739 DRIVER_INFO_2 *driver_info_2=NULL;
4743 #define MAX_VERSION 4
4745 for (version=0; version<MAX_VERSION; version++) {
4747 ndrivers=get_ntdrivers(&list, architecture, version);
4748 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4751 return ERROR_NOT_ENOUGH_MEMORY;
4754 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4756 return ERROR_NOT_ENOUGH_MEMORY;
4760 for (i=0; i<ndrivers; i++) {
4763 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4764 ZERO_STRUCT(driver);
4765 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4769 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4770 free_a_printer_driver(driver, 3);
4773 *returned+=ndrivers;
4777 /* check the required size. */
4778 for (i=0; i<*returned; i++) {
4779 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4780 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4783 if (!alloc_buffer_size(buffer, *needed)) {
4784 safe_free(driver_info_2);
4785 return ERROR_INSUFFICIENT_BUFFER;
4788 /* fill the buffer with the form structures */
4789 for (i=0; i<*returned; i++) {
4790 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4791 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4794 safe_free(driver_info_2);
4796 if (*needed > offered) {
4798 return ERROR_INSUFFICIENT_BUFFER;
4801 return NT_STATUS_NO_PROBLEMO;
4804 /****************************************************************************
4805 Enumerates all printer drivers at level 3.
4806 ****************************************************************************/
4807 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4812 fstring *list = NULL;
4814 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4815 DRIVER_INFO_3 *driver_info_3=NULL;
4819 #define MAX_VERSION 4
4821 for (version=0; version<MAX_VERSION; version++) {
4823 ndrivers=get_ntdrivers(&list, architecture, version);
4824 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4827 return ERROR_NOT_ENOUGH_MEMORY;
4830 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4832 return ERROR_NOT_ENOUGH_MEMORY;
4836 for (i=0; i<ndrivers; i++) {
4839 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4840 ZERO_STRUCT(driver);
4841 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4845 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4846 free_a_printer_driver(driver, 3);
4849 *returned+=ndrivers;
4853 /* check the required size. */
4854 for (i=0; i<*returned; i++) {
4855 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4856 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4859 if (!alloc_buffer_size(buffer, *needed)) {
4860 safe_free(driver_info_3);
4861 return ERROR_INSUFFICIENT_BUFFER;
4864 /* fill the buffer with the driver structures */
4865 for (i=0; i<*returned; i++) {
4866 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4867 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4870 for (i=0; i<*returned; i++)
4871 safe_free(driver_info_3[i].dependentfiles);
4873 safe_free(driver_info_3);
4875 if (*needed > offered) {
4877 return ERROR_INSUFFICIENT_BUFFER;
4880 return NT_STATUS_NO_PROBLEMO;
4883 /****************************************************************************
4884 Enumerates all printer drivers.
4885 ****************************************************************************/
4886 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4887 NEW_BUFFER *buffer, uint32 offered,
4888 uint32 *needed, uint32 *returned)
4890 fstring *list = NULL;
4892 fstring architecture;
4894 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4895 fstrcpy(servername, global_myname);
4899 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4903 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4905 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4907 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4911 return ERROR_INVALID_LEVEL;
4915 /****************************************************************************
4916 ****************************************************************************/
4917 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4919 form->flag=list->flag;
4920 init_unistr(&form->name, list->name);
4921 form->width=list->width;
4922 form->length=list->length;
4923 form->left=list->left;
4924 form->top=list->top;
4925 form->right=list->right;
4926 form->bottom=list->bottom;
4929 /****************************************************************************
4930 ****************************************************************************/
4931 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4932 NEW_BUFFER *buffer, uint32 offered,
4933 uint32 *needed, uint32 *numofforms)
4935 nt_forms_struct *list=NULL;
4940 DEBUG(4,("_new_spoolss_enumforms\n"));
4941 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4942 DEBUGADD(5,("Info level [%d]\n", level));
4944 *numofforms = get_ntforms(&list);
4945 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4947 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4951 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4953 return ERROR_NOT_ENOUGH_MEMORY;
4956 /* construct the list of form structures */
4957 for (i=0; i<*numofforms; i++) {
4958 DEBUGADD(6,("Filling form number [%d]\n",i));
4959 fill_form_1(&forms_1[i], &list[i]);
4964 /* check the required size. */
4965 for (i=0; i<*numofforms; i++) {
4966 DEBUGADD(6,("adding form [%d]'s size\n",i));
4967 buffer_size += spoolss_size_form_1(&forms_1[i]);
4970 *needed=buffer_size;
4972 if (!alloc_buffer_size(buffer, buffer_size)){
4974 return ERROR_INSUFFICIENT_BUFFER;
4977 /* fill the buffer with the form structures */
4978 for (i=0; i<*numofforms; i++) {
4979 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4980 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4985 if (*needed > offered) {
4987 return ERROR_INSUFFICIENT_BUFFER;
4990 return NT_STATUS_NO_PROBLEMO;
4994 return ERROR_INVALID_LEVEL;
4999 /****************************************************************************
5000 ****************************************************************************/
5001 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5003 nt_forms_struct *list=NULL;
5009 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5011 DEBUG(4,("_spoolss_getform\n"));
5012 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5013 DEBUGADD(5,("Info level [%d]\n", level));
5015 numofforms = get_ntforms(&list);
5016 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5018 if (numofforms == 0)
5019 return ERROR_NO_MORE_ITEMS;
5024 /* Check if the requested name is in the list of form structures */
5025 for (i=0; i<numofforms; i++) {
5027 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5029 if (strequal(form_name, list[i].name)) {
5030 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5031 fill_form_1(&form_1, &list[i]);
5038 /* check the required size. */
5040 *needed=spoolss_size_form_1(&form_1);
5042 if (!alloc_buffer_size(buffer, buffer_size)){
5043 return ERROR_INSUFFICIENT_BUFFER;
5046 if (*needed > offered) {
5047 return ERROR_INSUFFICIENT_BUFFER;
5050 /* fill the buffer with the form structures */
5051 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5052 new_smb_io_form_1("", buffer, &form_1, 0);
5054 return NT_STATUS_NO_PROBLEMO;
5058 return ERROR_INVALID_LEVEL;
5062 /****************************************************************************
5063 ****************************************************************************/
5064 static void fill_port_1(PORT_INFO_1 *port, char *name)
5066 init_unistr(&port->port_name, name);
5069 /****************************************************************************
5070 ****************************************************************************/
5071 static void fill_port_2(PORT_INFO_2 *port, char *name)
5073 init_unistr(&port->port_name, name);
5074 init_unistr(&port->monitor_name, "Local Monitor");
5075 init_unistr(&port->description, "Local Port");
5076 #define PORT_TYPE_WRITE 1
5077 port->port_type=PORT_TYPE_WRITE;
5081 /****************************************************************************
5083 ****************************************************************************/
5084 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5086 PORT_INFO_1 *ports=NULL;
5089 if (*lp_enumports_cmd()) {
5090 pid_t local_pid = sys_getpid();
5091 char *cmd = lp_enumports_cmd();
5099 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5100 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5104 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5105 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
5108 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5109 ret = smbrun(command, tmp_file, False);
5110 DEBUG(10,("Returned [%d]\n", ret));
5113 /* Is this the best error to return here? */
5114 return ERROR_ACCESS_DENIED;
5118 qlines = file_lines_load(tmp_file, &numlines,True);
5119 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5120 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5124 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5125 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5126 file_lines_free(qlines);
5127 return ERROR_NOT_ENOUGH_MEMORY;
5130 for (i=0; i<numlines; i++) {
5131 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5132 fill_port_1(&ports[i], qlines[i]);
5135 file_lines_free(qlines);
5138 *returned = numlines;
5141 *returned = 1; /* Sole Samba port returned. */
5143 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5144 return ERROR_NOT_ENOUGH_MEMORY;
5146 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5148 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5151 /* check the required size. */
5152 for (i=0; i<*returned; i++) {
5153 DEBUGADD(6,("adding port [%d]'s size\n", i));
5154 *needed += spoolss_size_port_info_1(&ports[i]);
5157 if (!alloc_buffer_size(buffer, *needed)) {
5159 return ERROR_INSUFFICIENT_BUFFER;
5162 /* fill the buffer with the ports structures */
5163 for (i=0; i<*returned; i++) {
5164 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5165 new_smb_io_port_1("", buffer, &ports[i], 0);
5170 if (*needed > offered) {
5172 return ERROR_INSUFFICIENT_BUFFER;
5175 return NT_STATUS_NO_PROBLEMO;
5178 /****************************************************************************
5180 ****************************************************************************/
5182 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5184 PORT_INFO_2 *ports=NULL;
5187 if (*lp_enumports_cmd()) {
5188 pid_t local_pid = sys_getpid();
5189 char *cmd = lp_enumports_cmd();
5197 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5198 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5202 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5203 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
5206 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5207 ret = smbrun(command, tmp_file, False);
5208 DEBUGADD(10,("returned [%d]\n", ret));
5211 /* Is this the best error to return here? */
5212 return ERROR_ACCESS_DENIED;
5216 qlines = file_lines_load(tmp_file, &numlines,True);
5217 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5218 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5222 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5223 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5224 file_lines_free(qlines);
5225 return ERROR_NOT_ENOUGH_MEMORY;
5228 for (i=0; i<numlines; i++) {
5229 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5230 fill_port_2(&(ports[i]), qlines[i]);
5233 file_lines_free(qlines);
5236 *returned = numlines;
5242 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5243 return ERROR_NOT_ENOUGH_MEMORY;
5245 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5247 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5250 /* check the required size. */
5251 for (i=0; i<*returned; i++) {
5252 DEBUGADD(6,("adding port [%d]'s size\n", i));
5253 *needed += spoolss_size_port_info_2(&ports[i]);
5256 if (!alloc_buffer_size(buffer, *needed)) {
5258 return ERROR_INSUFFICIENT_BUFFER;
5261 /* fill the buffer with the ports structures */
5262 for (i=0; i<*returned; i++) {
5263 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5264 new_smb_io_port_2("", buffer, &ports[i], 0);
5269 if (*needed > offered) {
5271 return ERROR_INSUFFICIENT_BUFFER;
5274 return NT_STATUS_NO_PROBLEMO;
5277 /****************************************************************************
5279 ****************************************************************************/
5280 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
5281 NEW_BUFFER *buffer, uint32 offered,
5282 uint32 *needed, uint32 *returned)
5284 DEBUG(4,("_spoolss_enumports\n"));
5291 return enumports_level_1(buffer, offered, needed, returned);
5293 return enumports_level_2(buffer, offered, needed, returned);
5295 return ERROR_INVALID_LEVEL;
5299 /****************************************************************************
5300 ****************************************************************************/
5301 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5302 const SPOOL_PRINTER_INFO_LEVEL *info,
5303 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5304 uint32 user_switch, const SPOOL_USER_CTR *user,
5307 NT_PRINTER_INFO_LEVEL *printer = NULL;
5311 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5312 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5313 return ERROR_NOT_ENOUGH_MEMORY;
5316 ZERO_STRUCTP(printer);
5318 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5319 convert_printer_info(info, printer, 2);
5321 if (*lp_addprinter_cmd() )
5322 if ( !add_printer_hook(printer) ) {
5323 free_a_printer(&printer,2);
5324 return ERROR_ACCESS_DENIED;
5327 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5328 printer->info_2->sharename);
5330 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5331 free_a_printer(&printer,2);
5332 return ERROR_ACCESS_DENIED;
5335 /* you must be a printer admin to add a new printer */
5336 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5337 free_a_printer(&printer,2);
5338 return ERROR_ACCESS_DENIED;
5342 * Do sanity check on the requested changes for Samba.
5345 if (!check_printer_ok(printer->info_2, snum)) {
5346 free_a_printer(&printer,2);
5347 return ERROR_INVALID_PARAMETER;
5350 /* write the ASCII on disk */
5351 if (add_a_printer(*printer, 2) != 0) {
5352 free_a_printer(&printer,2);
5353 return ERROR_ACCESS_DENIED;
5356 if (!open_printer_hnd(handle, name)) {
5357 /* Handle open failed - remove addition. */
5358 del_a_printer(printer->info_2->sharename);
5359 free_a_printer(&printer,2);
5360 return ERROR_ACCESS_DENIED;
5363 free_a_printer(&printer,2);
5365 srv_spoolss_sendnotify(handle);
5367 return NT_STATUS_NO_PROBLEMO;
5370 /****************************************************************************
5371 ****************************************************************************/
5372 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5373 const SPOOL_PRINTER_INFO_LEVEL *info,
5374 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5375 uint32 user_switch, const SPOOL_USER_CTR *user,
5380 /* we don't handle yet */
5381 /* but I know what to do ... */
5382 return ERROR_INVALID_LEVEL;
5384 return spoolss_addprinterex_level_2(uni_srv_name, info,
5385 unk0, unk1, unk2, unk3,
5386 user_switch, user, handle);
5388 return ERROR_INVALID_LEVEL;
5392 /****************************************************************************
5393 ****************************************************************************/
5394 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5395 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5397 uint32 err = NT_STATUS_NO_PROBLEMO;
5398 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5399 struct current_user user;
5401 ZERO_STRUCT(driver);
5403 get_current_user(&user, p);
5405 convert_printer_driver_info(info, &driver, level);
5407 DEBUG(5,("Cleaning driver's information\n"));
5408 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5411 DEBUG(5,("Moving driver to final destination\n"));
5412 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5414 err = ERROR_ACCESS_DENIED;
5418 if (add_a_printer_driver(driver, level)!=0) {
5419 err = ERROR_ACCESS_DENIED;
5424 free_a_printer_driver(driver, level);
5428 /****************************************************************************
5429 ****************************************************************************/
5430 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5432 init_unistr(&info->name, name);
5435 /****************************************************************************
5436 ****************************************************************************/
5437 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5441 pstring short_archi;
5442 DRIVER_DIRECTORY_1 *info=NULL;
5444 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5446 if (get_short_archi(short_archi, long_archi)==FALSE)
5447 return ERROR_INVALID_ENVIRONMENT;
5449 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5450 return ERROR_NOT_ENOUGH_MEMORY;
5452 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5454 DEBUG(4,("printer driver directory: [%s]\n", path));
5456 fill_driverdir_1(info, path);
5458 *needed += spoolss_size_driverdir_info_1(info);
5460 if (!alloc_buffer_size(buffer, *needed)) {
5462 return ERROR_INSUFFICIENT_BUFFER;
5465 new_smb_io_driverdir_1("", buffer, info, 0);
5469 if (*needed > offered)
5470 return ERROR_INSUFFICIENT_BUFFER;
5472 return NT_STATUS_NO_PROBLEMO;
5475 /****************************************************************************
5476 ****************************************************************************/
5477 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5478 NEW_BUFFER *buffer, uint32 offered,
5481 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5487 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5489 return ERROR_INVALID_LEVEL;
5493 /****************************************************************************
5494 ****************************************************************************/
5495 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5496 uint32 in_value_len, uint32 in_data_len,
5497 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5499 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5501 NT_PRINTER_INFO_LEVEL *printer = NULL;
5506 uint32 biggest_valuesize;
5507 uint32 biggest_datasize;
5509 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5514 ZERO_STRUCT(printer);
5516 *out_max_value_len=0;
5522 *out_max_data_len=0;
5526 DEBUG(5,("spoolss_enumprinterdata\n"));
5528 if (!OPEN_HANDLE(Printer)) {
5529 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5530 return ERROR_INVALID_HANDLE;
5533 if (!get_printer_snum(handle, &snum))
5534 return ERROR_INVALID_HANDLE;
5536 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5537 return ERROR_INVALID_HANDLE;
5540 * The NT machine wants to know the biggest size of value and data
5542 * cf: MSDN EnumPrinterData remark section
5544 if ( (in_value_len==0) && (in_data_len==0) ) {
5545 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5549 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5550 * if this parameter size doesn't exist.
5551 * Ok - my opinion here is that the client is not asking for the greatest
5552 * possible size of all the parameters, but is asking specifically for the size needed
5553 * for this specific parameter. In that case we can remove the loop below and
5554 * simplify this lookup code considerably. JF - comments welcome. JRA.
5557 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5559 free_a_printer(&printer, 2);
5560 return ERROR_NO_MORE_ITEMS;
5568 biggest_valuesize=0;
5571 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5572 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5573 if (data_len > biggest_datasize) biggest_datasize=data_len;
5575 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5583 * I think this is correct, it doesn't break APW and
5584 * allows Gerald's Win32 test programs to work correctly,
5585 * but may need altering.... JRA.
5588 if (param_index == 0) {
5589 /* No parameters found. */
5590 free_a_printer(&printer, 2);
5591 return ERROR_NO_MORE_ITEMS;
5594 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5595 *out_value_len=2*(1+biggest_valuesize);
5596 *out_data_len=biggest_datasize;
5598 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5600 free_a_printer(&printer, 2);
5601 return NT_STATUS_NO_PROBLEMO;
5605 * the value len is wrong in NT sp3
5606 * that's the number of bytes not the number of unicode chars
5609 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5611 free_a_printer(&printer, 2);
5612 return ERROR_NO_MORE_ITEMS;
5615 free_a_printer(&printer, 2);
5619 * - counted in bytes in the request
5620 * - counted in UNICODE chars in the max reply
5621 * - counted in bytes in the real size
5623 * take a pause *before* coding not *during* coding
5626 *out_max_value_len=(in_value_len/sizeof(uint16));
5627 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5629 return ERROR_NOT_ENOUGH_MEMORY;
5632 ZERO_STRUCTP(*out_value);
5633 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5637 /* the data is counted in bytes */
5638 *out_max_data_len=in_data_len;
5639 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5641 return ERROR_NOT_ENOUGH_MEMORY;
5644 memset(*data_out,'\0',in_data_len);
5645 memcpy(*data_out, data, (size_t)data_len);
5646 *out_data_len=data_len;
5650 return NT_STATUS_NO_PROBLEMO;
5653 /****************************************************************************
5654 ****************************************************************************/
5655 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5656 const UNISTR2 *value,
5661 uint32 numeric_data)
5663 NT_PRINTER_INFO_LEVEL *printer = NULL;
5664 NT_PRINTER_PARAM *param = NULL, old_param;
5666 uint32 status = 0x0;
5667 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5669 DEBUG(5,("spoolss_setprinterdata\n"));
5671 if (!OPEN_HANDLE(Printer)) {
5672 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5673 return ERROR_INVALID_HANDLE;
5676 if (!get_printer_snum(handle, &snum))
5677 return ERROR_INVALID_HANDLE;
5679 status = get_a_printer(&printer, 2, lp_servicename(snum));
5681 return ERROR_INVALID_NAME;
5683 convert_specific_param(¶m, value , type, data, real_len);
5685 /* Check if we are making any changes or not. Return true if
5686 nothing is actually changing. */
5688 ZERO_STRUCT(old_param);
5690 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5691 &old_param.type, (unsigned int *)&old_param.data_len)) {
5693 if (param->type == old_param.type &&
5694 param->data_len == old_param.data_len &&
5695 memcmp(param->data, old_param.data,
5696 old_param.data_len) == 0) {
5698 DEBUG(3, ("setprinterdata hasn't changed\n"));
5699 status = NT_STATUS_NO_PROBLEMO;
5706 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5707 DEBUG(3, ("security descriptor change denied by existing "
5708 "security descriptor\n"));
5709 status = ERROR_ACCESS_DENIED;
5713 unlink_specific_param_if_exist(printer->info_2, param);
5715 add_a_specific_param(printer->info_2, ¶m);
5716 status = mod_a_printer(*printer, 2);
5719 free_a_printer(&printer, 2);
5721 free_nt_printer_param(¶m);
5722 safe_free(old_param.data);
5727 /****************************************************************************
5728 ****************************************************************************/
5729 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5731 NT_PRINTER_INFO_LEVEL *printer = NULL;
5732 NT_PRINTER_PARAM param;
5734 uint32 status = 0x0;
5735 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5737 DEBUG(5,("spoolss_deleteprinterdata\n"));
5739 if (!OPEN_HANDLE(Printer)) {
5740 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5741 return ERROR_INVALID_HANDLE;
5744 if (!get_printer_snum(handle, &snum))
5745 return ERROR_INVALID_HANDLE;
5747 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5748 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
5749 "change denied by existing security descriptor\n"));
5750 return ERROR_ACCESS_DENIED;
5753 status = get_a_printer(&printer, 2, lp_servicename(snum));
5755 return ERROR_INVALID_NAME;
5757 ZERO_STRUCTP(¶m);
5758 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5760 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5761 status = ERROR_INVALID_PARAMETER;
5763 status = mod_a_printer(*printer, 2);
5765 free_a_printer(&printer, 2);
5769 /****************************************************************************
5770 ****************************************************************************/
5771 uint32 _spoolss_addform( POLICY_HND *handle,
5776 nt_forms_struct *list=NULL;
5777 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5779 DEBUG(5,("spoolss_addform\n"));
5781 if (!OPEN_HANDLE(Printer)) {
5782 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5783 return ERROR_INVALID_HANDLE;
5786 count=get_ntforms(&list);
5787 if(!add_a_form(&list, form, &count))
5788 return ERROR_NOT_ENOUGH_MEMORY;
5789 write_ntforms(&list, count);
5796 /****************************************************************************
5797 ****************************************************************************/
5798 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5802 nt_forms_struct *list=NULL;
5803 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5805 DEBUG(5,("spoolss_deleteform\n"));
5807 if (!OPEN_HANDLE(Printer)) {
5808 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5809 return ERROR_INVALID_HANDLE;
5812 count = get_ntforms(&list);
5813 if(!delete_a_form(&list, form_name, &count, &ret))
5814 return ERROR_INVALID_PARAMETER;
5821 /****************************************************************************
5822 ****************************************************************************/
5823 uint32 _spoolss_setform( POLICY_HND *handle,
5824 const UNISTR2 *uni_name,
5829 nt_forms_struct *list=NULL;
5830 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5832 DEBUG(5,("spoolss_setform\n"));
5834 if (!OPEN_HANDLE(Printer)) {
5835 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5836 return ERROR_INVALID_HANDLE;
5838 count=get_ntforms(&list);
5839 update_a_form(&list, form, count);
5840 write_ntforms(&list, count);
5847 /****************************************************************************
5848 enumprintprocessors level 1.
5849 ****************************************************************************/
5850 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5852 PRINTPROCESSOR_1 *info_1=NULL;
5854 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5855 return ERROR_NOT_ENOUGH_MEMORY;
5859 init_unistr(&info_1->name, "winprint");
5861 *needed += spoolss_size_printprocessor_info_1(info_1);
5863 if (!alloc_buffer_size(buffer, *needed))
5864 return ERROR_INSUFFICIENT_BUFFER;
5866 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5870 if (*needed > offered) {
5872 return ERROR_INSUFFICIENT_BUFFER;
5875 return NT_STATUS_NO_PROBLEMO;
5878 /****************************************************************************
5879 ****************************************************************************/
5880 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5881 NEW_BUFFER *buffer, uint32 offered,
5882 uint32 *needed, uint32 *returned)
5884 DEBUG(5,("spoolss_enumprintprocessors\n"));
5887 * Enumerate the print processors ...
5889 * Just reply with "winprint", to keep NT happy
5890 * and I can use my nice printer checker.
5898 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5900 return ERROR_INVALID_LEVEL;
5904 /****************************************************************************
5905 enumprintprocdatatypes level 1.
5906 ****************************************************************************/
5907 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5909 PRINTPROCDATATYPE_1 *info_1=NULL;
5911 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5912 return ERROR_NOT_ENOUGH_MEMORY;
5916 init_unistr(&info_1->name, "RAW");
5918 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5920 if (!alloc_buffer_size(buffer, *needed))
5921 return ERROR_INSUFFICIENT_BUFFER;
5923 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5927 if (*needed > offered) {
5929 return ERROR_INSUFFICIENT_BUFFER;
5932 return NT_STATUS_NO_PROBLEMO;
5935 /****************************************************************************
5936 ****************************************************************************/
5937 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5938 NEW_BUFFER *buffer, uint32 offered,
5939 uint32 *needed, uint32 *returned)
5941 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5948 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5950 return ERROR_INVALID_LEVEL;
5954 /****************************************************************************
5955 enumprintmonitors level 1.
5956 ****************************************************************************/
5957 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5959 PRINTMONITOR_1 *info_1=NULL;
5961 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5962 return ERROR_NOT_ENOUGH_MEMORY;
5966 init_unistr(&info_1->name, "Local Port");
5968 *needed += spoolss_size_printmonitor_info_1(info_1);
5970 if (!alloc_buffer_size(buffer, *needed))
5971 return ERROR_INSUFFICIENT_BUFFER;
5973 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5977 if (*needed > offered) {
5979 return ERROR_INSUFFICIENT_BUFFER;
5982 return NT_STATUS_NO_PROBLEMO;
5985 /****************************************************************************
5986 enumprintmonitors level 2.
5987 ****************************************************************************/
5988 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5990 PRINTMONITOR_2 *info_2=NULL;
5992 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
5993 return ERROR_NOT_ENOUGH_MEMORY;
5997 init_unistr(&info_2->name, "Local Port");
5998 init_unistr(&info_2->environment, "Windows NT X86");
5999 init_unistr(&info_2->dll_name, "localmon.dll");
6001 *needed += spoolss_size_printmonitor_info_2(info_2);
6003 if (!alloc_buffer_size(buffer, *needed))
6004 return ERROR_INSUFFICIENT_BUFFER;
6006 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6010 if (*needed > offered) {
6012 return ERROR_INSUFFICIENT_BUFFER;
6015 return NT_STATUS_NO_PROBLEMO;
6018 /****************************************************************************
6019 ****************************************************************************/
6020 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
6021 NEW_BUFFER *buffer, uint32 offered,
6022 uint32 *needed, uint32 *returned)
6024 DEBUG(5,("spoolss_enumprintmonitors\n"));
6027 * Enumerate the print monitors ...
6029 * Just reply with "Local Port", to keep NT happy
6030 * and I can use my nice printer checker.
6038 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6040 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6042 return ERROR_INVALID_LEVEL;
6046 /****************************************************************************
6047 ****************************************************************************/
6048 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6052 JOB_INFO_1 *info_1=NULL;
6054 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6056 if (info_1 == NULL) {
6058 return ERROR_NOT_ENOUGH_MEMORY;
6061 for (i=0; i<count && found==False; i++) {
6062 if (queue[i].job==(int)jobid)
6069 /* I shoud reply something else ... I can't find the good one */
6070 return NT_STATUS_NO_PROBLEMO;
6073 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6077 *needed += spoolss_size_job_info_1(info_1);
6079 if (!alloc_buffer_size(buffer, *needed)) {
6081 return ERROR_INSUFFICIENT_BUFFER;
6084 new_smb_io_job_info_1("", buffer, info_1, 0);
6088 if (*needed > offered)
6089 return ERROR_INSUFFICIENT_BUFFER;
6091 return NT_STATUS_NO_PROBLEMO;
6095 /****************************************************************************
6096 ****************************************************************************/
6097 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6102 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6104 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6106 ZERO_STRUCTP(info_2);
6108 if (info_2 == NULL) {
6110 return ERROR_NOT_ENOUGH_MEMORY;
6113 for (i=0; i<count && found==False; i++) {
6114 if (queue[i].job==(int)jobid)
6121 /* I shoud reply something else ... I can't find the good one */
6122 return NT_STATUS_NO_PROBLEMO;
6125 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6127 return ERROR_NOT_ENOUGH_MEMORY;
6130 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6132 free_a_printer(&ntprinter, 2);
6135 *needed += spoolss_size_job_info_2(info_2);
6137 if (!alloc_buffer_size(buffer, *needed)) {
6139 return ERROR_INSUFFICIENT_BUFFER;
6142 new_smb_io_job_info_2("", buffer, info_2, 0);
6144 free_job_info_2(info_2);
6147 if (*needed > offered)
6148 return ERROR_INSUFFICIENT_BUFFER;
6150 return NT_STATUS_NO_PROBLEMO;
6153 /****************************************************************************
6154 ****************************************************************************/
6155 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
6156 NEW_BUFFER *buffer, uint32 offered,
6161 print_queue_struct *queue=NULL;
6162 print_status_struct prt_status;
6164 DEBUG(5,("spoolss_getjob\n"));
6166 memset(&prt_status, 0, sizeof(prt_status));
6170 if (!get_printer_snum(handle, &snum))
6171 return ERROR_INVALID_HANDLE;
6173 count = print_queue_status(snum, &queue, &prt_status);
6175 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6176 count, prt_status.status, prt_status.message));
6180 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6182 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6185 return ERROR_INVALID_LEVEL;