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;
675 if (printername == NULL) {
676 result = ERROR_INVALID_PRINTER_NAME;
680 /* some sanity check because you can open a printer or a print server */
681 /* aka: \\server\printer or \\server */
682 unistr2_to_ascii(name, printername, sizeof(name)-1);
684 DEBUGADD(3,("checking name: %s\n",name));
686 if (!open_printer_hnd(handle, name)) {
687 result = ERROR_INVALID_PRINTER_NAME;
692 if (printer_default->datatype_ptr != NULL)
694 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
695 set_printer_hnd_datatype(handle, datatype);
698 set_printer_hnd_datatype(handle, "");
701 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
702 close_printer_handle(handle);
703 result = ERROR_ACCESS_DENIED;
707 /* Disallow MS AddPrinterWizard if parameter disables it. A Win2k
708 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
709 Then both Win2k and WinNT clients try an OpenPrinterEx with
710 SERVER_ALL_ACCESS, which we force to fail. Then they try
711 OpenPrinterEx with SERVER_READ which we allow. This lets the
712 client view printer folder, but does not show the MSAPW.
714 Note: this test needs code to check access rights here too. Jeremy
715 could you look at this? */
717 if (handle_is_printserver(handle) &&
718 !lp_ms_add_printer_wizard()) {
719 if (printer_default->access_required == 0) {
722 else if (printer_default->access_required != (SERVER_READ)) {
723 close_printer_handle(handle);
724 result = ERROR_ACCESS_DENIED;
729 /* NT doesn't let us connect to a printer if the connecting user
730 doesn't have print permission. */
732 if (!handle_is_printserver(handle)) {
734 if (!get_printer_snum(handle, &snum))
735 return ERROR_INVALID_HANDLE;
737 if (!print_access_check(NULL, snum, PRINTER_ACCESS_USE)) {
738 DEBUG(3, ("access DENIED for printer open\n"));
739 close_printer_handle(handle);
740 result = ERROR_ACCESS_DENIED;
745 * If we have a default device pointer in the
746 * printer_default struct, then we need to get
747 * the printer info from the tdb and if there is
748 * no default devicemode there then we do a *SET*
749 * here ! This is insanity.... JRA.
752 if (printer_default->devmode_cont.devmode != NULL) {
753 result = printer_write_default_dev( snum, printer_default);
755 close_printer_handle(handle);
765 /****************************************************************************
766 ****************************************************************************/
767 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
768 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
772 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
781 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
782 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
786 printer->info_3=NULL;
787 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
790 printer->info_6=NULL;
791 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
800 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
801 NT_DEVICEMODE **pp_nt_devmode)
803 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
806 * Ensure nt_devmode is a valid pointer
807 * as we will be overwriting it.
810 if (nt_devmode == NULL)
811 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
814 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
815 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
817 nt_devmode->specversion=devmode->specversion;
818 nt_devmode->driverversion=devmode->driverversion;
819 nt_devmode->size=devmode->size;
820 nt_devmode->fields=devmode->fields;
821 nt_devmode->orientation=devmode->orientation;
822 nt_devmode->papersize=devmode->papersize;
823 nt_devmode->paperlength=devmode->paperlength;
824 nt_devmode->paperwidth=devmode->paperwidth;
825 nt_devmode->scale=devmode->scale;
826 nt_devmode->copies=devmode->copies;
827 nt_devmode->defaultsource=devmode->defaultsource;
828 nt_devmode->printquality=devmode->printquality;
829 nt_devmode->color=devmode->color;
830 nt_devmode->duplex=devmode->duplex;
831 nt_devmode->yresolution=devmode->yresolution;
832 nt_devmode->ttoption=devmode->ttoption;
833 nt_devmode->collate=devmode->collate;
835 nt_devmode->logpixels=devmode->logpixels;
836 nt_devmode->bitsperpel=devmode->bitsperpel;
837 nt_devmode->pelswidth=devmode->pelswidth;
838 nt_devmode->pelsheight=devmode->pelsheight;
839 nt_devmode->displayflags=devmode->displayflags;
840 nt_devmode->displayfrequency=devmode->displayfrequency;
841 nt_devmode->icmmethod=devmode->icmmethod;
842 nt_devmode->icmintent=devmode->icmintent;
843 nt_devmode->mediatype=devmode->mediatype;
844 nt_devmode->dithertype=devmode->dithertype;
845 nt_devmode->reserved1=devmode->reserved1;
846 nt_devmode->reserved2=devmode->reserved2;
847 nt_devmode->panningwidth=devmode->panningwidth;
848 nt_devmode->panningheight=devmode->panningheight;
851 * Only change private and driverextra if the incoming devmode
852 * has a new one. JRA.
855 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
856 safe_free(nt_devmode->private);
857 nt_devmode->driverextra=devmode->driverextra;
858 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
860 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
863 *pp_nt_devmode = nt_devmode;
868 /********************************************************************
869 * api_spoolss_closeprinter
870 ********************************************************************/
871 uint32 _spoolss_closeprinter(POLICY_HND *handle)
873 Printer_entry *Printer=find_printer_index_by_hnd(handle);
875 if (Printer && Printer->document_started)
876 _spoolss_enddocprinter(handle); /* print job was not closed */
878 if (!close_printer_handle(handle))
879 return ERROR_INVALID_HANDLE;
881 return NT_STATUS_NO_PROBLEMO;
884 /********************************************************************
885 * api_spoolss_deleteprinter
886 ********************************************************************/
887 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
889 Printer_entry *Printer=find_printer_index_by_hnd(handle);
892 if (Printer && Printer->document_started)
893 _spoolss_enddocprinter(handle); /* print job was not closed */
895 result = delete_printer_handle(handle);
897 if (result == ERROR_SUCCESS) {
898 srv_spoolss_sendnotify(handle);
904 /********************************************************************
905 GetPrinterData on a printer server Handle.
906 ********************************************************************/
907 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
911 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
913 if (!strcmp(value, "BeepEnabled")) {
915 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
917 SIVAL(*data, 0, 0x01);
922 if (!strcmp(value, "EventLog")) {
924 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
926 SIVAL(*data, 0, 0x1B);
931 if (!strcmp(value, "NetPopup")) {
933 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
935 SIVAL(*data, 0, 0x01);
940 if (!strcmp(value, "MajorVersion")) {
942 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
944 SIVAL(*data, 0, 0x02);
949 if (!strcmp(value, "DefaultSpoolDirectory")) {
950 pstring string="You are using a Samba server";
952 *needed = 2*(strlen(string)+1);
953 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
955 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
957 /* it's done by hand ready to go on the wire */
958 for (i=0; i<strlen(string); i++) {
959 (*data)[2*i]=string[i];
965 if (!strcmp(value, "Architecture")) {
966 pstring string="Windows NT x86";
968 *needed = 2*(strlen(string)+1);
969 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
971 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
972 for (i=0; i<strlen(string); i++) {
973 (*data)[2*i]=string[i];
982 /********************************************************************
983 GetPrinterData on a printer Handle.
984 ********************************************************************/
985 static BOOL getprinterdata_printer(POLICY_HND *handle,
986 fstring value, uint32 *type,
987 uint8 **data, uint32 *needed, uint32 in_size )
989 NT_PRINTER_INFO_LEVEL *printer = NULL;
993 Printer_entry *Printer = find_printer_index_by_hnd(handle);
995 DEBUG(5,("getprinterdata_printer\n"));
997 if (!OPEN_HANDLE(Printer)) {
998 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1002 if(!get_printer_snum(handle, &snum))
1005 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1008 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1009 free_a_printer(&printer, 2);
1013 free_a_printer(&printer, 2);
1015 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1018 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
1022 memset(*data, 0, in_size *sizeof(uint8));
1023 /* copy the min(in_size, len) */
1024 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1031 DEBUG(5,("getprinterdata_printer:copy done\n"));
1038 /********************************************************************
1039 * spoolss_getprinterdata
1040 ********************************************************************/
1041 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
1050 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1053 * Reminder: when it's a string, the length is in BYTES
1054 * even if UNICODE is negociated.
1061 /* in case of problem, return some default values */
1065 DEBUG(4,("_spoolss_getprinterdata\n"));
1067 if (!OPEN_HANDLE(Printer)) {
1068 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1069 return ERROR_NOT_ENOUGH_MEMORY;
1070 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1071 return ERROR_INVALID_HANDLE;
1074 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1076 if (handle_is_printserver(handle))
1077 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1079 found= getprinterdata_printer(handle, value, type, data, needed, *out_size);
1082 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1083 /* reply this param doesn't exist */
1085 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
1086 return ERROR_NOT_ENOUGH_MEMORY;
1087 memset(*data, '\0', *out_size*sizeof(uint8));
1092 return ERROR_INVALID_PARAMETER;
1095 if (*needed > *out_size)
1096 return ERROR_MORE_DATA;
1098 return NT_STATUS_NO_PROBLEMO;
1102 /***************************************************************************
1103 connect to the client
1104 ****************************************************************************/
1105 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1110 * If it's the first connection, contact the client
1111 * and connect to the IPC$ share anonumously
1113 if (smb_connections==0) {
1114 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1116 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1122 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1128 /********************************************************************
1130 * ReplyFindFirstPrinterChangeNotifyEx
1132 * jfmxxxx: before replying OK: status=0
1133 * should do a rpc call to the workstation asking ReplyOpenPrinter
1134 * have to code it, later.
1136 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1137 * called from api_spoolss_rffpcnex
1138 ********************************************************************/
1139 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1140 const UNISTR2 *localmachine, uint32 printerlocal,
1141 SPOOL_NOTIFY_OPTION *option)
1143 /* store the notify value in the printer struct */
1145 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1147 if (!OPEN_HANDLE(Printer)) {
1148 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1149 return ERROR_INVALID_HANDLE;
1152 Printer->notify.flags=flags;
1153 Printer->notify.options=options;
1154 Printer->notify.printerlocal=printerlocal;
1155 Printer->notify.option=option;
1156 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1158 /* connect to the client machine and send a ReplyOpenPrinter */
1159 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1160 Printer->notify.printerlocal, 1,
1161 &Printer->notify.client_hnd))
1162 Printer->notify.client_connected=True;
1164 return NT_STATUS_NO_PROBLEMO;
1167 /*******************************************************************
1168 * fill a notify_info_data with the servername
1169 ********************************************************************/
1170 static void spoolss_notify_server_name(int snum,
1171 SPOOL_NOTIFY_INFO_DATA *data,
1172 print_queue_struct *queue,
1173 NT_PRINTER_INFO_LEVEL *printer,
1174 TALLOC_CTX *mem_ctx)
1176 pstring temp_name, temp;
1179 snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1181 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1183 data->notify_data.data.length = len / 2 - 1;
1184 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1186 if (!data->notify_data.data.string) {
1187 data->notify_data.data.length = 0;
1191 memcpy(data->notify_data.data.string, temp, len);
1194 /*******************************************************************
1195 * fill a notify_info_data with the printername (not including the servername).
1196 ********************************************************************/
1197 static void spoolss_notify_printer_name(int snum,
1198 SPOOL_NOTIFY_INFO_DATA *data,
1199 print_queue_struct *queue,
1200 NT_PRINTER_INFO_LEVEL *printer,
1201 TALLOC_CTX *mem_ctx)
1206 /* the notify name should not contain the \\server\ part */
1207 char *p = strrchr(printer->info_2->printername, '\\');
1210 p = printer->info_2->printername;
1215 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1217 data->notify_data.data.length = len / 2 - 1;
1218 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1220 if (!data->notify_data.data.string) {
1221 data->notify_data.data.length = 0;
1225 memcpy(data->notify_data.data.string, temp, len);
1228 /*******************************************************************
1229 * fill a notify_info_data with the servicename
1230 ********************************************************************/
1231 static void spoolss_notify_share_name(int snum,
1232 SPOOL_NOTIFY_INFO_DATA *data,
1233 print_queue_struct *queue,
1234 NT_PRINTER_INFO_LEVEL *printer,
1235 TALLOC_CTX *mem_ctx)
1240 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1241 sizeof(temp) - 2, True);
1243 data->notify_data.data.length = len / 2 - 1;
1244 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1246 if (!data->notify_data.data.string) {
1247 data->notify_data.data.length = 0;
1251 memcpy(data->notify_data.data.string, temp, len);
1254 /*******************************************************************
1255 * fill a notify_info_data with the port name
1256 ********************************************************************/
1257 static void spoolss_notify_port_name(int snum,
1258 SPOOL_NOTIFY_INFO_DATA *data,
1259 print_queue_struct *queue,
1260 NT_PRINTER_INFO_LEVEL *printer,
1261 TALLOC_CTX *mem_ctx)
1266 /* even if it's strange, that's consistant in all the code */
1268 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1269 sizeof(temp) - 2, True);
1271 data->notify_data.data.length = len / 2 - 1;
1272 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1274 if (!data->notify_data.data.string) {
1275 data->notify_data.data.length = 0;
1279 memcpy(data->notify_data.data.string, temp, len);
1282 /*******************************************************************
1283 * fill a notify_info_data with the printername
1284 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1285 * but it doesn't exist, have to see what to do
1286 ********************************************************************/
1287 static void spoolss_notify_driver_name(int snum,
1288 SPOOL_NOTIFY_INFO_DATA *data,
1289 print_queue_struct *queue,
1290 NT_PRINTER_INFO_LEVEL *printer,
1291 TALLOC_CTX *mem_ctx)
1296 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1297 sizeof(temp) - 2, True);
1299 data->notify_data.data.length = len / 2 - 1;
1300 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1302 if (!data->notify_data.data.string) {
1303 data->notify_data.data.length = 0;
1307 memcpy(data->notify_data.data.string, temp, len);
1310 /*******************************************************************
1311 * fill a notify_info_data with the comment
1312 ********************************************************************/
1313 static void spoolss_notify_comment(int snum,
1314 SPOOL_NOTIFY_INFO_DATA *data,
1315 print_queue_struct *queue,
1316 NT_PRINTER_INFO_LEVEL *printer,
1317 TALLOC_CTX *mem_ctx)
1322 if (*printer->info_2->comment == '\0')
1323 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1324 sizeof(temp) - 2, True);
1326 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1327 sizeof(temp) - 2, True);
1329 data->notify_data.data.length = len / 2 - 1;
1330 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1332 if (!data->notify_data.data.string) {
1333 data->notify_data.data.length = 0;
1337 memcpy(data->notify_data.data.string, temp, len);
1340 /*******************************************************************
1341 * fill a notify_info_data with the comment
1342 * jfm:xxxx incorrect, have to create a new smb.conf option
1343 * location = "Room 1, floor 2, building 3"
1344 ********************************************************************/
1345 static void spoolss_notify_location(int snum,
1346 SPOOL_NOTIFY_INFO_DATA *data,
1347 print_queue_struct *queue,
1348 NT_PRINTER_INFO_LEVEL *printer,
1349 TALLOC_CTX *mem_ctx)
1354 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1355 sizeof(temp) - 2, True);
1357 data->notify_data.data.length = len / 2 - 1;
1358 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1360 if (!data->notify_data.data.string) {
1361 data->notify_data.data.length = 0;
1365 memcpy(data->notify_data.data.string, temp, len);
1368 /*******************************************************************
1369 * fill a notify_info_data with the device mode
1370 * jfm:xxxx don't to it for know but that's a real problem !!!
1371 ********************************************************************/
1372 static void spoolss_notify_devmode(int snum,
1373 SPOOL_NOTIFY_INFO_DATA *data,
1374 print_queue_struct *queue,
1375 NT_PRINTER_INFO_LEVEL *printer,
1376 TALLOC_CTX *mem_ctx)
1380 /*******************************************************************
1381 * fill a notify_info_data with the separator file name
1382 * jfm:xxxx just return no file could add an option to smb.conf
1383 * separator file = "separator.txt"
1384 ********************************************************************/
1385 static void spoolss_notify_sepfile(int snum,
1386 SPOOL_NOTIFY_INFO_DATA *data,
1387 print_queue_struct *queue,
1388 NT_PRINTER_INFO_LEVEL *printer,
1389 TALLOC_CTX *mem_ctx)
1394 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1395 sizeof(temp) - 2, True);
1397 data->notify_data.data.length = len / 2 - 1;
1398 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1400 if (!data->notify_data.data.string) {
1401 data->notify_data.data.length = 0;
1405 memcpy(data->notify_data.data.string, temp, len);
1408 /*******************************************************************
1409 * fill a notify_info_data with the print processor
1410 * jfm:xxxx return always winprint to indicate we don't do anything to it
1411 ********************************************************************/
1412 static void spoolss_notify_print_processor(int snum,
1413 SPOOL_NOTIFY_INFO_DATA *data,
1414 print_queue_struct *queue,
1415 NT_PRINTER_INFO_LEVEL *printer,
1416 TALLOC_CTX *mem_ctx)
1421 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
1422 sizeof(temp) - 2, True);
1424 data->notify_data.data.length = len / 2 - 1;
1425 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1427 if (!data->notify_data.data.string) {
1428 data->notify_data.data.length = 0;
1432 memcpy(data->notify_data.data.string, temp, len);
1435 /*******************************************************************
1436 * fill a notify_info_data with the print processor options
1437 * jfm:xxxx send an empty string
1438 ********************************************************************/
1439 static void spoolss_notify_parameters(int snum,
1440 SPOOL_NOTIFY_INFO_DATA *data,
1441 print_queue_struct *queue,
1442 NT_PRINTER_INFO_LEVEL *printer,
1443 TALLOC_CTX *mem_ctx)
1448 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1449 sizeof(temp) - 2, True);
1451 data->notify_data.data.length = len / 2 - 1;
1452 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1454 if (!data->notify_data.data.string) {
1455 data->notify_data.data.length = 0;
1459 memcpy(data->notify_data.data.string, temp, len);
1462 /*******************************************************************
1463 * fill a notify_info_data with the data type
1464 * jfm:xxxx always send RAW as data type
1465 ********************************************************************/
1466 static void spoolss_notify_datatype(int snum,
1467 SPOOL_NOTIFY_INFO_DATA *data,
1468 print_queue_struct *queue,
1469 NT_PRINTER_INFO_LEVEL *printer,
1470 TALLOC_CTX *mem_ctx)
1475 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1476 sizeof(pstring) - 2, True);
1478 data->notify_data.data.length = len / 2 - 1;
1479 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1481 if (!data->notify_data.data.string) {
1482 data->notify_data.data.length = 0;
1486 memcpy(data->notify_data.data.string, temp, len);
1489 /*******************************************************************
1490 * fill a notify_info_data with the security descriptor
1491 * jfm:xxxx send an null pointer to say no security desc
1492 * have to implement security before !
1493 ********************************************************************/
1494 static void spoolss_notify_security_desc(int snum,
1495 SPOOL_NOTIFY_INFO_DATA *data,
1496 print_queue_struct *queue,
1497 NT_PRINTER_INFO_LEVEL *printer,
1498 TALLOC_CTX *mem_ctx)
1500 data->notify_data.data.length=0;
1501 data->notify_data.data.string = NULL;
1504 /*******************************************************************
1505 * fill a notify_info_data with the attributes
1506 * jfm:xxxx a samba printer is always shared
1507 ********************************************************************/
1508 static void spoolss_notify_attributes(int snum,
1509 SPOOL_NOTIFY_INFO_DATA *data,
1510 print_queue_struct *queue,
1511 NT_PRINTER_INFO_LEVEL *printer,
1512 TALLOC_CTX *mem_ctx)
1514 data->notify_data.value[0] = printer->info_2->attributes;
1517 /*******************************************************************
1518 * fill a notify_info_data with the priority
1519 ********************************************************************/
1520 static void spoolss_notify_priority(int snum,
1521 SPOOL_NOTIFY_INFO_DATA *data,
1522 print_queue_struct *queue,
1523 NT_PRINTER_INFO_LEVEL *printer,
1524 TALLOC_CTX *mem_ctx)
1526 data->notify_data.value[0] = printer->info_2->priority;
1529 /*******************************************************************
1530 * fill a notify_info_data with the default priority
1531 ********************************************************************/
1532 static void spoolss_notify_default_priority(int snum,
1533 SPOOL_NOTIFY_INFO_DATA *data,
1534 print_queue_struct *queue,
1535 NT_PRINTER_INFO_LEVEL *printer,
1536 TALLOC_CTX *mem_ctx)
1538 data->notify_data.value[0] = printer->info_2->default_priority;
1541 /*******************************************************************
1542 * fill a notify_info_data with the start time
1543 ********************************************************************/
1544 static void spoolss_notify_start_time(int snum,
1545 SPOOL_NOTIFY_INFO_DATA *data,
1546 print_queue_struct *queue,
1547 NT_PRINTER_INFO_LEVEL *printer,
1548 TALLOC_CTX *mem_ctx)
1550 data->notify_data.value[0] = printer->info_2->starttime;
1553 /*******************************************************************
1554 * fill a notify_info_data with the until time
1555 ********************************************************************/
1556 static void spoolss_notify_until_time(int snum,
1557 SPOOL_NOTIFY_INFO_DATA *data,
1558 print_queue_struct *queue,
1559 NT_PRINTER_INFO_LEVEL *printer,
1560 TALLOC_CTX *mem_ctx)
1562 data->notify_data.value[0] = printer->info_2->untiltime;
1565 /*******************************************************************
1566 * fill a notify_info_data with the status
1567 ********************************************************************/
1568 static void spoolss_notify_status(int snum,
1569 SPOOL_NOTIFY_INFO_DATA *data,
1570 print_queue_struct *queue,
1571 NT_PRINTER_INFO_LEVEL *printer,
1572 TALLOC_CTX *mem_ctx)
1576 print_queue_struct *q=NULL;
1577 print_status_struct status;
1579 memset(&status, 0, sizeof(status));
1580 count = print_queue_status(snum, &q, &status);
1581 data->notify_data.value[0]=(uint32) status.status;
1585 /*******************************************************************
1586 * fill a notify_info_data with the number of jobs queued
1587 ********************************************************************/
1588 static void spoolss_notify_cjobs(int snum,
1589 SPOOL_NOTIFY_INFO_DATA *data,
1590 print_queue_struct *queue,
1591 NT_PRINTER_INFO_LEVEL *printer,
1592 TALLOC_CTX *mem_ctx)
1594 print_queue_struct *q=NULL;
1595 print_status_struct status;
1597 memset(&status, 0, sizeof(status));
1598 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1602 /*******************************************************************
1603 * fill a notify_info_data with the average ppm
1604 ********************************************************************/
1605 static void spoolss_notify_average_ppm(int snum,
1606 SPOOL_NOTIFY_INFO_DATA *data,
1607 print_queue_struct *queue,
1608 NT_PRINTER_INFO_LEVEL *printer,
1609 TALLOC_CTX *mem_ctx)
1611 /* always respond 8 pages per minutes */
1612 /* a little hard ! */
1613 data->notify_data.value[0] = printer->info_2->averageppm;
1616 /*******************************************************************
1617 * fill a notify_info_data with username
1618 ********************************************************************/
1619 static void spoolss_notify_username(int snum,
1620 SPOOL_NOTIFY_INFO_DATA *data,
1621 print_queue_struct *queue,
1622 NT_PRINTER_INFO_LEVEL *printer,
1623 TALLOC_CTX *mem_ctx)
1628 len = (uint32)dos_PutUniCode(temp, queue->user,
1629 sizeof(temp) - 2, True);
1631 data->notify_data.data.length = len / 2 - 1;
1632 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1634 if (!data->notify_data.data.string) {
1635 data->notify_data.data.length = 0;
1639 memcpy(data->notify_data.data.string, temp, len);
1642 /*******************************************************************
1643 * fill a notify_info_data with job status
1644 ********************************************************************/
1645 static void spoolss_notify_job_status(int snum,
1646 SPOOL_NOTIFY_INFO_DATA *data,
1647 print_queue_struct *queue,
1648 NT_PRINTER_INFO_LEVEL *printer,
1649 TALLOC_CTX *mem_ctx)
1651 data->notify_data.value[0]=nt_printj_status(queue->status);
1654 /*******************************************************************
1655 * fill a notify_info_data with job name
1656 ********************************************************************/
1657 static void spoolss_notify_job_name(int snum,
1658 SPOOL_NOTIFY_INFO_DATA *data,
1659 print_queue_struct *queue,
1660 NT_PRINTER_INFO_LEVEL *printer,
1661 TALLOC_CTX *mem_ctx)
1666 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1669 data->notify_data.data.length = len / 2 - 1;
1670 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1672 if (!data->notify_data.data.string) {
1673 data->notify_data.data.length = 0;
1677 memcpy(data->notify_data.data.string, temp, len);
1680 /*******************************************************************
1681 * fill a notify_info_data with job status
1682 ********************************************************************/
1683 static void spoolss_notify_job_status_string(int snum,
1684 SPOOL_NOTIFY_INFO_DATA *data,
1685 print_queue_struct *queue,
1686 NT_PRINTER_INFO_LEVEL *printer,
1687 TALLOC_CTX *mem_ctx)
1689 char *p = "unknown";
1693 switch (queue->status) {
1698 p = ""; /* NT provides the paused string */
1708 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1710 data->notify_data.data.length = len / 2 - 1;
1711 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1713 if (!data->notify_data.data.string) {
1714 data->notify_data.data.length = 0;
1718 memcpy(data->notify_data.data.string, temp, len);
1721 /*******************************************************************
1722 * fill a notify_info_data with job time
1723 ********************************************************************/
1724 static void spoolss_notify_job_time(int snum,
1725 SPOOL_NOTIFY_INFO_DATA *data,
1726 print_queue_struct *queue,
1727 NT_PRINTER_INFO_LEVEL *printer,
1728 TALLOC_CTX *mem_ctx)
1730 data->notify_data.value[0]=0x0;
1733 /*******************************************************************
1734 * fill a notify_info_data with job size
1735 ********************************************************************/
1736 static void spoolss_notify_job_size(int snum,
1737 SPOOL_NOTIFY_INFO_DATA *data,
1738 print_queue_struct *queue,
1739 NT_PRINTER_INFO_LEVEL *printer,
1740 TALLOC_CTX *mem_ctx)
1742 data->notify_data.value[0]=queue->size;
1745 /*******************************************************************
1746 * fill a notify_info_data with job position
1747 ********************************************************************/
1748 static void spoolss_notify_job_position(int snum,
1749 SPOOL_NOTIFY_INFO_DATA *data,
1750 print_queue_struct *queue,
1751 NT_PRINTER_INFO_LEVEL *printer,
1752 TALLOC_CTX *mem_ctx)
1754 data->notify_data.value[0]=queue->job;
1757 /*******************************************************************
1758 * fill a notify_info_data with submitted time
1759 ********************************************************************/
1760 static void spoolss_notify_submitted_time(int snum,
1761 SPOOL_NOTIFY_INFO_DATA *data,
1762 print_queue_struct *queue,
1763 NT_PRINTER_INFO_LEVEL *printer,
1764 TALLOC_CTX *mem_ctx)
1769 t=gmtime(&queue->time);
1771 len = sizeof(SYSTEMTIME);
1773 data->notify_data.data.length = len;
1774 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1776 if (!data->notify_data.data.string) {
1777 data->notify_data.data.length = 0;
1781 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1786 struct s_notify_info_data_table
1792 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1793 print_queue_struct *queue,
1794 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
1797 struct s_notify_info_data_table notify_info_data_table[] =
1799 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1800 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1801 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1802 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1803 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1804 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1805 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1806 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1807 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1808 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1809 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1810 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1811 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1812 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1813 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1814 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1815 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1816 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1817 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1818 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1819 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1820 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1821 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1822 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1823 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1824 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1825 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1826 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1827 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1828 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1829 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1830 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1831 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1832 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1833 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1834 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1835 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1836 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1837 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1838 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1839 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1840 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1841 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1842 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1843 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1844 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1845 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1846 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1847 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1848 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1849 { END, END, "", END, NULL }
1852 /*******************************************************************
1853 return the size of info_data structure
1854 ********************************************************************/
1855 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1859 while (notify_info_data_table[i].type != END)
1861 if ( (notify_info_data_table[i].type == type ) &&
1862 (notify_info_data_table[i].field == field ) )
1864 return (notify_info_data_table[i].size);
1871 /*******************************************************************
1872 return the type of notify_info_data
1873 ********************************************************************/
1874 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1878 while (notify_info_data_table[i].type != END)
1880 if ( (notify_info_data_table[i].type == type ) &&
1881 (notify_info_data_table[i].field == field ) )
1883 if (notify_info_data_table[i].size == POINTER)
1897 /****************************************************************************
1898 ****************************************************************************/
1899 static int search_notify(uint16 type, uint16 field, int *value)
1904 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1906 if ( (notify_info_data_table[j].type == type ) &&
1907 (notify_info_data_table[j].field == field ) )
1912 if ( found && (notify_info_data_table[j].fn != NULL) )
1918 /****************************************************************************
1919 ****************************************************************************/
1920 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1922 info_data->type = type;
1923 info_data->field = field;
1924 info_data->reserved = 0;
1926 info_data->size = size_of_notify_info_data(type, field);
1927 info_data->enc_type = type_of_notify_info_data(type, field);
1931 /*******************************************************************
1933 * fill a notify_info struct with info asked
1935 ********************************************************************/
1936 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
1937 snum, SPOOL_NOTIFY_OPTION_TYPE
1938 *option_type, uint32 id,
1939 TALLOC_CTX *mem_ctx)
1945 SPOOL_NOTIFY_INFO_DATA *current_data;
1946 NT_PRINTER_INFO_LEVEL *printer = NULL;
1947 print_queue_struct *queue=NULL;
1949 type=option_type->type;
1951 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1952 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1953 option_type->count, lp_servicename(snum)));
1955 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1958 for(field_num=0; field_num<option_type->count; field_num++) {
1959 field = option_type->fields[field_num];
1960 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1962 if (!search_notify(type, field, &j) )
1965 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1968 current_data=&info->data[info->count];
1970 construct_info_data(current_data, type, field, id);
1972 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
1973 notify_info_data_table[j].name, snum, printer->info_2->printername ));
1975 notify_info_data_table[j].fn(snum, current_data, queue,
1981 free_a_printer(&printer, 2);
1985 /*******************************************************************
1987 * fill a notify_info struct with info asked
1989 ********************************************************************/
1990 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
1991 SPOOL_NOTIFY_INFO *info,
1992 NT_PRINTER_INFO_LEVEL *printer,
1993 int snum, SPOOL_NOTIFY_OPTION_TYPE
1994 *option_type, uint32 id,
1995 TALLOC_CTX *mem_ctx)
2001 SPOOL_NOTIFY_INFO_DATA *current_data;
2003 DEBUG(4,("construct_notify_jobs_info\n"));
2005 type = option_type->type;
2007 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2008 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2009 option_type->count));
2011 for(field_num=0; field_num<option_type->count; field_num++) {
2012 field = option_type->fields[field_num];
2014 if (!search_notify(type, field, &j) )
2017 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2021 current_data=&(info->data[info->count]);
2023 construct_info_data(current_data, type, field, id);
2024 notify_info_data_table[j].fn(snum, current_data, queue,
2033 * JFM: The enumeration is not that simple, it's even non obvious.
2035 * let's take an example: I want to monitor the PRINTER SERVER for
2036 * the printer's name and the number of jobs currently queued.
2037 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2038 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2040 * I have 3 printers on the back of my server.
2042 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2045 * 1 printer 1 name 1
2046 * 2 printer 1 cjob 1
2047 * 3 printer 2 name 2
2048 * 4 printer 2 cjob 2
2049 * 5 printer 3 name 3
2050 * 6 printer 3 name 3
2052 * that's the print server case, the printer case is even worse.
2057 /*******************************************************************
2059 * enumerate all printers on the printserver
2060 * fill a notify_info struct with info asked
2062 ********************************************************************/
2063 static uint32 printserver_notify_info(const POLICY_HND *hnd,
2064 SPOOL_NOTIFY_INFO *info,
2065 TALLOC_CTX *mem_ctx)
2068 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2069 int n_services=lp_numservices();
2072 SPOOL_NOTIFY_OPTION *option;
2073 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2075 DEBUG(4,("printserver_notify_info\n"));
2077 option=Printer->notify.option;
2083 for (i=0; i<option->count; i++) {
2084 option_type=&(option->ctr.type[i]);
2086 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2089 for (snum=0; snum<n_services; snum++)
2090 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2091 if (construct_notify_printer_info
2092 (info, snum, option_type, id, mem_ctx))
2097 * Debugging information, don't delete.
2100 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2101 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2102 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2104 for (i=0; i<info->count; i++) {
2105 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2106 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2107 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2111 return NT_STATUS_NO_PROBLEMO;
2114 /*******************************************************************
2116 * fill a notify_info struct with info asked
2118 ********************************************************************/
2119 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2120 TALLOC_CTX *mem_ctx)
2123 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2126 SPOOL_NOTIFY_OPTION *option;
2127 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2129 print_queue_struct *queue=NULL;
2130 print_status_struct status;
2132 DEBUG(4,("printer_notify_info\n"));
2134 option=Printer->notify.option;
2140 get_printer_snum(hnd, &snum);
2142 for (i=0; i<option->count; i++) {
2143 option_type=&option->ctr.type[i];
2145 switch ( option_type->type ) {
2146 case PRINTER_NOTIFY_TYPE:
2147 if(construct_notify_printer_info(info, snum,
2153 case JOB_NOTIFY_TYPE: {
2154 NT_PRINTER_INFO_LEVEL *printer = NULL;
2156 memset(&status, 0, sizeof(status));
2157 count = print_queue_status(snum, &queue, &status);
2159 if (get_a_printer(&printer, 2,
2160 lp_servicename(snum)) != 0)
2163 for (j=0; j<count; j++) {
2164 construct_notify_jobs_info(&queue[j], info,
2171 free_a_printer(&printer, 2);
2181 * Debugging information, don't delete.
2184 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2185 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2186 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2188 for (i=0; i<info->count; i++) {
2189 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2190 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2191 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2194 return NT_STATUS_NO_PROBLEMO;
2197 /********************************************************************
2199 ********************************************************************/
2200 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
2201 SPOOL_NOTIFY_OPTION *option, TALLOC_CTX *mem_ctx,
2202 SPOOL_NOTIFY_INFO *info)
2204 Printer_entry *Printer=find_printer_index_by_hnd(handle);
2205 uint32 result = ERROR_INVALID_HANDLE;
2207 if (!OPEN_HANDLE(Printer)) {
2208 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2209 OUR_HANDLE(handle)));
2213 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2215 /* jfm: the change value isn't used right now.
2216 * we will honour it when
2217 * a) we'll be able to send notification to the client
2218 * b) we'll have a way to communicate between the spoolss process.
2220 * same thing for option->flags
2221 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2222 * I don't have a global notification system, I'm sending back all the
2223 * informations even when _NOTHING_ has changed.
2226 /* just discard the SPOOL_NOTIFY_OPTION */
2228 safe_free(option->ctr.type);
2230 switch (Printer->printer_type) {
2231 case PRINTER_HANDLE_IS_PRINTSERVER:
2232 result = printserver_notify_info(handle, info,
2236 case PRINTER_HANDLE_IS_PRINTER:
2237 result = printer_notify_info(handle, info, mem_ctx);
2245 /********************************************************************
2246 * construct_printer_info_0
2247 * fill a printer_info_0 struct
2248 ********************************************************************/
2249 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2253 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2254 counter_printer_0 *session_counter;
2255 uint32 global_counter;
2259 print_queue_struct *queue=NULL;
2260 print_status_struct status;
2262 memset(&status, 0, sizeof(status));
2264 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2267 count = print_queue_status(snum, &queue, &status);
2269 /* check if we already have a counter for this printer */
2270 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2272 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2273 if (session_counter->snum == snum)
2277 /* it's the first time, add it to the list */
2278 if (session_counter==NULL) {
2279 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2280 free_a_printer(&ntprinter, 2);
2283 ZERO_STRUCTP(session_counter);
2284 session_counter->snum=snum;
2285 session_counter->counter=0;
2286 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2290 session_counter->counter++;
2293 * the global_counter should be stored in a TDB as it's common to all the clients
2294 * and should be zeroed on samba startup
2296 global_counter=session_counter->counter;
2298 pstrcpy(chaine,ntprinter->info_2->printername);
2300 init_unistr(&printer->printername, chaine);
2302 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2303 init_unistr(&printer->servername, chaine);
2305 printer->cjobs = count;
2306 printer->total_jobs = 0;
2307 printer->total_bytes = 0;
2309 setuptime = (time_t)ntprinter->info_2->setuptime;
2310 t=gmtime(&setuptime);
2312 printer->year = t->tm_year+1900;
2313 printer->month = t->tm_mon+1;
2314 printer->dayofweek = t->tm_wday;
2315 printer->day = t->tm_mday;
2316 printer->hour = t->tm_hour;
2317 printer->minute = t->tm_min;
2318 printer->second = t->tm_sec;
2319 printer->milliseconds = 0;
2321 printer->global_counter = global_counter;
2322 printer->total_pages = 0;
2323 printer->major_version = 0x0004; /* NT 4 */
2324 printer->build_version = 0x0565; /* build 1381 */
2325 printer->unknown7 = 0x1;
2326 printer->unknown8 = 0x0;
2327 printer->unknown9 = 0x0;
2328 printer->session_counter = session_counter->counter;
2329 printer->unknown11 = 0x0;
2330 printer->printer_errors = 0x0; /* number of print failure */
2331 printer->unknown13 = 0x0;
2332 printer->unknown14 = 0x1;
2333 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2334 printer->unknown16 = 0x0;
2335 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2336 printer->unknown18 = 0x0;
2337 printer->status = nt_printq_status(status.status);
2338 printer->unknown20 = 0x0;
2339 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2340 printer->unknown22 = 0x0;
2341 printer->unknown23 = 0x6; /* 6 ???*/
2342 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2343 printer->unknown25 = 0;
2344 printer->unknown26 = 0;
2345 printer->unknown27 = 0;
2346 printer->unknown28 = 0;
2347 printer->unknown29 = 0;
2350 free_a_printer(&ntprinter,2);
2354 /********************************************************************
2355 * construct_printer_info_1
2356 * fill a printer_info_1 struct
2357 ********************************************************************/
2358 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2362 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2364 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2367 printer->flags=flags;
2369 if (*ntprinter->info_2->comment == '\0') {
2370 init_unistr(&printer->comment, lp_comment(snum));
2371 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2372 ntprinter->info_2->drivername, lp_comment(snum));
2375 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2376 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2377 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2380 snprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2382 init_unistr(&printer->description, chaine);
2383 init_unistr(&printer->name, chaine2);
2385 free_a_printer(&ntprinter,2);
2390 /****************************************************************************
2391 Free a DEVMODE struct.
2392 ****************************************************************************/
2394 static void free_dev_mode(DEVICEMODE *dev)
2400 safe_free(dev->private);
2405 /****************************************************************************
2406 Create a DEVMODE struct. Returns malloced memory.
2407 ****************************************************************************/
2409 static DEVICEMODE *construct_dev_mode(int snum)
2413 NT_PRINTER_INFO_LEVEL *printer = NULL;
2414 NT_DEVICEMODE *ntdevmode = NULL;
2415 DEVICEMODE *devmode = NULL;
2417 DEBUG(7,("construct_dev_mode\n"));
2419 DEBUGADD(8,("getting printer characteristics\n"));
2421 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2422 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2426 ZERO_STRUCTP(devmode);
2428 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2431 if (printer->info_2->devmode)
2432 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2434 if (ntdevmode == NULL)
2437 DEBUGADD(8,("loading DEVICEMODE\n"));
2439 snprintf(adevice, sizeof(adevice), printer->info_2->printername);
2440 init_unistr(&devmode->devicename, adevice);
2442 snprintf(aform, sizeof(aform), ntdevmode->formname);
2443 init_unistr(&devmode->formname, aform);
2445 devmode->specversion = ntdevmode->specversion;
2446 devmode->driverversion = ntdevmode->driverversion;
2447 devmode->size = ntdevmode->size;
2448 devmode->driverextra = ntdevmode->driverextra;
2449 devmode->fields = ntdevmode->fields;
2451 devmode->orientation = ntdevmode->orientation;
2452 devmode->papersize = ntdevmode->papersize;
2453 devmode->paperlength = ntdevmode->paperlength;
2454 devmode->paperwidth = ntdevmode->paperwidth;
2455 devmode->scale = ntdevmode->scale;
2456 devmode->copies = ntdevmode->copies;
2457 devmode->defaultsource = ntdevmode->defaultsource;
2458 devmode->printquality = ntdevmode->printquality;
2459 devmode->color = ntdevmode->color;
2460 devmode->duplex = ntdevmode->duplex;
2461 devmode->yresolution = ntdevmode->yresolution;
2462 devmode->ttoption = ntdevmode->ttoption;
2463 devmode->collate = ntdevmode->collate;
2464 devmode->icmmethod = ntdevmode->icmmethod;
2465 devmode->icmintent = ntdevmode->icmintent;
2466 devmode->mediatype = ntdevmode->mediatype;
2467 devmode->dithertype = ntdevmode->dithertype;
2469 if (ntdevmode->private != NULL) {
2470 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2474 free_nt_devicemode(&ntdevmode);
2475 free_a_printer(&printer,2);
2482 free_nt_devicemode(&ntdevmode);
2484 free_a_printer(&printer,2);
2485 free_dev_mode(devmode);
2490 /********************************************************************
2491 * construct_printer_info_2
2492 * fill a printer_info_2 struct
2493 ********************************************************************/
2495 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2498 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2500 print_queue_struct *queue=NULL;
2501 print_status_struct status;
2502 memset(&status, 0, sizeof(status));
2504 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2507 memset(&status, 0, sizeof(status));
2508 count = print_queue_status(snum, &queue, &status);
2510 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2511 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2512 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2513 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2514 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2516 if (*ntprinter->info_2->comment == '\0')
2517 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2519 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2521 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2522 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2523 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2524 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2525 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2527 printer->attributes = ntprinter->info_2->attributes;
2529 printer->priority = ntprinter->info_2->priority; /* priority */
2530 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2531 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2532 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2533 printer->status = nt_printq_status(status.status); /* status */
2534 printer->cjobs = count; /* jobs */
2535 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2537 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2538 DEBUG(8, ("Returning NULL Devicemode!\n"));
2541 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2542 /* steal the printer info sec_desc structure. [badly done]. */
2543 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2544 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2545 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2546 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2549 printer->secdesc = NULL;
2552 free_a_printer(&ntprinter, 2);
2557 /********************************************************************
2558 * construct_printer_info_3
2559 * fill a printer_info_3 struct
2560 ********************************************************************/
2561 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2563 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2564 PRINTER_INFO_3 *printer = NULL;
2566 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2570 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2571 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2575 ZERO_STRUCTP(printer);
2577 printer->flags = 4; /* These are the components of the SD we are returning. */
2578 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2579 /* steal the printer info sec_desc structure. [badly done]. */
2580 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2584 * Set the flags for the components we are returning.
2587 if (printer->secdesc->owner_sid)
2588 printer->flags |= OWNER_SECURITY_INFORMATION;
2590 if (printer->secdesc->grp_sid)
2591 printer->flags |= GROUP_SECURITY_INFORMATION;
2593 if (printer->secdesc->dacl)
2594 printer->flags |= DACL_SECURITY_INFORMATION;
2596 if (printer->secdesc->sacl)
2597 printer->flags |= SACL_SECURITY_INFORMATION;
2600 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2601 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2602 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2605 free_a_printer(&ntprinter, 2);
2607 *pp_printer = printer;
2611 /********************************************************************
2612 Spoolss_enumprinters.
2613 ********************************************************************/
2614 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2618 int n_services=lp_numservices();
2619 PRINTER_INFO_1 *printers=NULL;
2620 PRINTER_INFO_1 current_prt;
2622 DEBUG(4,("enum_all_printers_info_1\n"));
2624 for (snum=0; snum<n_services; snum++) {
2625 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2626 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2628 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2629 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2631 return ERROR_NOT_ENOUGH_MEMORY;
2633 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2634 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2640 /* check the required size. */
2641 for (i=0; i<*returned; i++)
2642 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2644 if (!alloc_buffer_size(buffer, *needed))
2645 return ERROR_INSUFFICIENT_BUFFER;
2647 /* fill the buffer with the structures */
2648 for (i=0; i<*returned; i++)
2649 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2652 safe_free(printers);
2654 if (*needed > offered) {
2656 return ERROR_INSUFFICIENT_BUFFER;
2659 return NT_STATUS_NO_PROBLEMO;
2662 /********************************************************************
2663 enum_all_printers_info_1_local.
2664 *********************************************************************/
2665 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2667 DEBUG(4,("enum_all_printers_info_1_local\n"));
2669 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2672 /********************************************************************
2673 enum_all_printers_info_1_name.
2674 *********************************************************************/
2675 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2678 DEBUG(4,("enum_all_printers_info_1_name\n"));
2680 fstrcpy(temp, "\\\\");
2681 fstrcat(temp, global_myname);
2683 if (strequal(name, temp)) {
2684 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2687 return ERROR_INVALID_NAME;
2690 /********************************************************************
2691 enum_all_printers_info_1_remote.
2692 *********************************************************************/
2693 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2695 PRINTER_INFO_1 *printer;
2696 fstring printername;
2699 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2701 /* JFM: currently it's more a place holder than anything else.
2702 * In the spooler world there is a notion of server registration.
2703 * the print servers are registring (sp ?) on the PDC (in the same domain)
2705 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2708 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2709 return ERROR_NOT_ENOUGH_MEMORY;
2713 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2714 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2715 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2717 init_unistr(&printer->description, desc);
2718 init_unistr(&printer->name, printername);
2719 init_unistr(&printer->comment, comment);
2720 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2722 /* check the required size. */
2723 *needed += spoolss_size_printer_info_1(printer);
2725 if (!alloc_buffer_size(buffer, *needed)) {
2727 return ERROR_INSUFFICIENT_BUFFER;
2730 /* fill the buffer with the structures */
2731 new_smb_io_printer_info_1("", buffer, printer, 0);
2736 if (*needed > offered) {
2738 return ERROR_INSUFFICIENT_BUFFER;
2741 return NT_STATUS_NO_PROBLEMO;
2744 /********************************************************************
2745 enum_all_printers_info_1_network.
2746 *********************************************************************/
2747 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2749 DEBUG(4,("enum_all_printers_info_1_network\n"));
2751 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2754 /********************************************************************
2755 * api_spoolss_enumprinters
2757 * called from api_spoolss_enumprinters (see this to understand)
2758 ********************************************************************/
2759 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2763 int n_services=lp_numservices();
2764 PRINTER_INFO_2 *printers=NULL;
2765 PRINTER_INFO_2 current_prt;
2767 for (snum=0; snum<n_services; snum++) {
2768 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2769 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2771 if (construct_printer_info_2(¤t_prt, snum)) {
2772 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2773 return ERROR_NOT_ENOUGH_MEMORY;
2774 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2775 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2781 /* check the required size. */
2782 for (i=0; i<*returned; i++)
2783 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2785 if (!alloc_buffer_size(buffer, *needed)) {
2786 for (i=0; i<*returned; i++) {
2787 free_devmode(printers[i].devmode);
2788 free_sec_desc(&printers[i].secdesc);
2790 safe_free(printers);
2791 return ERROR_INSUFFICIENT_BUFFER;
2794 /* fill the buffer with the structures */
2795 for (i=0; i<*returned; i++)
2796 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2799 for (i=0; i<*returned; i++) {
2800 free_devmode(printers[i].devmode);
2801 free_sec_desc(&printers[i].secdesc);
2803 safe_free(printers);
2805 if (*needed > offered) {
2807 return ERROR_INSUFFICIENT_BUFFER;
2810 return NT_STATUS_NO_PROBLEMO;
2813 /********************************************************************
2814 * handle enumeration of printers at level 1
2815 ********************************************************************/
2816 static uint32 enumprinters_level1( uint32 flags, fstring name,
2817 NEW_BUFFER *buffer, uint32 offered,
2818 uint32 *needed, uint32 *returned)
2820 /* Not all the flags are equals */
2822 if (flags & PRINTER_ENUM_LOCAL)
2823 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2825 if (flags & PRINTER_ENUM_NAME)
2826 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2828 if (flags & PRINTER_ENUM_REMOTE)
2829 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2831 if (flags & PRINTER_ENUM_NETWORK)
2832 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
2834 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2837 /********************************************************************
2838 * handle enumeration of printers at level 2
2839 ********************************************************************/
2840 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2841 NEW_BUFFER *buffer, uint32 offered,
2842 uint32 *needed, uint32 *returned)
2846 fstrcpy(temp, "\\\\");
2847 fstrcat(temp, global_myname);
2849 if (flags & PRINTER_ENUM_LOCAL) {
2850 if (strequal(servername, temp))
2851 return enum_all_printers_info_2(buffer, offered, needed, returned);
2853 return enum_all_printers_info_2(buffer, offered, needed, returned);
2856 if (flags & PRINTER_ENUM_NAME) {
2857 if (strequal(servername, temp))
2858 return enum_all_printers_info_2(buffer, offered, needed, returned);
2860 return ERROR_INVALID_NAME;
2863 if (flags & PRINTER_ENUM_REMOTE)
2864 return ERROR_INVALID_LEVEL;
2866 return NT_STATUS_NO_PROBLEMO;
2869 /********************************************************************
2870 * handle enumeration of printers at level 5
2871 ********************************************************************/
2872 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2873 NEW_BUFFER *buffer, uint32 offered,
2874 uint32 *needed, uint32 *returned)
2876 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2877 return NT_STATUS_NO_PROBLEMO;
2880 /********************************************************************
2881 * api_spoolss_enumprinters
2883 * called from api_spoolss_enumprinters (see this to understand)
2884 ********************************************************************/
2885 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2886 NEW_BUFFER *buffer, uint32 offered,
2887 uint32 *needed, uint32 *returned)
2891 DEBUG(4,("_spoolss_enumprinters\n"));
2898 * flags==PRINTER_ENUM_NAME
2899 * if name=="" then enumerates all printers
2900 * if name!="" then enumerate the printer
2901 * flags==PRINTER_ENUM_REMOTE
2902 * name is NULL, enumerate printers
2903 * Level 2: name!="" enumerates printers, name can't be NULL
2904 * Level 3: doesn't exist
2905 * Level 4: does a local registry lookup
2906 * Level 5: same as Level 2
2909 unistr2_to_ascii(name, servername, sizeof(name)-1);
2914 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2916 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2918 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2922 return ERROR_INVALID_LEVEL;
2926 /****************************************************************************
2927 ****************************************************************************/
2928 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2930 PRINTER_INFO_0 *printer=NULL;
2932 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2933 return ERROR_NOT_ENOUGH_MEMORY;
2935 construct_printer_info_0(printer, snum);
2937 /* check the required size. */
2938 *needed += spoolss_size_printer_info_0(printer);
2940 if (!alloc_buffer_size(buffer, *needed)) {
2942 return ERROR_INSUFFICIENT_BUFFER;
2945 /* fill the buffer with the structures */
2946 new_smb_io_printer_info_0("", buffer, printer, 0);
2951 if (*needed > offered) {
2952 return ERROR_INSUFFICIENT_BUFFER;
2955 return NT_STATUS_NO_PROBLEMO;
2958 /****************************************************************************
2959 ****************************************************************************/
2960 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2962 PRINTER_INFO_1 *printer=NULL;
2964 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2965 return ERROR_NOT_ENOUGH_MEMORY;
2967 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
2969 /* check the required size. */
2970 *needed += spoolss_size_printer_info_1(printer);
2972 if (!alloc_buffer_size(buffer, *needed)) {
2974 return ERROR_INSUFFICIENT_BUFFER;
2977 /* fill the buffer with the structures */
2978 new_smb_io_printer_info_1("", buffer, printer, 0);
2983 if (*needed > offered) {
2984 return ERROR_INSUFFICIENT_BUFFER;
2987 return NT_STATUS_NO_PROBLEMO;
2990 /****************************************************************************
2991 ****************************************************************************/
2992 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2994 PRINTER_INFO_2 *printer=NULL;
2996 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2997 return ERROR_NOT_ENOUGH_MEMORY;
2999 construct_printer_info_2(printer, snum);
3001 /* check the required size. */
3002 *needed += spoolss_size_printer_info_2(printer);
3004 if (!alloc_buffer_size(buffer, *needed)) {
3005 free_printer_info_2(printer);
3006 return ERROR_INSUFFICIENT_BUFFER;
3009 /* fill the buffer with the structures */
3010 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
3011 free_printer_info_2(printer);
3012 return ERROR_NOT_ENOUGH_MEMORY;
3016 free_printer_info_2(printer);
3018 if (*needed > offered) {
3019 return ERROR_INSUFFICIENT_BUFFER;
3022 return NT_STATUS_NO_PROBLEMO;
3025 /****************************************************************************
3026 ****************************************************************************/
3027 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3029 PRINTER_INFO_3 *printer=NULL;
3031 if (!construct_printer_info_3(&printer, snum))
3032 return ERROR_NOT_ENOUGH_MEMORY;
3034 /* check the required size. */
3035 *needed += spoolss_size_printer_info_3(printer);
3037 if (!alloc_buffer_size(buffer, *needed)) {
3038 free_printer_info_3(printer);
3039 return ERROR_INSUFFICIENT_BUFFER;
3042 /* fill the buffer with the structures */
3043 new_smb_io_printer_info_3("", buffer, printer, 0);
3046 free_printer_info_3(printer);
3048 if (*needed > offered) {
3049 return ERROR_INSUFFICIENT_BUFFER;
3052 return NT_STATUS_NO_PROBLEMO;
3055 /****************************************************************************
3056 ****************************************************************************/
3057 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
3058 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3064 if (!get_printer_snum(handle, &snum))
3065 return ERROR_INVALID_HANDLE;
3069 return getprinter_level_0(snum, buffer, offered, needed);
3071 return getprinter_level_1(snum, buffer, offered, needed);
3073 return getprinter_level_2(snum, buffer, offered, needed);
3075 return getprinter_level_3(snum, buffer, offered, needed);
3077 return ERROR_INVALID_LEVEL;
3081 /********************************************************************
3082 * fill a DRIVER_INFO_1 struct
3083 ********************************************************************/
3084 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3086 init_unistr( &info->name, driver.info_3->name);
3089 /********************************************************************
3090 * construct_printer_driver_info_1
3091 ********************************************************************/
3092 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3094 NT_PRINTER_INFO_LEVEL *printer = NULL;
3095 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3097 ZERO_STRUCT(driver);
3099 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3100 return ERROR_INVALID_PRINTER_NAME;
3102 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3103 return ERROR_UNKNOWN_PRINTER_DRIVER;
3105 fill_printer_driver_info_1(info, driver, servername, architecture);
3107 free_a_printer(&printer,2);
3109 return NT_STATUS_NO_PROBLEMO;
3112 /********************************************************************
3113 * construct_printer_driver_info_2
3114 * fill a printer_info_2 struct
3115 ********************************************************************/
3116 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3120 info->version=driver.info_3->cversion;
3122 init_unistr( &info->name, driver.info_3->name );
3123 init_unistr( &info->architecture, driver.info_3->environment );
3126 if (strlen(driver.info_3->driverpath)) {
3127 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3128 init_unistr( &info->driverpath, temp );
3130 init_unistr( &info->driverpath, "" );
3132 if (strlen(driver.info_3->datafile)) {
3133 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3134 init_unistr( &info->datafile, temp );
3136 init_unistr( &info->datafile, "" );
3138 if (strlen(driver.info_3->configfile)) {
3139 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3140 init_unistr( &info->configfile, temp );
3142 init_unistr( &info->configfile, "" );
3145 /********************************************************************
3146 * construct_printer_driver_info_2
3147 * fill a printer_info_2 struct
3148 ********************************************************************/
3149 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3151 NT_PRINTER_INFO_LEVEL *printer = NULL;
3152 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3154 ZERO_STRUCT(printer);
3155 ZERO_STRUCT(driver);
3157 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3158 return ERROR_INVALID_PRINTER_NAME;
3160 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3161 return ERROR_UNKNOWN_PRINTER_DRIVER;
3163 fill_printer_driver_info_2(info, driver, servername);
3165 free_a_printer(&printer,2);
3167 return NT_STATUS_NO_PROBLEMO;
3170 /********************************************************************
3171 * copy a strings array and convert to UNICODE
3173 * convert an array of ascii string to a UNICODE string
3174 ********************************************************************/
3175 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3182 DEBUG(6,("init_unistr_array\n"));
3186 if (char_array == NULL)
3190 if (!v) v = ""; /* hack to handle null lists */
3192 if (strlen(v) == 0) break;
3193 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3194 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3195 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3196 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3199 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3204 (*uni_array)[j]=0x0000;
3207 DEBUGADD(6,("last one:done\n"));
3210 /********************************************************************
3211 * construct_printer_info_3
3212 * fill a printer_info_3 struct
3213 ********************************************************************/
3214 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3220 info->version=driver.info_3->cversion;
3222 init_unistr( &info->name, driver.info_3->name );
3223 init_unistr( &info->architecture, driver.info_3->environment );
3225 if (strlen(driver.info_3->driverpath)) {
3226 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3227 init_unistr( &info->driverpath, temp );
3229 init_unistr( &info->driverpath, "" );
3231 if (strlen(driver.info_3->datafile)) {
3232 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3233 init_unistr( &info->datafile, temp );
3235 init_unistr( &info->datafile, "" );
3237 if (strlen(driver.info_3->configfile)) {
3238 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3239 init_unistr( &info->configfile, temp );
3241 init_unistr( &info->configfile, "" );
3243 if (strlen(driver.info_3->helpfile)) {
3244 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3245 init_unistr( &info->helpfile, temp );
3247 init_unistr( &info->helpfile, "" );
3249 init_unistr( &info->monitorname, driver.info_3->monitorname );
3250 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3252 info->dependentfiles=NULL;
3253 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3256 /********************************************************************
3257 * construct_printer_info_3
3258 * fill a printer_info_3 struct
3259 ********************************************************************/
3260 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3262 NT_PRINTER_INFO_LEVEL *printer = NULL;
3263 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3265 ZERO_STRUCT(driver);
3267 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3268 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3270 return ERROR_INVALID_PRINTER_NAME;
3272 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3273 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3275 free_a_printer(&printer,2);
3276 return ERROR_UNKNOWN_PRINTER_DRIVER;
3279 fill_printer_driver_info_3(info, driver, servername);
3281 free_a_printer(&printer,2);
3283 return NT_STATUS_NO_PROBLEMO;
3286 /********************************************************************
3287 * construct_printer_info_6
3288 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3289 ********************************************************************/
3291 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3297 memset(&nullstr, '\0', sizeof(fstring));
3299 info->version=driver.info_3->cversion;
3301 init_unistr( &info->name, driver.info_3->name );
3302 init_unistr( &info->architecture, driver.info_3->environment );
3304 if (strlen(driver.info_3->driverpath)) {
3305 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3306 init_unistr( &info->driverpath, temp );
3308 init_unistr( &info->driverpath, "" );
3310 if (strlen(driver.info_3->datafile)) {
3311 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3312 init_unistr( &info->datafile, temp );
3314 init_unistr( &info->datafile, "" );
3316 if (strlen(driver.info_3->configfile)) {
3317 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3318 init_unistr( &info->configfile, temp );
3320 init_unistr( &info->configfile, "" );
3322 if (strlen(driver.info_3->helpfile)) {
3323 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3324 init_unistr( &info->helpfile, temp );
3326 init_unistr( &info->helpfile, "" );
3328 init_unistr( &info->monitorname, driver.info_3->monitorname );
3329 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3331 info->dependentfiles=NULL;
3332 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3334 info->previousdrivernames=NULL;
3335 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3337 info->driver_date.low=0;
3338 info->driver_date.high=0;
3341 info->driver_version_low=0;
3342 info->driver_version_high=0;
3344 init_unistr( &info->mfgname, "");
3345 init_unistr( &info->oem_url, "");
3346 init_unistr( &info->hardware_id, "");
3347 init_unistr( &info->provider, "");
3350 /********************************************************************
3351 * construct_printer_info_6
3352 * fill a printer_info_6 struct
3353 ********************************************************************/
3354 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3356 NT_PRINTER_INFO_LEVEL *printer = NULL;
3357 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3359 ZERO_STRUCT(driver);
3361 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3362 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3364 return ERROR_INVALID_PRINTER_NAME;
3366 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3367 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3370 * Is this a W2k client ?
3374 free_a_printer(&printer,2);
3375 return ERROR_UNKNOWN_PRINTER_DRIVER;
3378 /* Yes - try again with a WinNT driver. */
3380 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3381 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3383 free_a_printer(&printer,2);
3384 return ERROR_UNKNOWN_PRINTER_DRIVER;
3388 fill_printer_driver_info_6(info, driver, servername);
3390 free_a_printer(&printer,2);
3392 return NT_STATUS_NO_PROBLEMO;
3395 /****************************************************************************
3396 ****************************************************************************/
3398 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3400 safe_free(info->dependentfiles);
3403 /****************************************************************************
3404 ****************************************************************************/
3406 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3408 safe_free(info->dependentfiles);
3412 /****************************************************************************
3413 ****************************************************************************/
3414 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3416 DRIVER_INFO_1 *info=NULL;
3419 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3420 return ERROR_NOT_ENOUGH_MEMORY;
3422 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3423 if (status != NT_STATUS_NO_PROBLEMO) {
3428 /* check the required size. */
3429 *needed += spoolss_size_printer_driver_info_1(info);
3431 if (!alloc_buffer_size(buffer, *needed)) {
3433 return ERROR_INSUFFICIENT_BUFFER;
3436 /* fill the buffer with the structures */
3437 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3442 if (*needed > offered)
3443 return ERROR_INSUFFICIENT_BUFFER;
3445 return NT_STATUS_NO_PROBLEMO;
3448 /****************************************************************************
3449 ****************************************************************************/
3450 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3452 DRIVER_INFO_2 *info=NULL;
3455 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3456 return ERROR_NOT_ENOUGH_MEMORY;
3458 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3459 if (status != NT_STATUS_NO_PROBLEMO) {
3464 /* check the required size. */
3465 *needed += spoolss_size_printer_driver_info_2(info);
3467 if (!alloc_buffer_size(buffer, *needed)) {
3469 return ERROR_INSUFFICIENT_BUFFER;
3472 /* fill the buffer with the structures */
3473 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3478 if (*needed > offered)
3479 return ERROR_INSUFFICIENT_BUFFER;
3481 return NT_STATUS_NO_PROBLEMO;
3484 /****************************************************************************
3485 ****************************************************************************/
3486 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3493 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3494 if (status != NT_STATUS_NO_PROBLEMO) {
3498 /* check the required size. */
3499 *needed += spoolss_size_printer_driver_info_3(&info);
3501 if (!alloc_buffer_size(buffer, *needed)) {
3502 free_printer_driver_info_3(&info);
3503 return ERROR_INSUFFICIENT_BUFFER;
3506 /* fill the buffer with the structures */
3507 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3509 free_printer_driver_info_3(&info);
3511 if (*needed > offered)
3512 return ERROR_INSUFFICIENT_BUFFER;
3514 return NT_STATUS_NO_PROBLEMO;
3517 /****************************************************************************
3518 ****************************************************************************/
3519 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3526 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3527 if (status != NT_STATUS_NO_PROBLEMO) {
3531 /* check the required size. */
3532 *needed += spoolss_size_printer_driver_info_6(&info);
3534 if (!alloc_buffer_size(buffer, *needed)) {
3535 free_printer_driver_info_6(&info);
3536 return ERROR_INSUFFICIENT_BUFFER;
3539 /* fill the buffer with the structures */
3540 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3542 free_printer_driver_info_6(&info);
3544 if (*needed > offered)
3545 return ERROR_INSUFFICIENT_BUFFER;
3547 return NT_STATUS_NO_PROBLEMO;
3550 /****************************************************************************
3551 ****************************************************************************/
3552 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3553 uint32 clientmajorversion, uint32 clientminorversion,
3554 NEW_BUFFER *buffer, uint32 offered,
3555 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3558 fstring architecture;
3561 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3564 *servermajorversion=0;
3565 *serverminorversion=0;
3567 pstrcpy(servername, global_myname);
3568 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3570 if (!get_printer_snum(handle, &snum))
3571 return ERROR_INVALID_HANDLE;
3575 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3577 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3579 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3581 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3583 return ERROR_INVALID_LEVEL;
3587 /****************************************************************************
3588 ****************************************************************************/
3589 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3591 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3593 if (OPEN_HANDLE(Printer)) {
3594 Printer->page_started=True;
3598 DEBUG(3,("Error in startpageprinter printer handle\n"));
3599 return ERROR_INVALID_HANDLE;
3602 /****************************************************************************
3603 ****************************************************************************/
3604 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3606 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3608 if (!OPEN_HANDLE(Printer)) {
3609 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3610 return ERROR_INVALID_HANDLE;
3613 Printer->page_started=False;
3615 return NT_STATUS_NO_PROBLEMO;
3618 /****************************************************************************
3619 Return a user struct for a pipe user.
3620 ****************************************************************************/
3622 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
3624 if (p->ntlmssp_auth_validated) {
3625 memcpy(user, &p->pipe_user, sizeof(struct current_user));
3627 extern struct current_user current_user;
3628 memcpy(user, ¤t_user, sizeof(struct current_user));
3634 /********************************************************************
3635 * api_spoolss_getprinter
3636 * called from the spoolss dispatcher
3638 ********************************************************************/
3639 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3640 pipes_struct *p, DOC_INFO *docinfo,
3643 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3647 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3648 struct current_user user;
3650 if (!OPEN_HANDLE(Printer)) {
3651 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3652 return ERROR_INVALID_HANDLE;
3655 get_current_user(&user, p);
3658 * a nice thing with NT is it doesn't listen to what you tell it.
3659 * when asked to send _only_ RAW datas, it tries to send datas
3662 * So I add checks like in NT Server ...
3664 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3665 * there's a bug in NT client-side code, so we'll fix it in the
3666 * server-side code. *nnnnnggggh!*
3669 if (info_1->p_datatype != 0) {
3670 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3671 if (strcmp(datatype, "RAW") != 0) {
3673 return ERROR_INVALID_DATATYPE;
3677 /* get the share number of the printer */
3678 if (!get_printer_snum(handle, &snum)) {
3679 return ERROR_INVALID_HANDLE;
3682 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3684 Printer->jobid = print_job_start(&user, snum, jobname);
3686 /* An error occured in print_job_start() so return an appropriate
3689 if (Printer->jobid == -1) {
3690 return map_nt_error_from_unix(errno);
3693 Printer->document_started=True;
3694 (*jobid) = Printer->jobid;
3699 /********************************************************************
3700 * api_spoolss_getprinter
3701 * called from the spoolss dispatcher
3703 ********************************************************************/
3704 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3706 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3708 if (!OPEN_HANDLE(Printer)) {
3709 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3710 return ERROR_INVALID_HANDLE;
3713 Printer->document_started=False;
3714 print_job_end(Printer->jobid,True);
3715 /* error codes unhandled so far ... */
3720 /****************************************************************************
3721 ****************************************************************************/
3722 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3725 uint32 *buffer_written)
3727 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3729 if (!OPEN_HANDLE(Printer)) {
3730 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3731 return ERROR_INVALID_HANDLE;
3734 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3740 /********************************************************************
3741 * api_spoolss_getprinter
3742 * called from the spoolss dispatcher
3744 ********************************************************************/
3745 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3748 struct current_user user;
3749 int snum, errcode = ERROR_INVALID_FUNCTION;
3750 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3752 get_current_user(&user, p);
3754 if (!OPEN_HANDLE(Printer)) {
3755 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3756 return ERROR_INVALID_HANDLE;
3759 if (!get_printer_snum(handle, &snum))
3760 return ERROR_INVALID_HANDLE;
3763 case PRINTER_CONTROL_PAUSE:
3764 if (print_queue_pause(&user, snum, &errcode)) {
3768 case PRINTER_CONTROL_RESUME:
3769 case PRINTER_CONTROL_UNPAUSE:
3770 if (print_queue_resume(&user, snum, &errcode)) {
3774 case PRINTER_CONTROL_PURGE:
3775 if (print_queue_purge(&user, snum, &errcode)) {
3780 return ERROR_INVALID_LEVEL;
3786 /********************************************************************
3787 * api_spoolss_abortprinter
3788 ********************************************************************/
3790 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3792 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3795 /********************************************************************
3796 * called by spoolss_api_setprinter
3797 * when updating a printer description
3798 ********************************************************************/
3799 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3800 const SPOOL_PRINTER_INFO_LEVEL *info,
3801 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3803 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3804 struct current_user user;
3808 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3810 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3811 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3812 OUR_HANDLE(handle)));
3814 result = ERROR_INVALID_HANDLE;
3818 /* NT seems to like setting the security descriptor even though
3819 nothing may have actually changed. This causes annoying
3820 dialog boxes when the user doesn't have permission to change
3821 the security descriptor. */
3823 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3825 if (DEBUGLEVEL >= 10) {
3829 acl = old_secdesc_ctr->sec->dacl;
3830 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3831 PRINTERNAME(snum), acl->num_aces));
3833 for (i = 0; i < acl->num_aces; i++) {
3836 sid_to_string(sid_str, &acl->ace[i].sid);
3838 DEBUG(10, ("%s 0x%08x\n", sid_str,
3839 acl->ace[i].info.mask));
3842 acl = secdesc_ctr->sec->dacl;
3845 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3846 PRINTERNAME(snum), acl->num_aces));
3848 for (i = 0; i < acl->num_aces; i++) {
3851 sid_to_string(sid_str, &acl->ace[i].sid);
3853 DEBUG(10, ("%s 0x%08x\n", sid_str,
3854 acl->ace[i].info.mask));
3857 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3861 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3863 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3864 result = NT_STATUS_NO_PROBLEMO;
3868 /* Work out which user is performing the operation */
3870 get_current_user(&user, p);
3872 /* Check the user has permissions to change the security
3873 descriptor. By experimentation with two NT machines, the user
3874 requires Full Access to the printer to change security
3877 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3878 result = ERROR_ACCESS_DENIED;
3882 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3885 free_sec_desc_buf(&new_secdesc_ctr);
3886 free_sec_desc_buf(&old_secdesc_ctr);
3891 /********************************************************************
3892 Do Samba sanity checks on a printer info struct.
3893 this has changed purpose: it now "canonicalises" printer
3894 info from a client rather than just checking it is correct
3895 ********************************************************************/
3897 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3899 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3900 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3902 /* we force some elements to "correct" values */
3903 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3904 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3905 global_myname, lp_servicename(snum));
3906 fstrcpy(info->sharename, lp_servicename(snum));
3907 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3908 | PRINTER_ATTRIBUTE_LOCAL \
3909 | PRINTER_ATTRIBUTE_RAW_ONLY \
3910 | PRINTER_ATTRIBUTE_QUEUED ;
3915 /****************************************************************************
3916 ****************************************************************************/
3917 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3919 pid_t local_pid = sys_getpid();
3920 char *cmd = lp_addprinter_cmd();
3925 pstring driverlocation;
3929 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3930 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3934 /* build driver path... only 9X architecture is needed for legacy reasons */
3935 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3937 /* change \ to \\ for the shell */
3938 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3940 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3941 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3942 cmd, printer->info_2->printername, printer->info_2->sharename,
3943 printer->info_2->portname, printer->info_2->drivername,
3944 printer->info_2->location, driverlocation);
3948 /* Convert script args to unix-codepage */
3949 dos_to_unix(command, True);
3950 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3951 ret = smbrun(command, tmp_file, False);
3952 DEBUGADD(10,("returned [%d]\n", ret));
3960 /* Get lines and convert them back to dos-codepage */
3961 qlines = file_lines_load(tmp_file, &numlines, True);
3962 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3963 DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
3967 /* Set the portname to what the script says the portname should be. */
3968 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3969 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3971 /* Send SIGHUP to process group... is there a better way? */
3976 file_lines_free(qlines);
3980 /* Return true if two devicemodes are equal */
3982 #define DEVMODE_CHECK_INT(field) \
3983 if (d1->field != d2->field) { \
3984 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
3985 d1->field, d2->field)); \
3989 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
3991 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
3994 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
3995 return False; /* if either is exclusively NULL are not equal */
3998 if (!strequal(d1->devicename, d2->devicename) ||
3999 !strequal(d1->formname, d2->formname)) {
4000 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
4004 DEVMODE_CHECK_INT(specversion);
4005 DEVMODE_CHECK_INT(driverversion);
4006 DEVMODE_CHECK_INT(driverextra);
4007 DEVMODE_CHECK_INT(orientation);
4008 DEVMODE_CHECK_INT(papersize);
4009 DEVMODE_CHECK_INT(paperlength);
4010 DEVMODE_CHECK_INT(paperwidth);
4011 DEVMODE_CHECK_INT(scale);
4012 DEVMODE_CHECK_INT(copies);
4013 DEVMODE_CHECK_INT(defaultsource);
4014 DEVMODE_CHECK_INT(printquality);
4015 DEVMODE_CHECK_INT(color);
4016 DEVMODE_CHECK_INT(duplex);
4017 DEVMODE_CHECK_INT(yresolution);
4018 DEVMODE_CHECK_INT(ttoption);
4019 DEVMODE_CHECK_INT(collate);
4020 DEVMODE_CHECK_INT(logpixels);
4022 DEVMODE_CHECK_INT(fields);
4023 DEVMODE_CHECK_INT(bitsperpel);
4024 DEVMODE_CHECK_INT(pelswidth);
4025 DEVMODE_CHECK_INT(pelsheight);
4026 DEVMODE_CHECK_INT(displayflags);
4027 DEVMODE_CHECK_INT(displayfrequency);
4028 DEVMODE_CHECK_INT(icmmethod);
4029 DEVMODE_CHECK_INT(icmintent);
4030 DEVMODE_CHECK_INT(mediatype);
4031 DEVMODE_CHECK_INT(dithertype);
4032 DEVMODE_CHECK_INT(reserved1);
4033 DEVMODE_CHECK_INT(reserved2);
4034 DEVMODE_CHECK_INT(panningwidth);
4035 DEVMODE_CHECK_INT(panningheight);
4037 /* compare the private data if it exists */
4038 if (!d1->driverextra && !d2->driverextra) goto equal;
4041 DEVMODE_CHECK_INT(driverextra);
4043 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4044 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4049 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4053 /* Return true if two NT_PRINTER_PARAM structures are equal */
4055 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4056 NT_PRINTER_PARAM *p2)
4058 if (!p1 && !p2) goto equal;
4060 if ((!p1 && p2) || (p1 && !p2)) {
4061 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4065 /* Compare lists of printer parameters */
4069 NT_PRINTER_PARAM *q = p1;
4071 /* Find the parameter in the second structure */
4075 if (strequal(p1->value, q->value)) {
4077 if (p1->type != q->type) {
4078 DEBUG(10, ("nt_printer_param_equal():"
4079 "types for %s differ (%d != %d)\n",
4080 p1->value, p1->type,
4085 if (p1->data_len != q->data_len) {
4086 DEBUG(10, ("nt_printer_param_equal():"
4087 "len for %s differs (%d != %d)\n",
4088 p1->value, p1->data_len,
4093 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4096 DEBUG(10, ("nt_printer_param_equal():"
4097 "data for %s differs\n", p1->value));
4107 DEBUG(10, ("nt_printer_param_equal(): param %s "
4108 "does not exist\n", p1->value));
4117 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4121 /********************************************************************
4122 * Called by update_printer when trying to work out whether to
4123 * actually update printer info.
4124 ********************************************************************/
4126 #define PI_CHECK_INT(field) \
4127 if (pi1->field != pi2->field) { \
4128 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4129 pi1->field, pi2->field)); \
4133 #define PI_CHECK_STR(field) \
4134 if (!strequal(pi1->field, pi2->field)) { \
4135 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4136 pi1->field, pi2->field)); \
4140 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4141 NT_PRINTER_INFO_LEVEL *p2)
4143 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4145 /* Trivial conditions */
4147 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4151 if ((!p1 && p2) || (p1 && !p2) ||
4152 (!p1->info_2 && p2->info_2) ||
4153 (p1->info_2 && !p2->info_2)) {
4154 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4159 /* Compare two nt_printer_info_level structures. Don't compare
4160 status or cjobs as they seem to have something to do with the
4166 PI_CHECK_INT(attributes);
4167 PI_CHECK_INT(priority);
4168 PI_CHECK_INT(default_priority);
4169 PI_CHECK_INT(starttime);
4170 PI_CHECK_INT(untiltime);
4171 PI_CHECK_INT(averageppm);
4173 /* Yuck - don't check the printername or servername as the
4174 add_a_printer() code plays games with them. You can't
4175 change the printername or the sharename through this interface
4178 PI_CHECK_STR(sharename);
4179 PI_CHECK_STR(portname);
4180 PI_CHECK_STR(drivername);
4181 PI_CHECK_STR(comment);
4182 PI_CHECK_STR(location);
4184 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4188 PI_CHECK_STR(sepfile);
4189 PI_CHECK_STR(printprocessor);
4190 PI_CHECK_STR(datatype);
4191 PI_CHECK_STR(parameters);
4193 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4197 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4201 PI_CHECK_INT(changeid);
4202 PI_CHECK_INT(c_setprinter);
4203 PI_CHECK_INT(setuptime);
4206 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4210 /********************************************************************
4211 * called by spoolss_api_setprinter
4212 * when updating a printer description
4213 ********************************************************************/
4215 static uint32 update_printer(POLICY_HND *handle, uint32 level,
4216 const SPOOL_PRINTER_INFO_LEVEL *info,
4217 DEVICEMODE *devmode)
4220 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4221 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4224 DEBUG(8,("update_printer\n"));
4226 result = NT_STATUS_NO_PROBLEMO;
4229 DEBUG(0,("Send a mail to samba@samba.org\n"));
4230 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4231 result = ERROR_INVALID_LEVEL;
4235 if (!OPEN_HANDLE(Printer)) {
4236 result = ERROR_INVALID_HANDLE;
4240 if (!get_printer_snum(handle, &snum)) {
4241 result = ERROR_INVALID_HANDLE;
4245 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4246 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4247 result = ERROR_INVALID_HANDLE;
4251 DEBUGADD(8,("Converting info_2 struct\n"));
4254 * convert_printer_info converts the incoming
4255 * info from the client and overwrites the info
4256 * just read from the tdb in the pointer 'printer'.
4259 convert_printer_info(info, printer, level);
4261 if (info->info_2->devmode_ptr != 0) {
4262 /* we have a valid devmode
4263 convert it and link it*/
4265 DEBUGADD(8,("Converting the devicemode struct\n"));
4266 if (!convert_devicemode(printer->info_2->printername, devmode,
4267 &printer->info_2->devmode)) {
4268 result = ERROR_NOT_ENOUGH_MEMORY;
4273 /* Do sanity check on the requested changes for Samba */
4275 if (!check_printer_ok(printer->info_2, snum)) {
4276 result = ERROR_INVALID_PARAMETER;
4280 /* NT likes to call this function even though nothing has actually
4281 changed. Check this so the user doesn't end up with an
4282 annoying permission denied dialog box. */
4284 if (nt_printer_info_level_equal(printer, old_printer)) {
4285 DEBUG(3, ("printer info has not changed\n"));
4286 result = NT_STATUS_NO_PROBLEMO;
4290 /* Check calling user has permission to update printer description */
4292 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4293 DEBUG(3, ("printer property change denied by security "
4295 result = ERROR_ACCESS_DENIED;
4299 /* Call addprinter hook */
4301 if (*lp_addprinter_cmd() )
4302 if ( !add_printer_hook(printer) ) {
4303 result = ERROR_ACCESS_DENIED;
4307 /* Update printer info */
4309 if (add_a_printer(*printer, 2)!=0) {
4310 /* I don't really know what to return here !!! */
4311 result = ERROR_ACCESS_DENIED;
4316 free_a_printer(&printer, 2);
4317 free_a_printer(&old_printer, 2);
4319 srv_spoolss_sendnotify(handle);
4324 /****************************************************************************
4325 ****************************************************************************/
4326 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
4327 const SPOOL_PRINTER_INFO_LEVEL *info,
4328 DEVMODE_CTR devmode_ctr,
4329 SEC_DESC_BUF *secdesc_ctr,
4330 uint32 command, pipes_struct *p)
4332 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4334 if (!OPEN_HANDLE(Printer)) {
4335 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4336 return ERROR_INVALID_HANDLE;
4339 /* check the level */
4342 return control_printer(handle, command, p);
4344 return update_printer(handle, level, info, devmode_ctr.devmode);
4346 return update_printer_sec(handle, level, info, p,
4349 return ERROR_INVALID_LEVEL;
4353 /****************************************************************************
4354 ****************************************************************************/
4355 uint32 _spoolss_fcpn(POLICY_HND *handle)
4357 Printer_entry *Printer= find_printer_index_by_hnd(handle);
4359 if (!OPEN_HANDLE(Printer)) {
4360 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4361 return ERROR_INVALID_HANDLE;
4364 if (Printer->notify.client_connected==True)
4365 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4366 return ERROR_INVALID_HANDLE;
4368 Printer->notify.flags=0;
4369 Printer->notify.options=0;
4370 Printer->notify.localmachine[0]='\0';
4371 Printer->notify.printerlocal=0;
4372 if (Printer->notify.option)
4373 safe_free(Printer->notify.option->ctr.type);
4374 safe_free(Printer->notify.option);
4375 Printer->notify.option=NULL;
4376 Printer->notify.client_connected=False;
4378 return NT_STATUS_NO_PROBLEMO;
4381 /****************************************************************************
4382 ****************************************************************************/
4383 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
4384 NEW_BUFFER *buffer, uint32 offered,
4388 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4389 returns for AddJob. AddJob
4390 must fail on non-local
4394 /****************************************************************************
4395 ****************************************************************************/
4396 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4397 int position, int snum)
4403 t=gmtime(&queue->time);
4404 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4406 job_info->jobid=queue->job;
4407 init_unistr(&job_info->printername, lp_servicename(snum));
4408 init_unistr(&job_info->machinename, temp_name);
4409 init_unistr(&job_info->username, queue->user);
4410 init_unistr(&job_info->document, queue->file);
4411 init_unistr(&job_info->datatype, "RAW");
4412 init_unistr(&job_info->text_status, "");
4413 job_info->status=nt_printj_status(queue->status);
4414 job_info->priority=queue->priority;
4415 job_info->position=position;
4416 job_info->totalpages=0;
4417 job_info->pagesprinted=0;
4419 make_systemtime(&job_info->submitted, t);
4422 /****************************************************************************
4423 ****************************************************************************/
4424 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4425 int position, int snum,
4426 NT_PRINTER_INFO_LEVEL *ntprinter)
4432 t=gmtime(&queue->time);
4433 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4435 job_info->jobid=queue->job;
4437 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4439 init_unistr(&job_info->printername, chaine);
4441 init_unistr(&job_info->machinename, temp_name);
4442 init_unistr(&job_info->username, queue->user);
4443 init_unistr(&job_info->document, queue->file);
4444 init_unistr(&job_info->notifyname, queue->user);
4445 init_unistr(&job_info->datatype, "RAW");
4446 init_unistr(&job_info->printprocessor, "winprint");
4447 init_unistr(&job_info->parameters, "");
4448 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4449 init_unistr(&job_info->text_status, "");
4451 /* and here the security descriptor */
4453 job_info->status=nt_printj_status(queue->status);
4454 job_info->priority=queue->priority;
4455 job_info->position=position;
4456 job_info->starttime=0;
4457 job_info->untiltime=0;
4458 job_info->totalpages=0;
4459 job_info->size=queue->size;
4460 make_systemtime(&(job_info->submitted), t);
4461 job_info->timeelapsed=0;
4462 job_info->pagesprinted=0;
4464 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4471 /****************************************************************************
4472 Enumjobs at level 1.
4473 ****************************************************************************/
4474 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4475 NEW_BUFFER *buffer, uint32 offered,
4476 uint32 *needed, uint32 *returned)
4481 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4485 return ERROR_NOT_ENOUGH_MEMORY;
4488 for (i=0; i<*returned; i++)
4489 fill_job_info_1(&info[i], &queue[i], i, snum);
4493 /* check the required size. */
4494 for (i=0; i<*returned; i++)
4495 (*needed) += spoolss_size_job_info_1(&info[i]);
4497 if (!alloc_buffer_size(buffer, *needed)) {
4499 return ERROR_INSUFFICIENT_BUFFER;
4502 /* fill the buffer with the structures */
4503 for (i=0; i<*returned; i++)
4504 new_smb_io_job_info_1("", buffer, &info[i], 0);
4509 if (*needed > offered) {
4511 return ERROR_INSUFFICIENT_BUFFER;
4514 return NT_STATUS_NO_PROBLEMO;
4517 /****************************************************************************
4518 Enumjobs at level 2.
4519 ****************************************************************************/
4520 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4521 NEW_BUFFER *buffer, uint32 offered,
4522 uint32 *needed, uint32 *returned)
4524 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4528 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4531 return ERROR_NOT_ENOUGH_MEMORY;
4534 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4536 return ERROR_NOT_ENOUGH_MEMORY;
4539 for (i=0; i<*returned; i++)
4540 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4542 free_a_printer(&ntprinter, 2);
4545 /* check the required size. */
4546 for (i=0; i<*returned; i++)
4547 (*needed) += spoolss_size_job_info_2(&info[i]);
4549 if (!alloc_buffer_size(buffer, *needed)) {
4551 return ERROR_INSUFFICIENT_BUFFER;
4554 /* fill the buffer with the structures */
4555 for (i=0; i<*returned; i++)
4556 new_smb_io_job_info_2("", buffer, &info[i], 0);
4559 for (i = 0; i < *returned; i++)
4560 free_job_info_2(&info[i]);
4564 if (*needed > offered) {
4566 return ERROR_INSUFFICIENT_BUFFER;
4569 return NT_STATUS_NO_PROBLEMO;
4572 /****************************************************************************
4574 ****************************************************************************/
4575 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4576 NEW_BUFFER *buffer, uint32 offered,
4577 uint32 *needed, uint32 *returned)
4580 print_queue_struct *queue=NULL;
4581 print_status_struct prt_status;
4583 DEBUG(4,("_spoolss_enumjobs\n"));
4585 ZERO_STRUCT(prt_status);
4590 if (!get_printer_snum(handle, &snum))
4591 return ERROR_INVALID_HANDLE;
4593 *returned = print_queue_status(snum, &queue, &prt_status);
4594 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4596 if (*returned == 0) {
4598 return NT_STATUS_NO_PROBLEMO;
4603 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4605 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4609 return ERROR_INVALID_LEVEL;
4614 /****************************************************************************
4615 ****************************************************************************/
4616 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4621 /****************************************************************************
4622 ****************************************************************************/
4623 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4624 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4626 struct current_user user;
4627 print_status_struct prt_status;
4628 int snum, errcode = ERROR_INVALID_FUNCTION;
4630 memset(&prt_status, 0, sizeof(prt_status));
4632 if (!get_printer_snum(handle, &snum)) {
4633 return ERROR_INVALID_HANDLE;
4636 if (!print_job_exists(jobid)) {
4637 return ERROR_INVALID_PRINTER_NAME;
4640 get_current_user(&user, p);
4643 case JOB_CONTROL_CANCEL:
4644 case JOB_CONTROL_DELETE:
4645 if (print_job_delete(&user, jobid, &errcode)) {
4649 case JOB_CONTROL_PAUSE:
4650 if (print_job_pause(&user, jobid, &errcode)) {
4654 case JOB_CONTROL_RESTART:
4655 case JOB_CONTROL_RESUME:
4656 if (print_job_resume(&user, jobid, &errcode)) {
4661 return ERROR_INVALID_LEVEL;
4667 /****************************************************************************
4668 Enumerates all printer drivers at level 1.
4669 ****************************************************************************/
4670 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4675 fstring *list = NULL;
4677 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4678 DRIVER_INFO_1 *driver_info_1=NULL;
4682 #define MAX_VERSION 4
4684 for (version=0; version<MAX_VERSION; version++) {
4686 ndrivers=get_ntdrivers(&list, architecture, version);
4687 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4690 return ERROR_NOT_ENOUGH_MEMORY;
4693 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4695 return ERROR_NOT_ENOUGH_MEMORY;
4699 for (i=0; i<ndrivers; i++) {
4701 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4702 ZERO_STRUCT(driver);
4703 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4707 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4708 free_a_printer_driver(driver, 3);
4711 *returned+=ndrivers;
4715 /* check the required size. */
4716 for (i=0; i<*returned; i++) {
4717 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4718 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4721 if (!alloc_buffer_size(buffer, *needed)) {
4722 safe_free(driver_info_1);
4723 return ERROR_INSUFFICIENT_BUFFER;
4726 /* fill the buffer with the form structures */
4727 for (i=0; i<*returned; i++) {
4728 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4729 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4732 safe_free(driver_info_1);
4734 if (*needed > offered) {
4736 return ERROR_INSUFFICIENT_BUFFER;
4739 return NT_STATUS_NO_PROBLEMO;
4742 /****************************************************************************
4743 Enumerates all printer drivers at level 2.
4744 ****************************************************************************/
4745 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4750 fstring *list = NULL;
4752 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4753 DRIVER_INFO_2 *driver_info_2=NULL;
4757 #define MAX_VERSION 4
4759 for (version=0; version<MAX_VERSION; version++) {
4761 ndrivers=get_ntdrivers(&list, architecture, version);
4762 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4765 return ERROR_NOT_ENOUGH_MEMORY;
4768 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4770 return ERROR_NOT_ENOUGH_MEMORY;
4774 for (i=0; i<ndrivers; i++) {
4777 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4778 ZERO_STRUCT(driver);
4779 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4783 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4784 free_a_printer_driver(driver, 3);
4787 *returned+=ndrivers;
4791 /* check the required size. */
4792 for (i=0; i<*returned; i++) {
4793 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4794 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4797 if (!alloc_buffer_size(buffer, *needed)) {
4798 safe_free(driver_info_2);
4799 return ERROR_INSUFFICIENT_BUFFER;
4802 /* fill the buffer with the form structures */
4803 for (i=0; i<*returned; i++) {
4804 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4805 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4808 safe_free(driver_info_2);
4810 if (*needed > offered) {
4812 return ERROR_INSUFFICIENT_BUFFER;
4815 return NT_STATUS_NO_PROBLEMO;
4818 /****************************************************************************
4819 Enumerates all printer drivers at level 3.
4820 ****************************************************************************/
4821 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4826 fstring *list = NULL;
4828 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4829 DRIVER_INFO_3 *driver_info_3=NULL;
4833 #define MAX_VERSION 4
4835 for (version=0; version<MAX_VERSION; version++) {
4837 ndrivers=get_ntdrivers(&list, architecture, version);
4838 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4841 return ERROR_NOT_ENOUGH_MEMORY;
4844 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4846 return ERROR_NOT_ENOUGH_MEMORY;
4850 for (i=0; i<ndrivers; i++) {
4853 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4854 ZERO_STRUCT(driver);
4855 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4859 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4860 free_a_printer_driver(driver, 3);
4863 *returned+=ndrivers;
4867 /* check the required size. */
4868 for (i=0; i<*returned; i++) {
4869 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4870 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4873 if (!alloc_buffer_size(buffer, *needed)) {
4874 safe_free(driver_info_3);
4875 return ERROR_INSUFFICIENT_BUFFER;
4878 /* fill the buffer with the driver structures */
4879 for (i=0; i<*returned; i++) {
4880 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4881 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4884 for (i=0; i<*returned; i++)
4885 safe_free(driver_info_3[i].dependentfiles);
4887 safe_free(driver_info_3);
4889 if (*needed > offered) {
4891 return ERROR_INSUFFICIENT_BUFFER;
4894 return NT_STATUS_NO_PROBLEMO;
4897 /****************************************************************************
4898 Enumerates all printer drivers.
4899 ****************************************************************************/
4900 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4901 NEW_BUFFER *buffer, uint32 offered,
4902 uint32 *needed, uint32 *returned)
4904 fstring *list = NULL;
4906 fstring architecture;
4908 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4909 fstrcpy(servername, global_myname);
4913 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4917 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4919 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4921 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4925 return ERROR_INVALID_LEVEL;
4929 /****************************************************************************
4930 ****************************************************************************/
4931 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4933 form->flag=list->flag;
4934 init_unistr(&form->name, list->name);
4935 form->width=list->width;
4936 form->length=list->length;
4937 form->left=list->left;
4938 form->top=list->top;
4939 form->right=list->right;
4940 form->bottom=list->bottom;
4943 /****************************************************************************
4944 ****************************************************************************/
4945 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4946 NEW_BUFFER *buffer, uint32 offered,
4947 uint32 *needed, uint32 *numofforms)
4949 nt_forms_struct *list=NULL;
4954 DEBUG(4,("_new_spoolss_enumforms\n"));
4955 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4956 DEBUGADD(5,("Info level [%d]\n", level));
4958 *numofforms = get_ntforms(&list);
4959 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4961 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4965 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4967 return ERROR_NOT_ENOUGH_MEMORY;
4970 /* construct the list of form structures */
4971 for (i=0; i<*numofforms; i++) {
4972 DEBUGADD(6,("Filling form number [%d]\n",i));
4973 fill_form_1(&forms_1[i], &list[i]);
4978 /* check the required size. */
4979 for (i=0; i<*numofforms; i++) {
4980 DEBUGADD(6,("adding form [%d]'s size\n",i));
4981 buffer_size += spoolss_size_form_1(&forms_1[i]);
4984 *needed=buffer_size;
4986 if (!alloc_buffer_size(buffer, buffer_size)){
4988 return ERROR_INSUFFICIENT_BUFFER;
4991 /* fill the buffer with the form structures */
4992 for (i=0; i<*numofforms; i++) {
4993 DEBUGADD(6,("adding form [%d] to buffer\n",i));
4994 new_smb_io_form_1("", buffer, &forms_1[i], 0);
4999 if (*needed > offered) {
5001 return ERROR_INSUFFICIENT_BUFFER;
5004 return NT_STATUS_NO_PROBLEMO;
5008 return ERROR_INVALID_LEVEL;
5013 /****************************************************************************
5014 ****************************************************************************/
5015 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5017 nt_forms_struct *list=NULL;
5023 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5025 DEBUG(4,("_spoolss_getform\n"));
5026 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5027 DEBUGADD(5,("Info level [%d]\n", level));
5029 numofforms = get_ntforms(&list);
5030 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5032 if (numofforms == 0)
5033 return ERROR_NO_MORE_ITEMS;
5038 /* Check if the requested name is in the list of form structures */
5039 for (i=0; i<numofforms; i++) {
5041 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5043 if (strequal(form_name, list[i].name)) {
5044 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5045 fill_form_1(&form_1, &list[i]);
5052 /* check the required size. */
5054 *needed=spoolss_size_form_1(&form_1);
5056 if (!alloc_buffer_size(buffer, buffer_size)){
5057 return ERROR_INSUFFICIENT_BUFFER;
5060 if (*needed > offered) {
5061 return ERROR_INSUFFICIENT_BUFFER;
5064 /* fill the buffer with the form structures */
5065 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5066 new_smb_io_form_1("", buffer, &form_1, 0);
5068 return NT_STATUS_NO_PROBLEMO;
5072 return ERROR_INVALID_LEVEL;
5076 /****************************************************************************
5077 ****************************************************************************/
5078 static void fill_port_1(PORT_INFO_1 *port, char *name)
5080 init_unistr(&port->port_name, name);
5083 /****************************************************************************
5084 ****************************************************************************/
5085 static void fill_port_2(PORT_INFO_2 *port, char *name)
5087 init_unistr(&port->port_name, name);
5088 init_unistr(&port->monitor_name, "Local Monitor");
5089 init_unistr(&port->description, "Local Port");
5090 #define PORT_TYPE_WRITE 1
5091 port->port_type=PORT_TYPE_WRITE;
5095 /****************************************************************************
5097 ****************************************************************************/
5098 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5100 PORT_INFO_1 *ports=NULL;
5103 if (*lp_enumports_cmd()) {
5104 pid_t local_pid = sys_getpid();
5105 char *cmd = lp_enumports_cmd();
5113 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5114 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5118 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5119 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
5122 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5123 ret = smbrun(command, tmp_file, False);
5124 DEBUG(10,("Returned [%d]\n", ret));
5127 /* Is this the best error to return here? */
5128 return ERROR_ACCESS_DENIED;
5132 qlines = file_lines_load(tmp_file, &numlines,True);
5133 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5134 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5138 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5139 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5140 file_lines_free(qlines);
5141 return ERROR_NOT_ENOUGH_MEMORY;
5144 for (i=0; i<numlines; i++) {
5145 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5146 fill_port_1(&ports[i], qlines[i]);
5149 file_lines_free(qlines);
5152 *returned = numlines;
5155 *returned = 1; /* Sole Samba port returned. */
5157 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5158 return ERROR_NOT_ENOUGH_MEMORY;
5160 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5162 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5165 /* check the required size. */
5166 for (i=0; i<*returned; i++) {
5167 DEBUGADD(6,("adding port [%d]'s size\n", i));
5168 *needed += spoolss_size_port_info_1(&ports[i]);
5171 if (!alloc_buffer_size(buffer, *needed)) {
5173 return ERROR_INSUFFICIENT_BUFFER;
5176 /* fill the buffer with the ports structures */
5177 for (i=0; i<*returned; i++) {
5178 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5179 new_smb_io_port_1("", buffer, &ports[i], 0);
5184 if (*needed > offered) {
5186 return ERROR_INSUFFICIENT_BUFFER;
5189 return NT_STATUS_NO_PROBLEMO;
5192 /****************************************************************************
5194 ****************************************************************************/
5196 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5198 PORT_INFO_2 *ports=NULL;
5201 if (*lp_enumports_cmd()) {
5202 pid_t local_pid = sys_getpid();
5203 char *cmd = lp_enumports_cmd();
5211 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5212 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5216 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5217 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
5220 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5221 ret = smbrun(command, tmp_file, False);
5222 DEBUGADD(10,("returned [%d]\n", ret));
5225 /* Is this the best error to return here? */
5226 return ERROR_ACCESS_DENIED;
5230 qlines = file_lines_load(tmp_file, &numlines,True);
5231 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5232 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5236 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5237 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5238 file_lines_free(qlines);
5239 return ERROR_NOT_ENOUGH_MEMORY;
5242 for (i=0; i<numlines; i++) {
5243 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5244 fill_port_2(&(ports[i]), qlines[i]);
5247 file_lines_free(qlines);
5250 *returned = numlines;
5256 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5257 return ERROR_NOT_ENOUGH_MEMORY;
5259 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5261 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5264 /* check the required size. */
5265 for (i=0; i<*returned; i++) {
5266 DEBUGADD(6,("adding port [%d]'s size\n", i));
5267 *needed += spoolss_size_port_info_2(&ports[i]);
5270 if (!alloc_buffer_size(buffer, *needed)) {
5272 return ERROR_INSUFFICIENT_BUFFER;
5275 /* fill the buffer with the ports structures */
5276 for (i=0; i<*returned; i++) {
5277 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5278 new_smb_io_port_2("", buffer, &ports[i], 0);
5283 if (*needed > offered) {
5285 return ERROR_INSUFFICIENT_BUFFER;
5288 return NT_STATUS_NO_PROBLEMO;
5291 /****************************************************************************
5293 ****************************************************************************/
5294 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
5295 NEW_BUFFER *buffer, uint32 offered,
5296 uint32 *needed, uint32 *returned)
5298 DEBUG(4,("_spoolss_enumports\n"));
5305 return enumports_level_1(buffer, offered, needed, returned);
5307 return enumports_level_2(buffer, offered, needed, returned);
5309 return ERROR_INVALID_LEVEL;
5313 /****************************************************************************
5314 ****************************************************************************/
5315 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5316 const SPOOL_PRINTER_INFO_LEVEL *info,
5317 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5318 uint32 user_switch, const SPOOL_USER_CTR *user,
5321 NT_PRINTER_INFO_LEVEL *printer = NULL;
5325 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5326 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5327 return ERROR_NOT_ENOUGH_MEMORY;
5330 ZERO_STRUCTP(printer);
5332 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5333 convert_printer_info(info, printer, 2);
5335 if (*lp_addprinter_cmd() )
5336 if ( !add_printer_hook(printer) ) {
5337 free_a_printer(&printer,2);
5338 return ERROR_ACCESS_DENIED;
5341 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5342 printer->info_2->sharename);
5344 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5345 free_a_printer(&printer,2);
5346 return ERROR_ACCESS_DENIED;
5349 /* you must be a printer admin to add a new printer */
5350 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5351 free_a_printer(&printer,2);
5352 return ERROR_ACCESS_DENIED;
5356 * Do sanity check on the requested changes for Samba.
5359 if (!check_printer_ok(printer->info_2, snum)) {
5360 free_a_printer(&printer,2);
5361 return ERROR_INVALID_PARAMETER;
5364 /* write the ASCII on disk */
5365 if (add_a_printer(*printer, 2) != 0) {
5366 free_a_printer(&printer,2);
5367 return ERROR_ACCESS_DENIED;
5370 if (!open_printer_hnd(handle, name)) {
5371 /* Handle open failed - remove addition. */
5372 del_a_printer(printer->info_2->sharename);
5373 free_a_printer(&printer,2);
5374 return ERROR_ACCESS_DENIED;
5377 free_a_printer(&printer,2);
5379 srv_spoolss_sendnotify(handle);
5381 return NT_STATUS_NO_PROBLEMO;
5384 /****************************************************************************
5385 ****************************************************************************/
5386 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5387 const SPOOL_PRINTER_INFO_LEVEL *info,
5388 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5389 uint32 user_switch, const SPOOL_USER_CTR *user,
5394 /* we don't handle yet */
5395 /* but I know what to do ... */
5396 return ERROR_INVALID_LEVEL;
5398 return spoolss_addprinterex_level_2(uni_srv_name, info,
5399 unk0, unk1, unk2, unk3,
5400 user_switch, user, handle);
5402 return ERROR_INVALID_LEVEL;
5406 /****************************************************************************
5407 ****************************************************************************/
5408 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5409 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5411 uint32 err = NT_STATUS_NO_PROBLEMO;
5412 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5413 struct current_user user;
5415 ZERO_STRUCT(driver);
5417 get_current_user(&user, p);
5419 convert_printer_driver_info(info, &driver, level);
5421 DEBUG(5,("Cleaning driver's information\n"));
5422 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5425 DEBUG(5,("Moving driver to final destination\n"));
5426 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5428 err = ERROR_ACCESS_DENIED;
5432 if (add_a_printer_driver(driver, level)!=0) {
5433 err = ERROR_ACCESS_DENIED;
5438 free_a_printer_driver(driver, level);
5442 /****************************************************************************
5443 ****************************************************************************/
5444 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5446 init_unistr(&info->name, name);
5449 /****************************************************************************
5450 ****************************************************************************/
5451 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5455 pstring short_archi;
5456 DRIVER_DIRECTORY_1 *info=NULL;
5458 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5460 if (get_short_archi(short_archi, long_archi)==FALSE)
5461 return ERROR_INVALID_ENVIRONMENT;
5463 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5464 return ERROR_NOT_ENOUGH_MEMORY;
5466 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5468 DEBUG(4,("printer driver directory: [%s]\n", path));
5470 fill_driverdir_1(info, path);
5472 *needed += spoolss_size_driverdir_info_1(info);
5474 if (!alloc_buffer_size(buffer, *needed)) {
5476 return ERROR_INSUFFICIENT_BUFFER;
5479 new_smb_io_driverdir_1("", buffer, info, 0);
5483 if (*needed > offered)
5484 return ERROR_INSUFFICIENT_BUFFER;
5486 return NT_STATUS_NO_PROBLEMO;
5489 /****************************************************************************
5490 ****************************************************************************/
5491 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5492 NEW_BUFFER *buffer, uint32 offered,
5495 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5501 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5503 return ERROR_INVALID_LEVEL;
5507 /****************************************************************************
5508 ****************************************************************************/
5509 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5510 uint32 in_value_len, uint32 in_data_len,
5511 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5513 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5515 NT_PRINTER_INFO_LEVEL *printer = NULL;
5520 uint32 biggest_valuesize;
5521 uint32 biggest_datasize;
5523 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5528 ZERO_STRUCT(printer);
5530 *out_max_value_len=0;
5536 *out_max_data_len=0;
5540 DEBUG(5,("spoolss_enumprinterdata\n"));
5542 if (!OPEN_HANDLE(Printer)) {
5543 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5544 return ERROR_INVALID_HANDLE;
5547 if (!get_printer_snum(handle, &snum))
5548 return ERROR_INVALID_HANDLE;
5550 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5551 return ERROR_INVALID_HANDLE;
5554 * The NT machine wants to know the biggest size of value and data
5556 * cf: MSDN EnumPrinterData remark section
5558 if ( (in_value_len==0) && (in_data_len==0) ) {
5559 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5563 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5564 * if this parameter size doesn't exist.
5565 * Ok - my opinion here is that the client is not asking for the greatest
5566 * possible size of all the parameters, but is asking specifically for the size needed
5567 * for this specific parameter. In that case we can remove the loop below and
5568 * simplify this lookup code considerably. JF - comments welcome. JRA.
5571 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5573 free_a_printer(&printer, 2);
5574 return ERROR_NO_MORE_ITEMS;
5582 biggest_valuesize=0;
5585 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5586 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5587 if (data_len > biggest_datasize) biggest_datasize=data_len;
5589 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5597 * I think this is correct, it doesn't break APW and
5598 * allows Gerald's Win32 test programs to work correctly,
5599 * but may need altering.... JRA.
5602 if (param_index == 0) {
5603 /* No parameters found. */
5604 free_a_printer(&printer, 2);
5605 return ERROR_NO_MORE_ITEMS;
5608 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5609 *out_value_len=2*(1+biggest_valuesize);
5610 *out_data_len=biggest_datasize;
5612 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5614 free_a_printer(&printer, 2);
5615 return NT_STATUS_NO_PROBLEMO;
5619 * the value len is wrong in NT sp3
5620 * that's the number of bytes not the number of unicode chars
5623 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5625 free_a_printer(&printer, 2);
5626 return ERROR_NO_MORE_ITEMS;
5629 free_a_printer(&printer, 2);
5633 * - counted in bytes in the request
5634 * - counted in UNICODE chars in the max reply
5635 * - counted in bytes in the real size
5637 * take a pause *before* coding not *during* coding
5640 *out_max_value_len=(in_value_len/sizeof(uint16));
5641 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5643 return ERROR_NOT_ENOUGH_MEMORY;
5646 ZERO_STRUCTP(*out_value);
5647 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5651 /* the data is counted in bytes */
5652 *out_max_data_len=in_data_len;
5653 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5655 return ERROR_NOT_ENOUGH_MEMORY;
5658 memset(*data_out,'\0',in_data_len);
5659 memcpy(*data_out, data, (size_t)data_len);
5660 *out_data_len=data_len;
5664 return NT_STATUS_NO_PROBLEMO;
5667 /****************************************************************************
5668 ****************************************************************************/
5669 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5670 const UNISTR2 *value,
5675 uint32 numeric_data)
5677 NT_PRINTER_INFO_LEVEL *printer = NULL;
5678 NT_PRINTER_PARAM *param = NULL, old_param;
5680 uint32 status = 0x0;
5681 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5683 DEBUG(5,("spoolss_setprinterdata\n"));
5685 if (!OPEN_HANDLE(Printer)) {
5686 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5687 return ERROR_INVALID_HANDLE;
5690 if (!get_printer_snum(handle, &snum))
5691 return ERROR_INVALID_HANDLE;
5693 status = get_a_printer(&printer, 2, lp_servicename(snum));
5695 return ERROR_INVALID_NAME;
5697 convert_specific_param(¶m, value , type, data, real_len);
5699 /* Check if we are making any changes or not. Return true if
5700 nothing is actually changing. */
5702 ZERO_STRUCT(old_param);
5704 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5705 &old_param.type, (unsigned int *)&old_param.data_len)) {
5707 if (param->type == old_param.type &&
5708 param->data_len == old_param.data_len &&
5709 memcmp(param->data, old_param.data,
5710 old_param.data_len) == 0) {
5712 DEBUG(3, ("setprinterdata hasn't changed\n"));
5713 status = NT_STATUS_NO_PROBLEMO;
5720 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5721 DEBUG(3, ("security descriptor change denied by existing "
5722 "security descriptor\n"));
5723 status = ERROR_ACCESS_DENIED;
5727 unlink_specific_param_if_exist(printer->info_2, param);
5729 add_a_specific_param(printer->info_2, ¶m);
5730 status = mod_a_printer(*printer, 2);
5733 free_a_printer(&printer, 2);
5735 free_nt_printer_param(¶m);
5736 safe_free(old_param.data);
5741 /****************************************************************************
5742 ****************************************************************************/
5743 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5745 NT_PRINTER_INFO_LEVEL *printer = NULL;
5746 NT_PRINTER_PARAM param;
5748 uint32 status = 0x0;
5749 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5751 DEBUG(5,("spoolss_deleteprinterdata\n"));
5753 if (!OPEN_HANDLE(Printer)) {
5754 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5755 return ERROR_INVALID_HANDLE;
5758 if (!get_printer_snum(handle, &snum))
5759 return ERROR_INVALID_HANDLE;
5761 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5762 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
5763 "change denied by existing security descriptor\n"));
5764 return ERROR_ACCESS_DENIED;
5767 status = get_a_printer(&printer, 2, lp_servicename(snum));
5769 return ERROR_INVALID_NAME;
5771 ZERO_STRUCTP(¶m);
5772 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5774 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5775 status = ERROR_INVALID_PARAMETER;
5777 status = mod_a_printer(*printer, 2);
5779 free_a_printer(&printer, 2);
5783 /****************************************************************************
5784 ****************************************************************************/
5785 uint32 _spoolss_addform( POLICY_HND *handle,
5790 nt_forms_struct *list=NULL;
5791 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5793 DEBUG(5,("spoolss_addform\n"));
5795 if (!OPEN_HANDLE(Printer)) {
5796 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5797 return ERROR_INVALID_HANDLE;
5800 count=get_ntforms(&list);
5801 if(!add_a_form(&list, form, &count))
5802 return ERROR_NOT_ENOUGH_MEMORY;
5803 write_ntforms(&list, count);
5810 /****************************************************************************
5811 ****************************************************************************/
5812 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5816 nt_forms_struct *list=NULL;
5817 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5819 DEBUG(5,("spoolss_deleteform\n"));
5821 if (!OPEN_HANDLE(Printer)) {
5822 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5823 return ERROR_INVALID_HANDLE;
5826 count = get_ntforms(&list);
5827 if(!delete_a_form(&list, form_name, &count, &ret))
5828 return ERROR_INVALID_PARAMETER;
5835 /****************************************************************************
5836 ****************************************************************************/
5837 uint32 _spoolss_setform( POLICY_HND *handle,
5838 const UNISTR2 *uni_name,
5843 nt_forms_struct *list=NULL;
5844 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5846 DEBUG(5,("spoolss_setform\n"));
5848 if (!OPEN_HANDLE(Printer)) {
5849 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5850 return ERROR_INVALID_HANDLE;
5852 count=get_ntforms(&list);
5853 update_a_form(&list, form, count);
5854 write_ntforms(&list, count);
5861 /****************************************************************************
5862 enumprintprocessors level 1.
5863 ****************************************************************************/
5864 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5866 PRINTPROCESSOR_1 *info_1=NULL;
5868 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5869 return ERROR_NOT_ENOUGH_MEMORY;
5873 init_unistr(&info_1->name, "winprint");
5875 *needed += spoolss_size_printprocessor_info_1(info_1);
5877 if (!alloc_buffer_size(buffer, *needed))
5878 return ERROR_INSUFFICIENT_BUFFER;
5880 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5884 if (*needed > offered) {
5886 return ERROR_INSUFFICIENT_BUFFER;
5889 return NT_STATUS_NO_PROBLEMO;
5892 /****************************************************************************
5893 ****************************************************************************/
5894 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5895 NEW_BUFFER *buffer, uint32 offered,
5896 uint32 *needed, uint32 *returned)
5898 DEBUG(5,("spoolss_enumprintprocessors\n"));
5901 * Enumerate the print processors ...
5903 * Just reply with "winprint", to keep NT happy
5904 * and I can use my nice printer checker.
5912 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5914 return ERROR_INVALID_LEVEL;
5918 /****************************************************************************
5919 enumprintprocdatatypes level 1.
5920 ****************************************************************************/
5921 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5923 PRINTPROCDATATYPE_1 *info_1=NULL;
5925 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5926 return ERROR_NOT_ENOUGH_MEMORY;
5930 init_unistr(&info_1->name, "RAW");
5932 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5934 if (!alloc_buffer_size(buffer, *needed))
5935 return ERROR_INSUFFICIENT_BUFFER;
5937 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5941 if (*needed > offered) {
5943 return ERROR_INSUFFICIENT_BUFFER;
5946 return NT_STATUS_NO_PROBLEMO;
5949 /****************************************************************************
5950 ****************************************************************************/
5951 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5952 NEW_BUFFER *buffer, uint32 offered,
5953 uint32 *needed, uint32 *returned)
5955 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5962 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5964 return ERROR_INVALID_LEVEL;
5968 /****************************************************************************
5969 enumprintmonitors level 1.
5970 ****************************************************************************/
5971 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5973 PRINTMONITOR_1 *info_1=NULL;
5975 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5976 return ERROR_NOT_ENOUGH_MEMORY;
5980 init_unistr(&info_1->name, "Local Port");
5982 *needed += spoolss_size_printmonitor_info_1(info_1);
5984 if (!alloc_buffer_size(buffer, *needed))
5985 return ERROR_INSUFFICIENT_BUFFER;
5987 smb_io_printmonitor_info_1("", buffer, info_1, 0);
5991 if (*needed > offered) {
5993 return ERROR_INSUFFICIENT_BUFFER;
5996 return NT_STATUS_NO_PROBLEMO;
5999 /****************************************************************************
6000 enumprintmonitors level 2.
6001 ****************************************************************************/
6002 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6004 PRINTMONITOR_2 *info_2=NULL;
6006 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6007 return ERROR_NOT_ENOUGH_MEMORY;
6011 init_unistr(&info_2->name, "Local Port");
6012 init_unistr(&info_2->environment, "Windows NT X86");
6013 init_unistr(&info_2->dll_name, "localmon.dll");
6015 *needed += spoolss_size_printmonitor_info_2(info_2);
6017 if (!alloc_buffer_size(buffer, *needed))
6018 return ERROR_INSUFFICIENT_BUFFER;
6020 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6024 if (*needed > offered) {
6026 return ERROR_INSUFFICIENT_BUFFER;
6029 return NT_STATUS_NO_PROBLEMO;
6032 /****************************************************************************
6033 ****************************************************************************/
6034 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
6035 NEW_BUFFER *buffer, uint32 offered,
6036 uint32 *needed, uint32 *returned)
6038 DEBUG(5,("spoolss_enumprintmonitors\n"));
6041 * Enumerate the print monitors ...
6043 * Just reply with "Local Port", to keep NT happy
6044 * and I can use my nice printer checker.
6052 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6054 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6056 return ERROR_INVALID_LEVEL;
6060 /****************************************************************************
6061 ****************************************************************************/
6062 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6066 JOB_INFO_1 *info_1=NULL;
6068 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6070 if (info_1 == NULL) {
6072 return ERROR_NOT_ENOUGH_MEMORY;
6075 for (i=0; i<count && found==False; i++) {
6076 if (queue[i].job==(int)jobid)
6083 /* I shoud reply something else ... I can't find the good one */
6084 return NT_STATUS_NO_PROBLEMO;
6087 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6091 *needed += spoolss_size_job_info_1(info_1);
6093 if (!alloc_buffer_size(buffer, *needed)) {
6095 return ERROR_INSUFFICIENT_BUFFER;
6098 new_smb_io_job_info_1("", buffer, info_1, 0);
6102 if (*needed > offered)
6103 return ERROR_INSUFFICIENT_BUFFER;
6105 return NT_STATUS_NO_PROBLEMO;
6109 /****************************************************************************
6110 ****************************************************************************/
6111 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6116 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6118 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6120 ZERO_STRUCTP(info_2);
6122 if (info_2 == NULL) {
6124 return ERROR_NOT_ENOUGH_MEMORY;
6127 for (i=0; i<count && found==False; i++) {
6128 if (queue[i].job==(int)jobid)
6135 /* I shoud reply something else ... I can't find the good one */
6136 return NT_STATUS_NO_PROBLEMO;
6139 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6141 return ERROR_NOT_ENOUGH_MEMORY;
6144 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6146 free_a_printer(&ntprinter, 2);
6149 *needed += spoolss_size_job_info_2(info_2);
6151 if (!alloc_buffer_size(buffer, *needed)) {
6153 return ERROR_INSUFFICIENT_BUFFER;
6156 new_smb_io_job_info_2("", buffer, info_2, 0);
6158 free_job_info_2(info_2);
6161 if (*needed > offered)
6162 return ERROR_INSUFFICIENT_BUFFER;
6164 return NT_STATUS_NO_PROBLEMO;
6167 /****************************************************************************
6168 ****************************************************************************/
6169 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
6170 NEW_BUFFER *buffer, uint32 offered,
6175 print_queue_struct *queue=NULL;
6176 print_status_struct prt_status;
6178 DEBUG(5,("spoolss_getjob\n"));
6180 memset(&prt_status, 0, sizeof(prt_status));
6184 if (!get_printer_snum(handle, &snum))
6185 return ERROR_INVALID_HANDLE;
6187 count = print_queue_status(snum, &queue, &prt_status);
6189 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6190 count, prt_status.status, prt_status.message));
6194 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6196 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6199 return ERROR_INVALID_LEVEL;