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 Return a user struct for a pipe user.
663 ****************************************************************************/
665 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
667 if (p->ntlmssp_auth_validated) {
668 memcpy(user, &p->pipe_user, sizeof(struct current_user));
670 extern struct current_user current_user;
671 memcpy(user, ¤t_user, sizeof(struct current_user));
677 /********************************************************************
678 * spoolss_open_printer
680 * called from the spoolss dispatcher
681 ********************************************************************/
682 uint32 _spoolss_open_printer_ex( const UNISTR2 *printername, pipes_struct *p,
683 PRINTER_DEFAULT *printer_default,
684 uint32 user_switch, SPOOL_USER_CTR user_ctr,
687 uint32 result = NT_STATUS_NO_PROBLEMO;
690 struct current_user user;
692 if (printername == NULL)
693 return ERROR_INVALID_PRINTER_NAME;
695 /* some sanity check because you can open a printer or a print server */
696 /* aka: \\server\printer or \\server */
697 unistr2_to_ascii(name, printername, sizeof(name)-1);
699 DEBUGADD(3,("checking name: %s\n",name));
701 if (!open_printer_hnd(handle, name))
702 return ERROR_INVALID_PRINTER_NAME;
705 if (printer_default->datatype_ptr != NULL)
707 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
708 set_printer_hnd_datatype(handle, datatype);
711 set_printer_hnd_datatype(handle, "");
714 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
715 close_printer_handle(handle);
716 return ERROR_ACCESS_DENIED;
720 First case: the user is opening the print server:
722 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
723 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
725 Then both Win2k and WinNT clients try an OpenPrinterEx with
726 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
727 or if the user is listed in the smb.conf printer admin parameter.
729 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
730 client view printer folder, but does not show the MSAPW.
732 Note: this test needs code to check access rights here too. Jeremy
733 could you look at this?
736 Second case: the user is opening a printer:
737 NT doesn't let us connect to a printer if the connecting user
738 doesn't have print permission.
742 get_current_user(&user, p);
744 if (handle_is_printserver(handle) ) {
745 if (printer_default->access_required == 0) {
746 return NT_STATUS_NO_PROBLEMO;
748 else if ( (printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
750 if (!lp_ms_add_printer_wizard()) {
751 close_printer_handle(handle);
752 return ERROR_ACCESS_DENIED;
754 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
755 return NT_STATUS_NO_PROBLEMO;
757 close_printer_handle(handle);
758 return ERROR_ACCESS_DENIED;
762 return NT_STATUS_NO_PROBLEMO;
765 if (!get_printer_snum(handle, &snum))
766 return ERROR_INVALID_HANDLE;
768 /* map an empty access mask to the minimum access mask */
769 if (printer_default->access_required == 0x0)
770 printer_default->access_required = PRINTER_ACCESS_USE;
772 if (!print_access_check(&user, snum, printer_default->access_required)) {
773 DEBUG(3, ("access DENIED for printer open\n"));
774 close_printer_handle(handle);
775 return ERROR_ACCESS_DENIED;
779 * If we have a default device pointer in the
780 * printer_default struct, then we need to get
781 * the printer info from the tdb and if there is
782 * no default devicemode there then we do a *SET*
783 * here ! This is insanity.... JRA.
786 if (printer_default->devmode_cont.devmode != NULL) {
787 result = printer_write_default_dev( snum, printer_default);
789 close_printer_handle(handle);
794 return NT_STATUS_NO_PROBLEMO;
799 /****************************************************************************
800 ****************************************************************************/
801 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
802 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
806 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
815 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
816 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
820 printer->info_3=NULL;
821 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
824 printer->info_6=NULL;
825 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
834 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
835 NT_DEVICEMODE **pp_nt_devmode)
837 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
840 * Ensure nt_devmode is a valid pointer
841 * as we will be overwriting it.
844 if (nt_devmode == NULL)
845 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
848 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
849 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
851 nt_devmode->specversion=devmode->specversion;
852 nt_devmode->driverversion=devmode->driverversion;
853 nt_devmode->size=devmode->size;
854 nt_devmode->fields=devmode->fields;
855 nt_devmode->orientation=devmode->orientation;
856 nt_devmode->papersize=devmode->papersize;
857 nt_devmode->paperlength=devmode->paperlength;
858 nt_devmode->paperwidth=devmode->paperwidth;
859 nt_devmode->scale=devmode->scale;
860 nt_devmode->copies=devmode->copies;
861 nt_devmode->defaultsource=devmode->defaultsource;
862 nt_devmode->printquality=devmode->printquality;
863 nt_devmode->color=devmode->color;
864 nt_devmode->duplex=devmode->duplex;
865 nt_devmode->yresolution=devmode->yresolution;
866 nt_devmode->ttoption=devmode->ttoption;
867 nt_devmode->collate=devmode->collate;
869 nt_devmode->logpixels=devmode->logpixels;
870 nt_devmode->bitsperpel=devmode->bitsperpel;
871 nt_devmode->pelswidth=devmode->pelswidth;
872 nt_devmode->pelsheight=devmode->pelsheight;
873 nt_devmode->displayflags=devmode->displayflags;
874 nt_devmode->displayfrequency=devmode->displayfrequency;
875 nt_devmode->icmmethod=devmode->icmmethod;
876 nt_devmode->icmintent=devmode->icmintent;
877 nt_devmode->mediatype=devmode->mediatype;
878 nt_devmode->dithertype=devmode->dithertype;
879 nt_devmode->reserved1=devmode->reserved1;
880 nt_devmode->reserved2=devmode->reserved2;
881 nt_devmode->panningwidth=devmode->panningwidth;
882 nt_devmode->panningheight=devmode->panningheight;
885 * Only change private and driverextra if the incoming devmode
886 * has a new one. JRA.
889 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
890 safe_free(nt_devmode->private);
891 nt_devmode->driverextra=devmode->driverextra;
892 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
894 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
897 *pp_nt_devmode = nt_devmode;
902 /********************************************************************
903 * api_spoolss_closeprinter
904 ********************************************************************/
905 uint32 _spoolss_closeprinter(POLICY_HND *handle)
907 Printer_entry *Printer=find_printer_index_by_hnd(handle);
909 if (Printer && Printer->document_started)
910 _spoolss_enddocprinter(handle); /* print job was not closed */
912 if (!close_printer_handle(handle))
913 return ERROR_INVALID_HANDLE;
915 return NT_STATUS_NO_PROBLEMO;
918 /********************************************************************
919 * api_spoolss_deleteprinter
920 ********************************************************************/
921 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
923 Printer_entry *Printer=find_printer_index_by_hnd(handle);
926 if (Printer && Printer->document_started)
927 _spoolss_enddocprinter(handle); /* print job was not closed */
929 result = delete_printer_handle(handle);
931 if (result == ERROR_SUCCESS) {
932 srv_spoolss_sendnotify(handle);
938 /********************************************************************
939 GetPrinterData on a printer server Handle.
940 ********************************************************************/
941 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
945 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
947 if (!strcmp(value, "BeepEnabled")) {
949 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
951 SIVAL(*data, 0, 0x01);
956 if (!strcmp(value, "EventLog")) {
958 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
960 SIVAL(*data, 0, 0x1B);
965 if (!strcmp(value, "NetPopup")) {
967 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
969 SIVAL(*data, 0, 0x01);
974 if (!strcmp(value, "MajorVersion")) {
976 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
978 SIVAL(*data, 0, 0x02);
983 if (!strcmp(value, "DefaultSpoolDirectory")) {
984 pstring string="You are using a Samba server";
986 *needed = 2*(strlen(string)+1);
987 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
989 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
991 /* it's done by hand ready to go on the wire */
992 for (i=0; i<strlen(string); i++) {
993 (*data)[2*i]=string[i];
999 if (!strcmp(value, "Architecture")) {
1000 pstring string="Windows NT x86";
1002 *needed = 2*(strlen(string)+1);
1003 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1005 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1006 for (i=0; i<strlen(string); i++) {
1007 (*data)[2*i]=string[i];
1008 (*data)[2*i+1]='\0';
1016 /********************************************************************
1017 GetPrinterData on a printer Handle.
1018 ********************************************************************/
1019 static BOOL getprinterdata_printer(POLICY_HND *handle,
1020 fstring value, uint32 *type,
1021 uint8 **data, uint32 *needed, uint32 in_size )
1023 NT_PRINTER_INFO_LEVEL *printer = NULL;
1027 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1029 DEBUG(5,("getprinterdata_printer\n"));
1031 if (!OPEN_HANDLE(Printer)) {
1032 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1036 if(!get_printer_snum(handle, &snum))
1039 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1042 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1043 free_a_printer(&printer, 2);
1047 free_a_printer(&printer, 2);
1049 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1052 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
1056 memset(*data, 0, in_size *sizeof(uint8));
1057 /* copy the min(in_size, len) */
1058 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1065 DEBUG(5,("getprinterdata_printer:copy done\n"));
1072 /********************************************************************
1073 * spoolss_getprinterdata
1074 ********************************************************************/
1075 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
1084 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1087 * Reminder: when it's a string, the length is in BYTES
1088 * even if UNICODE is negociated.
1095 /* in case of problem, return some default values */
1099 DEBUG(4,("_spoolss_getprinterdata\n"));
1101 if (!OPEN_HANDLE(Printer)) {
1102 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1103 return ERROR_NOT_ENOUGH_MEMORY;
1104 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1105 return ERROR_INVALID_HANDLE;
1108 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1110 if (handle_is_printserver(handle))
1111 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1113 found= getprinterdata_printer(handle, value, type, data, needed, *out_size);
1116 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1117 /* reply this param doesn't exist */
1119 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
1120 return ERROR_NOT_ENOUGH_MEMORY;
1121 memset(*data, '\0', *out_size*sizeof(uint8));
1126 return ERROR_INVALID_PARAMETER;
1129 if (*needed > *out_size)
1130 return ERROR_MORE_DATA;
1132 return NT_STATUS_NO_PROBLEMO;
1136 /***************************************************************************
1137 connect to the client
1138 ****************************************************************************/
1139 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1144 * If it's the first connection, contact the client
1145 * and connect to the IPC$ share anonumously
1147 if (smb_connections==0) {
1148 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1150 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1156 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1162 /********************************************************************
1164 * ReplyFindFirstPrinterChangeNotifyEx
1166 * jfmxxxx: before replying OK: status=0
1167 * should do a rpc call to the workstation asking ReplyOpenPrinter
1168 * have to code it, later.
1170 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1171 * called from api_spoolss_rffpcnex
1172 ********************************************************************/
1173 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1174 const UNISTR2 *localmachine, uint32 printerlocal,
1175 SPOOL_NOTIFY_OPTION *option)
1177 /* store the notify value in the printer struct */
1179 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1181 if (!OPEN_HANDLE(Printer)) {
1182 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1183 return ERROR_INVALID_HANDLE;
1186 Printer->notify.flags=flags;
1187 Printer->notify.options=options;
1188 Printer->notify.printerlocal=printerlocal;
1189 Printer->notify.option=option;
1190 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1192 /* connect to the client machine and send a ReplyOpenPrinter */
1193 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1194 Printer->notify.printerlocal, 1,
1195 &Printer->notify.client_hnd))
1196 Printer->notify.client_connected=True;
1198 return NT_STATUS_NO_PROBLEMO;
1201 /*******************************************************************
1202 * fill a notify_info_data with the servername
1203 ********************************************************************/
1204 static void spoolss_notify_server_name(int snum,
1205 SPOOL_NOTIFY_INFO_DATA *data,
1206 print_queue_struct *queue,
1207 NT_PRINTER_INFO_LEVEL *printer,
1208 TALLOC_CTX *mem_ctx)
1210 pstring temp_name, temp;
1213 snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1215 len = (uint32)dos_PutUniCode(temp, temp_name, 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 printername (not including the servername).
1230 ********************************************************************/
1231 static void spoolss_notify_printer_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 /* the notify name should not contain the \\server\ part */
1241 char *p = strrchr(printer->info_2->printername, '\\');
1244 p = printer->info_2->printername;
1249 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1251 data->notify_data.data.length = len / 2 - 1;
1252 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1254 if (!data->notify_data.data.string) {
1255 data->notify_data.data.length = 0;
1259 memcpy(data->notify_data.data.string, temp, len);
1262 /*******************************************************************
1263 * fill a notify_info_data with the servicename
1264 ********************************************************************/
1265 static void spoolss_notify_share_name(int snum,
1266 SPOOL_NOTIFY_INFO_DATA *data,
1267 print_queue_struct *queue,
1268 NT_PRINTER_INFO_LEVEL *printer,
1269 TALLOC_CTX *mem_ctx)
1274 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1275 sizeof(temp) - 2, True);
1277 data->notify_data.data.length = len / 2 - 1;
1278 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1280 if (!data->notify_data.data.string) {
1281 data->notify_data.data.length = 0;
1285 memcpy(data->notify_data.data.string, temp, len);
1288 /*******************************************************************
1289 * fill a notify_info_data with the port name
1290 ********************************************************************/
1291 static void spoolss_notify_port_name(int snum,
1292 SPOOL_NOTIFY_INFO_DATA *data,
1293 print_queue_struct *queue,
1294 NT_PRINTER_INFO_LEVEL *printer,
1295 TALLOC_CTX *mem_ctx)
1300 /* even if it's strange, that's consistant in all the code */
1302 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1303 sizeof(temp) - 2, True);
1305 data->notify_data.data.length = len / 2 - 1;
1306 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1308 if (!data->notify_data.data.string) {
1309 data->notify_data.data.length = 0;
1313 memcpy(data->notify_data.data.string, temp, len);
1316 /*******************************************************************
1317 * fill a notify_info_data with the printername
1318 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1319 * but it doesn't exist, have to see what to do
1320 ********************************************************************/
1321 static void spoolss_notify_driver_name(int snum,
1322 SPOOL_NOTIFY_INFO_DATA *data,
1323 print_queue_struct *queue,
1324 NT_PRINTER_INFO_LEVEL *printer,
1325 TALLOC_CTX *mem_ctx)
1330 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1331 sizeof(temp) - 2, True);
1333 data->notify_data.data.length = len / 2 - 1;
1334 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1336 if (!data->notify_data.data.string) {
1337 data->notify_data.data.length = 0;
1341 memcpy(data->notify_data.data.string, temp, len);
1344 /*******************************************************************
1345 * fill a notify_info_data with the comment
1346 ********************************************************************/
1347 static void spoolss_notify_comment(int snum,
1348 SPOOL_NOTIFY_INFO_DATA *data,
1349 print_queue_struct *queue,
1350 NT_PRINTER_INFO_LEVEL *printer,
1351 TALLOC_CTX *mem_ctx)
1356 if (*printer->info_2->comment == '\0')
1357 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1358 sizeof(temp) - 2, True);
1360 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1361 sizeof(temp) - 2, True);
1363 data->notify_data.data.length = len / 2 - 1;
1364 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1366 if (!data->notify_data.data.string) {
1367 data->notify_data.data.length = 0;
1371 memcpy(data->notify_data.data.string, temp, len);
1374 /*******************************************************************
1375 * fill a notify_info_data with the comment
1376 * jfm:xxxx incorrect, have to create a new smb.conf option
1377 * location = "Room 1, floor 2, building 3"
1378 ********************************************************************/
1379 static void spoolss_notify_location(int snum,
1380 SPOOL_NOTIFY_INFO_DATA *data,
1381 print_queue_struct *queue,
1382 NT_PRINTER_INFO_LEVEL *printer,
1383 TALLOC_CTX *mem_ctx)
1388 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1389 sizeof(temp) - 2, True);
1391 data->notify_data.data.length = len / 2 - 1;
1392 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1394 if (!data->notify_data.data.string) {
1395 data->notify_data.data.length = 0;
1399 memcpy(data->notify_data.data.string, temp, len);
1402 /*******************************************************************
1403 * fill a notify_info_data with the device mode
1404 * jfm:xxxx don't to it for know but that's a real problem !!!
1405 ********************************************************************/
1406 static void spoolss_notify_devmode(int snum,
1407 SPOOL_NOTIFY_INFO_DATA *data,
1408 print_queue_struct *queue,
1409 NT_PRINTER_INFO_LEVEL *printer,
1410 TALLOC_CTX *mem_ctx)
1414 /*******************************************************************
1415 * fill a notify_info_data with the separator file name
1416 * jfm:xxxx just return no file could add an option to smb.conf
1417 * separator file = "separator.txt"
1418 ********************************************************************/
1419 static void spoolss_notify_sepfile(int snum,
1420 SPOOL_NOTIFY_INFO_DATA *data,
1421 print_queue_struct *queue,
1422 NT_PRINTER_INFO_LEVEL *printer,
1423 TALLOC_CTX *mem_ctx)
1428 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1429 sizeof(temp) - 2, True);
1431 data->notify_data.data.length = len / 2 - 1;
1432 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1434 if (!data->notify_data.data.string) {
1435 data->notify_data.data.length = 0;
1439 memcpy(data->notify_data.data.string, temp, len);
1442 /*******************************************************************
1443 * fill a notify_info_data with the print processor
1444 * jfm:xxxx return always winprint to indicate we don't do anything to it
1445 ********************************************************************/
1446 static void spoolss_notify_print_processor(int snum,
1447 SPOOL_NOTIFY_INFO_DATA *data,
1448 print_queue_struct *queue,
1449 NT_PRINTER_INFO_LEVEL *printer,
1450 TALLOC_CTX *mem_ctx)
1455 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
1456 sizeof(temp) - 2, True);
1458 data->notify_data.data.length = len / 2 - 1;
1459 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1461 if (!data->notify_data.data.string) {
1462 data->notify_data.data.length = 0;
1466 memcpy(data->notify_data.data.string, temp, len);
1469 /*******************************************************************
1470 * fill a notify_info_data with the print processor options
1471 * jfm:xxxx send an empty string
1472 ********************************************************************/
1473 static void spoolss_notify_parameters(int snum,
1474 SPOOL_NOTIFY_INFO_DATA *data,
1475 print_queue_struct *queue,
1476 NT_PRINTER_INFO_LEVEL *printer,
1477 TALLOC_CTX *mem_ctx)
1482 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1483 sizeof(temp) - 2, True);
1485 data->notify_data.data.length = len / 2 - 1;
1486 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1488 if (!data->notify_data.data.string) {
1489 data->notify_data.data.length = 0;
1493 memcpy(data->notify_data.data.string, temp, len);
1496 /*******************************************************************
1497 * fill a notify_info_data with the data type
1498 * jfm:xxxx always send RAW as data type
1499 ********************************************************************/
1500 static void spoolss_notify_datatype(int snum,
1501 SPOOL_NOTIFY_INFO_DATA *data,
1502 print_queue_struct *queue,
1503 NT_PRINTER_INFO_LEVEL *printer,
1504 TALLOC_CTX *mem_ctx)
1509 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1510 sizeof(pstring) - 2, True);
1512 data->notify_data.data.length = len / 2 - 1;
1513 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1515 if (!data->notify_data.data.string) {
1516 data->notify_data.data.length = 0;
1520 memcpy(data->notify_data.data.string, temp, len);
1523 /*******************************************************************
1524 * fill a notify_info_data with the security descriptor
1525 * jfm:xxxx send an null pointer to say no security desc
1526 * have to implement security before !
1527 ********************************************************************/
1528 static void spoolss_notify_security_desc(int snum,
1529 SPOOL_NOTIFY_INFO_DATA *data,
1530 print_queue_struct *queue,
1531 NT_PRINTER_INFO_LEVEL *printer,
1532 TALLOC_CTX *mem_ctx)
1534 data->notify_data.data.length=0;
1535 data->notify_data.data.string = NULL;
1538 /*******************************************************************
1539 * fill a notify_info_data with the attributes
1540 * jfm:xxxx a samba printer is always shared
1541 ********************************************************************/
1542 static void spoolss_notify_attributes(int snum,
1543 SPOOL_NOTIFY_INFO_DATA *data,
1544 print_queue_struct *queue,
1545 NT_PRINTER_INFO_LEVEL *printer,
1546 TALLOC_CTX *mem_ctx)
1548 data->notify_data.value[0] = printer->info_2->attributes;
1551 /*******************************************************************
1552 * fill a notify_info_data with the priority
1553 ********************************************************************/
1554 static void spoolss_notify_priority(int snum,
1555 SPOOL_NOTIFY_INFO_DATA *data,
1556 print_queue_struct *queue,
1557 NT_PRINTER_INFO_LEVEL *printer,
1558 TALLOC_CTX *mem_ctx)
1560 data->notify_data.value[0] = printer->info_2->priority;
1563 /*******************************************************************
1564 * fill a notify_info_data with the default priority
1565 ********************************************************************/
1566 static void spoolss_notify_default_priority(int snum,
1567 SPOOL_NOTIFY_INFO_DATA *data,
1568 print_queue_struct *queue,
1569 NT_PRINTER_INFO_LEVEL *printer,
1570 TALLOC_CTX *mem_ctx)
1572 data->notify_data.value[0] = printer->info_2->default_priority;
1575 /*******************************************************************
1576 * fill a notify_info_data with the start time
1577 ********************************************************************/
1578 static void spoolss_notify_start_time(int snum,
1579 SPOOL_NOTIFY_INFO_DATA *data,
1580 print_queue_struct *queue,
1581 NT_PRINTER_INFO_LEVEL *printer,
1582 TALLOC_CTX *mem_ctx)
1584 data->notify_data.value[0] = printer->info_2->starttime;
1587 /*******************************************************************
1588 * fill a notify_info_data with the until time
1589 ********************************************************************/
1590 static void spoolss_notify_until_time(int snum,
1591 SPOOL_NOTIFY_INFO_DATA *data,
1592 print_queue_struct *queue,
1593 NT_PRINTER_INFO_LEVEL *printer,
1594 TALLOC_CTX *mem_ctx)
1596 data->notify_data.value[0] = printer->info_2->untiltime;
1599 /*******************************************************************
1600 * fill a notify_info_data with the status
1601 ********************************************************************/
1602 static void spoolss_notify_status(int snum,
1603 SPOOL_NOTIFY_INFO_DATA *data,
1604 print_queue_struct *queue,
1605 NT_PRINTER_INFO_LEVEL *printer,
1606 TALLOC_CTX *mem_ctx)
1610 print_queue_struct *q=NULL;
1611 print_status_struct status;
1613 memset(&status, 0, sizeof(status));
1614 count = print_queue_status(snum, &q, &status);
1615 data->notify_data.value[0]=(uint32) status.status;
1619 /*******************************************************************
1620 * fill a notify_info_data with the number of jobs queued
1621 ********************************************************************/
1622 static void spoolss_notify_cjobs(int snum,
1623 SPOOL_NOTIFY_INFO_DATA *data,
1624 print_queue_struct *queue,
1625 NT_PRINTER_INFO_LEVEL *printer,
1626 TALLOC_CTX *mem_ctx)
1628 print_queue_struct *q=NULL;
1629 print_status_struct status;
1631 memset(&status, 0, sizeof(status));
1632 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1636 /*******************************************************************
1637 * fill a notify_info_data with the average ppm
1638 ********************************************************************/
1639 static void spoolss_notify_average_ppm(int snum,
1640 SPOOL_NOTIFY_INFO_DATA *data,
1641 print_queue_struct *queue,
1642 NT_PRINTER_INFO_LEVEL *printer,
1643 TALLOC_CTX *mem_ctx)
1645 /* always respond 8 pages per minutes */
1646 /* a little hard ! */
1647 data->notify_data.value[0] = printer->info_2->averageppm;
1650 /*******************************************************************
1651 * fill a notify_info_data with username
1652 ********************************************************************/
1653 static void spoolss_notify_username(int snum,
1654 SPOOL_NOTIFY_INFO_DATA *data,
1655 print_queue_struct *queue,
1656 NT_PRINTER_INFO_LEVEL *printer,
1657 TALLOC_CTX *mem_ctx)
1662 len = (uint32)dos_PutUniCode(temp, queue->user,
1663 sizeof(temp) - 2, True);
1665 data->notify_data.data.length = len / 2 - 1;
1666 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1668 if (!data->notify_data.data.string) {
1669 data->notify_data.data.length = 0;
1673 memcpy(data->notify_data.data.string, temp, len);
1676 /*******************************************************************
1677 * fill a notify_info_data with job status
1678 ********************************************************************/
1679 static void spoolss_notify_job_status(int snum,
1680 SPOOL_NOTIFY_INFO_DATA *data,
1681 print_queue_struct *queue,
1682 NT_PRINTER_INFO_LEVEL *printer,
1683 TALLOC_CTX *mem_ctx)
1685 data->notify_data.value[0]=nt_printj_status(queue->status);
1688 /*******************************************************************
1689 * fill a notify_info_data with job name
1690 ********************************************************************/
1691 static void spoolss_notify_job_name(int snum,
1692 SPOOL_NOTIFY_INFO_DATA *data,
1693 print_queue_struct *queue,
1694 NT_PRINTER_INFO_LEVEL *printer,
1695 TALLOC_CTX *mem_ctx)
1700 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1703 data->notify_data.data.length = len / 2 - 1;
1704 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1706 if (!data->notify_data.data.string) {
1707 data->notify_data.data.length = 0;
1711 memcpy(data->notify_data.data.string, temp, len);
1714 /*******************************************************************
1715 * fill a notify_info_data with job status
1716 ********************************************************************/
1717 static void spoolss_notify_job_status_string(int snum,
1718 SPOOL_NOTIFY_INFO_DATA *data,
1719 print_queue_struct *queue,
1720 NT_PRINTER_INFO_LEVEL *printer,
1721 TALLOC_CTX *mem_ctx)
1723 char *p = "unknown";
1727 switch (queue->status) {
1732 p = ""; /* NT provides the paused string */
1742 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1744 data->notify_data.data.length = len / 2 - 1;
1745 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1747 if (!data->notify_data.data.string) {
1748 data->notify_data.data.length = 0;
1752 memcpy(data->notify_data.data.string, temp, len);
1755 /*******************************************************************
1756 * fill a notify_info_data with job time
1757 ********************************************************************/
1758 static void spoolss_notify_job_time(int snum,
1759 SPOOL_NOTIFY_INFO_DATA *data,
1760 print_queue_struct *queue,
1761 NT_PRINTER_INFO_LEVEL *printer,
1762 TALLOC_CTX *mem_ctx)
1764 data->notify_data.value[0]=0x0;
1767 /*******************************************************************
1768 * fill a notify_info_data with job size
1769 ********************************************************************/
1770 static void spoolss_notify_job_size(int snum,
1771 SPOOL_NOTIFY_INFO_DATA *data,
1772 print_queue_struct *queue,
1773 NT_PRINTER_INFO_LEVEL *printer,
1774 TALLOC_CTX *mem_ctx)
1776 data->notify_data.value[0]=queue->size;
1779 /*******************************************************************
1780 * fill a notify_info_data with job position
1781 ********************************************************************/
1782 static void spoolss_notify_job_position(int snum,
1783 SPOOL_NOTIFY_INFO_DATA *data,
1784 print_queue_struct *queue,
1785 NT_PRINTER_INFO_LEVEL *printer,
1786 TALLOC_CTX *mem_ctx)
1788 data->notify_data.value[0]=queue->job;
1791 /*******************************************************************
1792 * fill a notify_info_data with submitted time
1793 ********************************************************************/
1794 static void spoolss_notify_submitted_time(int snum,
1795 SPOOL_NOTIFY_INFO_DATA *data,
1796 print_queue_struct *queue,
1797 NT_PRINTER_INFO_LEVEL *printer,
1798 TALLOC_CTX *mem_ctx)
1803 t=gmtime(&queue->time);
1805 len = sizeof(SYSTEMTIME);
1807 data->notify_data.data.length = len;
1808 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1810 if (!data->notify_data.data.string) {
1811 data->notify_data.data.length = 0;
1815 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1820 struct s_notify_info_data_table
1826 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1827 print_queue_struct *queue,
1828 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
1831 struct s_notify_info_data_table notify_info_data_table[] =
1833 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1834 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1835 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1836 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1837 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1838 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1839 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1840 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1841 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1842 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1843 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1844 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1845 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1846 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1847 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1848 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1849 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1850 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1851 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1852 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1853 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1854 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1855 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1856 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1857 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1858 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1859 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1860 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1861 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1862 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1863 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1864 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1865 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1866 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1867 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1868 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1869 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1870 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1871 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1872 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1873 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1874 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1875 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1876 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1877 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1878 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1879 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1880 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1881 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1882 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1883 { END, END, "", END, NULL }
1886 /*******************************************************************
1887 return the size of info_data structure
1888 ********************************************************************/
1889 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1893 while (notify_info_data_table[i].type != END)
1895 if ( (notify_info_data_table[i].type == type ) &&
1896 (notify_info_data_table[i].field == field ) )
1898 return (notify_info_data_table[i].size);
1905 /*******************************************************************
1906 return the type of notify_info_data
1907 ********************************************************************/
1908 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1912 while (notify_info_data_table[i].type != END)
1914 if ( (notify_info_data_table[i].type == type ) &&
1915 (notify_info_data_table[i].field == field ) )
1917 if (notify_info_data_table[i].size == POINTER)
1931 /****************************************************************************
1932 ****************************************************************************/
1933 static int search_notify(uint16 type, uint16 field, int *value)
1938 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1940 if ( (notify_info_data_table[j].type == type ) &&
1941 (notify_info_data_table[j].field == field ) )
1946 if ( found && (notify_info_data_table[j].fn != NULL) )
1952 /****************************************************************************
1953 ****************************************************************************/
1954 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1956 info_data->type = type;
1957 info_data->field = field;
1958 info_data->reserved = 0;
1960 info_data->size = size_of_notify_info_data(type, field);
1961 info_data->enc_type = type_of_notify_info_data(type, field);
1965 /*******************************************************************
1967 * fill a notify_info struct with info asked
1969 ********************************************************************/
1970 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
1971 snum, SPOOL_NOTIFY_OPTION_TYPE
1972 *option_type, uint32 id,
1973 TALLOC_CTX *mem_ctx)
1979 SPOOL_NOTIFY_INFO_DATA *current_data;
1980 NT_PRINTER_INFO_LEVEL *printer = NULL;
1981 print_queue_struct *queue=NULL;
1983 type=option_type->type;
1985 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1986 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1987 option_type->count, lp_servicename(snum)));
1989 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1992 for(field_num=0; field_num<option_type->count; field_num++) {
1993 field = option_type->fields[field_num];
1994 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1996 if (!search_notify(type, field, &j) )
1999 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2002 current_data=&info->data[info->count];
2004 construct_info_data(current_data, type, field, id);
2006 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2007 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2009 notify_info_data_table[j].fn(snum, current_data, queue,
2015 free_a_printer(&printer, 2);
2019 /*******************************************************************
2021 * fill a notify_info struct with info asked
2023 ********************************************************************/
2024 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2025 SPOOL_NOTIFY_INFO *info,
2026 NT_PRINTER_INFO_LEVEL *printer,
2027 int snum, SPOOL_NOTIFY_OPTION_TYPE
2028 *option_type, uint32 id,
2029 TALLOC_CTX *mem_ctx)
2035 SPOOL_NOTIFY_INFO_DATA *current_data;
2037 DEBUG(4,("construct_notify_jobs_info\n"));
2039 type = option_type->type;
2041 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2042 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2043 option_type->count));
2045 for(field_num=0; field_num<option_type->count; field_num++) {
2046 field = option_type->fields[field_num];
2048 if (!search_notify(type, field, &j) )
2051 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2055 current_data=&(info->data[info->count]);
2057 construct_info_data(current_data, type, field, id);
2058 notify_info_data_table[j].fn(snum, current_data, queue,
2067 * JFM: The enumeration is not that simple, it's even non obvious.
2069 * let's take an example: I want to monitor the PRINTER SERVER for
2070 * the printer's name and the number of jobs currently queued.
2071 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2072 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2074 * I have 3 printers on the back of my server.
2076 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2079 * 1 printer 1 name 1
2080 * 2 printer 1 cjob 1
2081 * 3 printer 2 name 2
2082 * 4 printer 2 cjob 2
2083 * 5 printer 3 name 3
2084 * 6 printer 3 name 3
2086 * that's the print server case, the printer case is even worse.
2091 /*******************************************************************
2093 * enumerate all printers on the printserver
2094 * fill a notify_info struct with info asked
2096 ********************************************************************/
2097 static uint32 printserver_notify_info(const POLICY_HND *hnd,
2098 SPOOL_NOTIFY_INFO *info,
2099 TALLOC_CTX *mem_ctx)
2102 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2103 int n_services=lp_numservices();
2106 SPOOL_NOTIFY_OPTION *option;
2107 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2109 DEBUG(4,("printserver_notify_info\n"));
2111 option=Printer->notify.option;
2117 for (i=0; i<option->count; i++) {
2118 option_type=&(option->ctr.type[i]);
2120 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2123 for (snum=0; snum<n_services; snum++)
2124 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2125 if (construct_notify_printer_info
2126 (info, snum, option_type, id, mem_ctx))
2131 * Debugging information, don't delete.
2134 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2135 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2136 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2138 for (i=0; i<info->count; i++) {
2139 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2140 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2141 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2145 return NT_STATUS_NO_PROBLEMO;
2148 /*******************************************************************
2150 * fill a notify_info struct with info asked
2152 ********************************************************************/
2153 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2154 TALLOC_CTX *mem_ctx)
2157 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2160 SPOOL_NOTIFY_OPTION *option;
2161 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2163 print_queue_struct *queue=NULL;
2164 print_status_struct status;
2166 DEBUG(4,("printer_notify_info\n"));
2168 option=Printer->notify.option;
2174 get_printer_snum(hnd, &snum);
2176 for (i=0; i<option->count; i++) {
2177 option_type=&option->ctr.type[i];
2179 switch ( option_type->type ) {
2180 case PRINTER_NOTIFY_TYPE:
2181 if(construct_notify_printer_info(info, snum,
2187 case JOB_NOTIFY_TYPE: {
2188 NT_PRINTER_INFO_LEVEL *printer = NULL;
2190 memset(&status, 0, sizeof(status));
2191 count = print_queue_status(snum, &queue, &status);
2193 if (get_a_printer(&printer, 2,
2194 lp_servicename(snum)) != 0)
2197 for (j=0; j<count; j++) {
2198 construct_notify_jobs_info(&queue[j], info,
2205 free_a_printer(&printer, 2);
2215 * Debugging information, don't delete.
2218 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2219 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2220 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2222 for (i=0; i<info->count; i++) {
2223 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2224 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2225 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2228 return NT_STATUS_NO_PROBLEMO;
2231 /********************************************************************
2233 ********************************************************************/
2234 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
2235 SPOOL_NOTIFY_OPTION *option, TALLOC_CTX *mem_ctx,
2236 SPOOL_NOTIFY_INFO *info)
2238 Printer_entry *Printer=find_printer_index_by_hnd(handle);
2239 uint32 result = ERROR_INVALID_HANDLE;
2241 if (!OPEN_HANDLE(Printer)) {
2242 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2243 OUR_HANDLE(handle)));
2247 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2249 /* jfm: the change value isn't used right now.
2250 * we will honour it when
2251 * a) we'll be able to send notification to the client
2252 * b) we'll have a way to communicate between the spoolss process.
2254 * same thing for option->flags
2255 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2256 * I don't have a global notification system, I'm sending back all the
2257 * informations even when _NOTHING_ has changed.
2260 /* just discard the SPOOL_NOTIFY_OPTION */
2262 safe_free(option->ctr.type);
2264 switch (Printer->printer_type) {
2265 case PRINTER_HANDLE_IS_PRINTSERVER:
2266 result = printserver_notify_info(handle, info,
2270 case PRINTER_HANDLE_IS_PRINTER:
2271 result = printer_notify_info(handle, info, mem_ctx);
2279 /********************************************************************
2280 * construct_printer_info_0
2281 * fill a printer_info_0 struct
2282 ********************************************************************/
2283 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2287 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2288 counter_printer_0 *session_counter;
2289 uint32 global_counter;
2293 print_queue_struct *queue=NULL;
2294 print_status_struct status;
2296 memset(&status, 0, sizeof(status));
2298 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2301 count = print_queue_status(snum, &queue, &status);
2303 /* check if we already have a counter for this printer */
2304 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2306 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2307 if (session_counter->snum == snum)
2311 /* it's the first time, add it to the list */
2312 if (session_counter==NULL) {
2313 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2314 free_a_printer(&ntprinter, 2);
2317 ZERO_STRUCTP(session_counter);
2318 session_counter->snum=snum;
2319 session_counter->counter=0;
2320 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2324 session_counter->counter++;
2327 * the global_counter should be stored in a TDB as it's common to all the clients
2328 * and should be zeroed on samba startup
2330 global_counter=session_counter->counter;
2332 pstrcpy(chaine,ntprinter->info_2->printername);
2334 init_unistr(&printer->printername, chaine);
2336 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2337 init_unistr(&printer->servername, chaine);
2339 printer->cjobs = count;
2340 printer->total_jobs = 0;
2341 printer->total_bytes = 0;
2343 setuptime = (time_t)ntprinter->info_2->setuptime;
2344 t=gmtime(&setuptime);
2346 printer->year = t->tm_year+1900;
2347 printer->month = t->tm_mon+1;
2348 printer->dayofweek = t->tm_wday;
2349 printer->day = t->tm_mday;
2350 printer->hour = t->tm_hour;
2351 printer->minute = t->tm_min;
2352 printer->second = t->tm_sec;
2353 printer->milliseconds = 0;
2355 printer->global_counter = global_counter;
2356 printer->total_pages = 0;
2357 printer->major_version = 0x0004; /* NT 4 */
2358 printer->build_version = 0x0565; /* build 1381 */
2359 printer->unknown7 = 0x1;
2360 printer->unknown8 = 0x0;
2361 printer->unknown9 = 0x0;
2362 printer->session_counter = session_counter->counter;
2363 printer->unknown11 = 0x0;
2364 printer->printer_errors = 0x0; /* number of print failure */
2365 printer->unknown13 = 0x0;
2366 printer->unknown14 = 0x1;
2367 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2368 printer->unknown16 = 0x0;
2369 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2370 printer->unknown18 = 0x0;
2371 printer->status = nt_printq_status(status.status);
2372 printer->unknown20 = 0x0;
2373 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2374 printer->unknown22 = 0x0;
2375 printer->unknown23 = 0x6; /* 6 ???*/
2376 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2377 printer->unknown25 = 0;
2378 printer->unknown26 = 0;
2379 printer->unknown27 = 0;
2380 printer->unknown28 = 0;
2381 printer->unknown29 = 0;
2384 free_a_printer(&ntprinter,2);
2388 /********************************************************************
2389 * construct_printer_info_1
2390 * fill a printer_info_1 struct
2391 ********************************************************************/
2392 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2396 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2398 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2401 printer->flags=flags;
2403 if (*ntprinter->info_2->comment == '\0') {
2404 init_unistr(&printer->comment, lp_comment(snum));
2405 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2406 ntprinter->info_2->drivername, lp_comment(snum));
2409 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2410 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2411 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2414 snprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2416 init_unistr(&printer->description, chaine);
2417 init_unistr(&printer->name, chaine2);
2419 free_a_printer(&ntprinter,2);
2424 /****************************************************************************
2425 Free a DEVMODE struct.
2426 ****************************************************************************/
2428 static void free_dev_mode(DEVICEMODE *dev)
2434 safe_free(dev->private);
2439 /****************************************************************************
2440 Create a DEVMODE struct. Returns malloced memory.
2441 ****************************************************************************/
2443 static DEVICEMODE *construct_dev_mode(int snum)
2447 NT_PRINTER_INFO_LEVEL *printer = NULL;
2448 NT_DEVICEMODE *ntdevmode = NULL;
2449 DEVICEMODE *devmode = NULL;
2451 DEBUG(7,("construct_dev_mode\n"));
2453 DEBUGADD(8,("getting printer characteristics\n"));
2455 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2456 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2460 ZERO_STRUCTP(devmode);
2462 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2465 if (printer->info_2->devmode)
2466 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2468 if (ntdevmode == NULL)
2471 DEBUGADD(8,("loading DEVICEMODE\n"));
2473 snprintf(adevice, sizeof(adevice), printer->info_2->printername);
2474 init_unistr(&devmode->devicename, adevice);
2476 snprintf(aform, sizeof(aform), ntdevmode->formname);
2477 init_unistr(&devmode->formname, aform);
2479 devmode->specversion = ntdevmode->specversion;
2480 devmode->driverversion = ntdevmode->driverversion;
2481 devmode->size = ntdevmode->size;
2482 devmode->driverextra = ntdevmode->driverextra;
2483 devmode->fields = ntdevmode->fields;
2485 devmode->orientation = ntdevmode->orientation;
2486 devmode->papersize = ntdevmode->papersize;
2487 devmode->paperlength = ntdevmode->paperlength;
2488 devmode->paperwidth = ntdevmode->paperwidth;
2489 devmode->scale = ntdevmode->scale;
2490 devmode->copies = ntdevmode->copies;
2491 devmode->defaultsource = ntdevmode->defaultsource;
2492 devmode->printquality = ntdevmode->printquality;
2493 devmode->color = ntdevmode->color;
2494 devmode->duplex = ntdevmode->duplex;
2495 devmode->yresolution = ntdevmode->yresolution;
2496 devmode->ttoption = ntdevmode->ttoption;
2497 devmode->collate = ntdevmode->collate;
2498 devmode->icmmethod = ntdevmode->icmmethod;
2499 devmode->icmintent = ntdevmode->icmintent;
2500 devmode->mediatype = ntdevmode->mediatype;
2501 devmode->dithertype = ntdevmode->dithertype;
2503 if (ntdevmode->private != NULL) {
2504 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2508 free_nt_devicemode(&ntdevmode);
2509 free_a_printer(&printer,2);
2516 free_nt_devicemode(&ntdevmode);
2518 free_a_printer(&printer,2);
2519 free_dev_mode(devmode);
2524 /********************************************************************
2525 * construct_printer_info_2
2526 * fill a printer_info_2 struct
2527 ********************************************************************/
2529 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2532 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2534 print_queue_struct *queue=NULL;
2535 print_status_struct status;
2536 memset(&status, 0, sizeof(status));
2538 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2541 memset(&status, 0, sizeof(status));
2542 count = print_queue_status(snum, &queue, &status);
2544 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2545 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2546 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2547 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2548 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2550 if (*ntprinter->info_2->comment == '\0')
2551 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2553 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2555 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2556 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2557 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2558 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2559 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2561 printer->attributes = ntprinter->info_2->attributes;
2563 printer->priority = ntprinter->info_2->priority; /* priority */
2564 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2565 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2566 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2567 printer->status = nt_printq_status(status.status); /* status */
2568 printer->cjobs = count; /* jobs */
2569 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2571 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2572 DEBUG(8, ("Returning NULL Devicemode!\n"));
2575 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2576 /* steal the printer info sec_desc structure. [badly done]. */
2577 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2578 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2579 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2580 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2583 printer->secdesc = NULL;
2586 free_a_printer(&ntprinter, 2);
2591 /********************************************************************
2592 * construct_printer_info_3
2593 * fill a printer_info_3 struct
2594 ********************************************************************/
2595 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2597 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2598 PRINTER_INFO_3 *printer = NULL;
2600 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2604 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2605 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2609 ZERO_STRUCTP(printer);
2611 printer->flags = 4; /* These are the components of the SD we are returning. */
2612 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2613 /* steal the printer info sec_desc structure. [badly done]. */
2614 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2618 * Set the flags for the components we are returning.
2621 if (printer->secdesc->owner_sid)
2622 printer->flags |= OWNER_SECURITY_INFORMATION;
2624 if (printer->secdesc->grp_sid)
2625 printer->flags |= GROUP_SECURITY_INFORMATION;
2627 if (printer->secdesc->dacl)
2628 printer->flags |= DACL_SECURITY_INFORMATION;
2630 if (printer->secdesc->sacl)
2631 printer->flags |= SACL_SECURITY_INFORMATION;
2634 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2635 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2636 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2639 free_a_printer(&ntprinter, 2);
2641 *pp_printer = printer;
2645 /********************************************************************
2646 Spoolss_enumprinters.
2647 ********************************************************************/
2648 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2652 int n_services=lp_numservices();
2653 PRINTER_INFO_1 *printers=NULL;
2654 PRINTER_INFO_1 current_prt;
2656 DEBUG(4,("enum_all_printers_info_1\n"));
2658 for (snum=0; snum<n_services; snum++) {
2659 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2660 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2662 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2663 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2665 return ERROR_NOT_ENOUGH_MEMORY;
2667 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2668 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2674 /* check the required size. */
2675 for (i=0; i<*returned; i++)
2676 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2678 if (!alloc_buffer_size(buffer, *needed))
2679 return ERROR_INSUFFICIENT_BUFFER;
2681 /* fill the buffer with the structures */
2682 for (i=0; i<*returned; i++)
2683 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2686 safe_free(printers);
2688 if (*needed > offered) {
2690 return ERROR_INSUFFICIENT_BUFFER;
2693 return NT_STATUS_NO_PROBLEMO;
2696 /********************************************************************
2697 enum_all_printers_info_1_local.
2698 *********************************************************************/
2699 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2701 DEBUG(4,("enum_all_printers_info_1_local\n"));
2703 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2706 /********************************************************************
2707 enum_all_printers_info_1_name.
2708 *********************************************************************/
2709 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2712 DEBUG(4,("enum_all_printers_info_1_name\n"));
2714 fstrcpy(temp, "\\\\");
2715 fstrcat(temp, global_myname);
2717 if (strequal(name, temp)) {
2718 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2721 return ERROR_INVALID_NAME;
2724 /********************************************************************
2725 enum_all_printers_info_1_remote.
2726 *********************************************************************/
2727 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2729 PRINTER_INFO_1 *printer;
2730 fstring printername;
2733 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2735 /* JFM: currently it's more a place holder than anything else.
2736 * In the spooler world there is a notion of server registration.
2737 * the print servers are registring (sp ?) on the PDC (in the same domain)
2739 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2742 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2743 return ERROR_NOT_ENOUGH_MEMORY;
2747 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2748 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2749 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2751 init_unistr(&printer->description, desc);
2752 init_unistr(&printer->name, printername);
2753 init_unistr(&printer->comment, comment);
2754 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2756 /* check the required size. */
2757 *needed += spoolss_size_printer_info_1(printer);
2759 if (!alloc_buffer_size(buffer, *needed)) {
2761 return ERROR_INSUFFICIENT_BUFFER;
2764 /* fill the buffer with the structures */
2765 new_smb_io_printer_info_1("", buffer, printer, 0);
2770 if (*needed > offered) {
2772 return ERROR_INSUFFICIENT_BUFFER;
2775 return NT_STATUS_NO_PROBLEMO;
2778 /********************************************************************
2779 enum_all_printers_info_1_network.
2780 *********************************************************************/
2781 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2783 DEBUG(4,("enum_all_printers_info_1_network\n"));
2785 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2788 /********************************************************************
2789 * api_spoolss_enumprinters
2791 * called from api_spoolss_enumprinters (see this to understand)
2792 ********************************************************************/
2793 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2797 int n_services=lp_numservices();
2798 PRINTER_INFO_2 *printers=NULL;
2799 PRINTER_INFO_2 current_prt;
2801 for (snum=0; snum<n_services; snum++) {
2802 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2803 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2805 if (construct_printer_info_2(¤t_prt, snum)) {
2806 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2807 return ERROR_NOT_ENOUGH_MEMORY;
2808 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2809 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2815 /* check the required size. */
2816 for (i=0; i<*returned; i++)
2817 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2819 if (!alloc_buffer_size(buffer, *needed)) {
2820 for (i=0; i<*returned; i++) {
2821 free_devmode(printers[i].devmode);
2822 free_sec_desc(&printers[i].secdesc);
2824 safe_free(printers);
2825 return ERROR_INSUFFICIENT_BUFFER;
2828 /* fill the buffer with the structures */
2829 for (i=0; i<*returned; i++)
2830 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2833 for (i=0; i<*returned; i++) {
2834 free_devmode(printers[i].devmode);
2835 free_sec_desc(&printers[i].secdesc);
2837 safe_free(printers);
2839 if (*needed > offered) {
2841 return ERROR_INSUFFICIENT_BUFFER;
2844 return NT_STATUS_NO_PROBLEMO;
2847 /********************************************************************
2848 * handle enumeration of printers at level 1
2849 ********************************************************************/
2850 static uint32 enumprinters_level1( uint32 flags, fstring name,
2851 NEW_BUFFER *buffer, uint32 offered,
2852 uint32 *needed, uint32 *returned)
2854 /* Not all the flags are equals */
2856 if (flags & PRINTER_ENUM_LOCAL)
2857 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2859 if (flags & PRINTER_ENUM_NAME)
2860 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2862 if (flags & PRINTER_ENUM_REMOTE)
2863 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2865 if (flags & PRINTER_ENUM_NETWORK)
2866 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
2868 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2871 /********************************************************************
2872 * handle enumeration of printers at level 2
2873 ********************************************************************/
2874 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2875 NEW_BUFFER *buffer, uint32 offered,
2876 uint32 *needed, uint32 *returned)
2880 fstrcpy(temp, "\\\\");
2881 fstrcat(temp, global_myname);
2883 if (flags & PRINTER_ENUM_LOCAL) {
2884 if (strequal(servername, temp))
2885 return enum_all_printers_info_2(buffer, offered, needed, returned);
2887 return enum_all_printers_info_2(buffer, offered, needed, returned);
2890 if (flags & PRINTER_ENUM_NAME) {
2891 if (strequal(servername, temp))
2892 return enum_all_printers_info_2(buffer, offered, needed, returned);
2894 return ERROR_INVALID_NAME;
2897 if (flags & PRINTER_ENUM_REMOTE)
2898 return ERROR_INVALID_LEVEL;
2900 return NT_STATUS_NO_PROBLEMO;
2903 /********************************************************************
2904 * handle enumeration of printers at level 5
2905 ********************************************************************/
2906 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2907 NEW_BUFFER *buffer, uint32 offered,
2908 uint32 *needed, uint32 *returned)
2910 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2911 return NT_STATUS_NO_PROBLEMO;
2914 /********************************************************************
2915 * api_spoolss_enumprinters
2917 * called from api_spoolss_enumprinters (see this to understand)
2918 ********************************************************************/
2919 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2920 NEW_BUFFER *buffer, uint32 offered,
2921 uint32 *needed, uint32 *returned)
2925 DEBUG(4,("_spoolss_enumprinters\n"));
2932 * flags==PRINTER_ENUM_NAME
2933 * if name=="" then enumerates all printers
2934 * if name!="" then enumerate the printer
2935 * flags==PRINTER_ENUM_REMOTE
2936 * name is NULL, enumerate printers
2937 * Level 2: name!="" enumerates printers, name can't be NULL
2938 * Level 3: doesn't exist
2939 * Level 4: does a local registry lookup
2940 * Level 5: same as Level 2
2943 unistr2_to_ascii(name, servername, sizeof(name)-1);
2948 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2950 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2952 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2956 return ERROR_INVALID_LEVEL;
2960 /****************************************************************************
2961 ****************************************************************************/
2962 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2964 PRINTER_INFO_0 *printer=NULL;
2966 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2967 return ERROR_NOT_ENOUGH_MEMORY;
2969 construct_printer_info_0(printer, snum);
2971 /* check the required size. */
2972 *needed += spoolss_size_printer_info_0(printer);
2974 if (!alloc_buffer_size(buffer, *needed)) {
2976 return ERROR_INSUFFICIENT_BUFFER;
2979 /* fill the buffer with the structures */
2980 new_smb_io_printer_info_0("", buffer, printer, 0);
2985 if (*needed > offered) {
2986 return ERROR_INSUFFICIENT_BUFFER;
2989 return NT_STATUS_NO_PROBLEMO;
2992 /****************************************************************************
2993 ****************************************************************************/
2994 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2996 PRINTER_INFO_1 *printer=NULL;
2998 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2999 return ERROR_NOT_ENOUGH_MEMORY;
3001 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3003 /* check the required size. */
3004 *needed += spoolss_size_printer_info_1(printer);
3006 if (!alloc_buffer_size(buffer, *needed)) {
3008 return ERROR_INSUFFICIENT_BUFFER;
3011 /* fill the buffer with the structures */
3012 new_smb_io_printer_info_1("", buffer, printer, 0);
3017 if (*needed > offered) {
3018 return ERROR_INSUFFICIENT_BUFFER;
3021 return NT_STATUS_NO_PROBLEMO;
3024 /****************************************************************************
3025 ****************************************************************************/
3026 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3028 PRINTER_INFO_2 *printer=NULL;
3030 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3031 return ERROR_NOT_ENOUGH_MEMORY;
3033 construct_printer_info_2(printer, snum);
3035 /* check the required size. */
3036 *needed += spoolss_size_printer_info_2(printer);
3038 if (!alloc_buffer_size(buffer, *needed)) {
3039 free_printer_info_2(printer);
3040 return ERROR_INSUFFICIENT_BUFFER;
3043 /* fill the buffer with the structures */
3044 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
3045 free_printer_info_2(printer);
3046 return ERROR_NOT_ENOUGH_MEMORY;
3050 free_printer_info_2(printer);
3052 if (*needed > offered) {
3053 return ERROR_INSUFFICIENT_BUFFER;
3056 return NT_STATUS_NO_PROBLEMO;
3059 /****************************************************************************
3060 ****************************************************************************/
3061 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3063 PRINTER_INFO_3 *printer=NULL;
3065 if (!construct_printer_info_3(&printer, snum))
3066 return ERROR_NOT_ENOUGH_MEMORY;
3068 /* check the required size. */
3069 *needed += spoolss_size_printer_info_3(printer);
3071 if (!alloc_buffer_size(buffer, *needed)) {
3072 free_printer_info_3(printer);
3073 return ERROR_INSUFFICIENT_BUFFER;
3076 /* fill the buffer with the structures */
3077 new_smb_io_printer_info_3("", buffer, printer, 0);
3080 free_printer_info_3(printer);
3082 if (*needed > offered) {
3083 return ERROR_INSUFFICIENT_BUFFER;
3086 return NT_STATUS_NO_PROBLEMO;
3089 /****************************************************************************
3090 ****************************************************************************/
3091 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
3092 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3098 if (!get_printer_snum(handle, &snum))
3099 return ERROR_INVALID_HANDLE;
3103 return getprinter_level_0(snum, buffer, offered, needed);
3105 return getprinter_level_1(snum, buffer, offered, needed);
3107 return getprinter_level_2(snum, buffer, offered, needed);
3109 return getprinter_level_3(snum, buffer, offered, needed);
3111 return ERROR_INVALID_LEVEL;
3115 /********************************************************************
3116 * fill a DRIVER_INFO_1 struct
3117 ********************************************************************/
3118 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3120 init_unistr( &info->name, driver.info_3->name);
3123 /********************************************************************
3124 * construct_printer_driver_info_1
3125 ********************************************************************/
3126 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3128 NT_PRINTER_INFO_LEVEL *printer = NULL;
3129 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3131 ZERO_STRUCT(driver);
3133 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3134 return ERROR_INVALID_PRINTER_NAME;
3136 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3137 return ERROR_UNKNOWN_PRINTER_DRIVER;
3139 fill_printer_driver_info_1(info, driver, servername, architecture);
3141 free_a_printer(&printer,2);
3143 return NT_STATUS_NO_PROBLEMO;
3146 /********************************************************************
3147 * construct_printer_driver_info_2
3148 * fill a printer_info_2 struct
3149 ********************************************************************/
3150 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3154 info->version=driver.info_3->cversion;
3156 init_unistr( &info->name, driver.info_3->name );
3157 init_unistr( &info->architecture, driver.info_3->environment );
3160 if (strlen(driver.info_3->driverpath)) {
3161 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3162 init_unistr( &info->driverpath, temp );
3164 init_unistr( &info->driverpath, "" );
3166 if (strlen(driver.info_3->datafile)) {
3167 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3168 init_unistr( &info->datafile, temp );
3170 init_unistr( &info->datafile, "" );
3172 if (strlen(driver.info_3->configfile)) {
3173 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3174 init_unistr( &info->configfile, temp );
3176 init_unistr( &info->configfile, "" );
3179 /********************************************************************
3180 * construct_printer_driver_info_2
3181 * fill a printer_info_2 struct
3182 ********************************************************************/
3183 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3185 NT_PRINTER_INFO_LEVEL *printer = NULL;
3186 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3188 ZERO_STRUCT(printer);
3189 ZERO_STRUCT(driver);
3191 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3192 return ERROR_INVALID_PRINTER_NAME;
3194 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3195 return ERROR_UNKNOWN_PRINTER_DRIVER;
3197 fill_printer_driver_info_2(info, driver, servername);
3199 free_a_printer(&printer,2);
3201 return NT_STATUS_NO_PROBLEMO;
3204 /********************************************************************
3205 * copy a strings array and convert to UNICODE
3207 * convert an array of ascii string to a UNICODE string
3208 ********************************************************************/
3209 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3216 DEBUG(6,("init_unistr_array\n"));
3220 if (char_array == NULL)
3224 if (!v) v = ""; /* hack to handle null lists */
3226 if (strlen(v) == 0) break;
3227 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3228 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3229 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3230 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3233 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3238 (*uni_array)[j]=0x0000;
3241 DEBUGADD(6,("last one:done\n"));
3244 /********************************************************************
3245 * construct_printer_info_3
3246 * fill a printer_info_3 struct
3247 ********************************************************************/
3248 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3254 info->version=driver.info_3->cversion;
3256 init_unistr( &info->name, driver.info_3->name );
3257 init_unistr( &info->architecture, driver.info_3->environment );
3259 if (strlen(driver.info_3->driverpath)) {
3260 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3261 init_unistr( &info->driverpath, temp );
3263 init_unistr( &info->driverpath, "" );
3265 if (strlen(driver.info_3->datafile)) {
3266 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3267 init_unistr( &info->datafile, temp );
3269 init_unistr( &info->datafile, "" );
3271 if (strlen(driver.info_3->configfile)) {
3272 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3273 init_unistr( &info->configfile, temp );
3275 init_unistr( &info->configfile, "" );
3277 if (strlen(driver.info_3->helpfile)) {
3278 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3279 init_unistr( &info->helpfile, temp );
3281 init_unistr( &info->helpfile, "" );
3283 init_unistr( &info->monitorname, driver.info_3->monitorname );
3284 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3286 info->dependentfiles=NULL;
3287 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3290 /********************************************************************
3291 * construct_printer_info_3
3292 * fill a printer_info_3 struct
3293 ********************************************************************/
3294 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3296 NT_PRINTER_INFO_LEVEL *printer = NULL;
3297 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3299 ZERO_STRUCT(driver);
3301 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3302 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3304 return ERROR_INVALID_PRINTER_NAME;
3306 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3307 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3309 free_a_printer(&printer,2);
3310 return ERROR_UNKNOWN_PRINTER_DRIVER;
3313 fill_printer_driver_info_3(info, driver, servername);
3315 free_a_printer(&printer,2);
3317 return NT_STATUS_NO_PROBLEMO;
3320 /********************************************************************
3321 * construct_printer_info_6
3322 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3323 ********************************************************************/
3325 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3331 memset(&nullstr, '\0', sizeof(fstring));
3333 info->version=driver.info_3->cversion;
3335 init_unistr( &info->name, driver.info_3->name );
3336 init_unistr( &info->architecture, driver.info_3->environment );
3338 if (strlen(driver.info_3->driverpath)) {
3339 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3340 init_unistr( &info->driverpath, temp );
3342 init_unistr( &info->driverpath, "" );
3344 if (strlen(driver.info_3->datafile)) {
3345 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3346 init_unistr( &info->datafile, temp );
3348 init_unistr( &info->datafile, "" );
3350 if (strlen(driver.info_3->configfile)) {
3351 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3352 init_unistr( &info->configfile, temp );
3354 init_unistr( &info->configfile, "" );
3356 if (strlen(driver.info_3->helpfile)) {
3357 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3358 init_unistr( &info->helpfile, temp );
3360 init_unistr( &info->helpfile, "" );
3362 init_unistr( &info->monitorname, driver.info_3->monitorname );
3363 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3365 info->dependentfiles=NULL;
3366 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3368 info->previousdrivernames=NULL;
3369 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3371 info->driver_date.low=0;
3372 info->driver_date.high=0;
3375 info->driver_version_low=0;
3376 info->driver_version_high=0;
3378 init_unistr( &info->mfgname, "");
3379 init_unistr( &info->oem_url, "");
3380 init_unistr( &info->hardware_id, "");
3381 init_unistr( &info->provider, "");
3384 /********************************************************************
3385 * construct_printer_info_6
3386 * fill a printer_info_6 struct
3387 ********************************************************************/
3388 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3390 NT_PRINTER_INFO_LEVEL *printer = NULL;
3391 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3393 ZERO_STRUCT(driver);
3395 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3396 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3398 return ERROR_INVALID_PRINTER_NAME;
3400 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3401 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3404 * Is this a W2k client ?
3408 free_a_printer(&printer,2);
3409 return ERROR_UNKNOWN_PRINTER_DRIVER;
3412 /* Yes - try again with a WinNT driver. */
3414 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3415 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3417 free_a_printer(&printer,2);
3418 return ERROR_UNKNOWN_PRINTER_DRIVER;
3422 fill_printer_driver_info_6(info, driver, servername);
3424 free_a_printer(&printer,2);
3426 return NT_STATUS_NO_PROBLEMO;
3429 /****************************************************************************
3430 ****************************************************************************/
3432 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3434 safe_free(info->dependentfiles);
3437 /****************************************************************************
3438 ****************************************************************************/
3440 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3442 safe_free(info->dependentfiles);
3446 /****************************************************************************
3447 ****************************************************************************/
3448 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3450 DRIVER_INFO_1 *info=NULL;
3453 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3454 return ERROR_NOT_ENOUGH_MEMORY;
3456 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3457 if (status != NT_STATUS_NO_PROBLEMO) {
3462 /* check the required size. */
3463 *needed += spoolss_size_printer_driver_info_1(info);
3465 if (!alloc_buffer_size(buffer, *needed)) {
3467 return ERROR_INSUFFICIENT_BUFFER;
3470 /* fill the buffer with the structures */
3471 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3476 if (*needed > offered)
3477 return ERROR_INSUFFICIENT_BUFFER;
3479 return NT_STATUS_NO_PROBLEMO;
3482 /****************************************************************************
3483 ****************************************************************************/
3484 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3486 DRIVER_INFO_2 *info=NULL;
3489 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3490 return ERROR_NOT_ENOUGH_MEMORY;
3492 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3493 if (status != NT_STATUS_NO_PROBLEMO) {
3498 /* check the required size. */
3499 *needed += spoolss_size_printer_driver_info_2(info);
3501 if (!alloc_buffer_size(buffer, *needed)) {
3503 return ERROR_INSUFFICIENT_BUFFER;
3506 /* fill the buffer with the structures */
3507 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3512 if (*needed > offered)
3513 return ERROR_INSUFFICIENT_BUFFER;
3515 return NT_STATUS_NO_PROBLEMO;
3518 /****************************************************************************
3519 ****************************************************************************/
3520 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3527 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3528 if (status != NT_STATUS_NO_PROBLEMO) {
3532 /* check the required size. */
3533 *needed += spoolss_size_printer_driver_info_3(&info);
3535 if (!alloc_buffer_size(buffer, *needed)) {
3536 free_printer_driver_info_3(&info);
3537 return ERROR_INSUFFICIENT_BUFFER;
3540 /* fill the buffer with the structures */
3541 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3543 free_printer_driver_info_3(&info);
3545 if (*needed > offered)
3546 return ERROR_INSUFFICIENT_BUFFER;
3548 return NT_STATUS_NO_PROBLEMO;
3551 /****************************************************************************
3552 ****************************************************************************/
3553 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3560 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3561 if (status != NT_STATUS_NO_PROBLEMO) {
3565 /* check the required size. */
3566 *needed += spoolss_size_printer_driver_info_6(&info);
3568 if (!alloc_buffer_size(buffer, *needed)) {
3569 free_printer_driver_info_6(&info);
3570 return ERROR_INSUFFICIENT_BUFFER;
3573 /* fill the buffer with the structures */
3574 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3576 free_printer_driver_info_6(&info);
3578 if (*needed > offered)
3579 return ERROR_INSUFFICIENT_BUFFER;
3581 return NT_STATUS_NO_PROBLEMO;
3584 /****************************************************************************
3585 ****************************************************************************/
3586 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3587 uint32 clientmajorversion, uint32 clientminorversion,
3588 NEW_BUFFER *buffer, uint32 offered,
3589 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3592 fstring architecture;
3595 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3598 *servermajorversion=0;
3599 *serverminorversion=0;
3601 pstrcpy(servername, global_myname);
3602 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3604 if (!get_printer_snum(handle, &snum))
3605 return ERROR_INVALID_HANDLE;
3609 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3611 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3613 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3615 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3617 return ERROR_INVALID_LEVEL;
3621 /****************************************************************************
3622 ****************************************************************************/
3623 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3625 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3627 if (OPEN_HANDLE(Printer)) {
3628 Printer->page_started=True;
3632 DEBUG(3,("Error in startpageprinter printer handle\n"));
3633 return ERROR_INVALID_HANDLE;
3636 /****************************************************************************
3637 ****************************************************************************/
3638 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3640 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3642 if (!OPEN_HANDLE(Printer)) {
3643 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3644 return ERROR_INVALID_HANDLE;
3647 Printer->page_started=False;
3649 return NT_STATUS_NO_PROBLEMO;
3652 /********************************************************************
3653 * api_spoolss_getprinter
3654 * called from the spoolss dispatcher
3656 ********************************************************************/
3657 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3658 pipes_struct *p, DOC_INFO *docinfo,
3661 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3665 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3666 struct current_user user;
3668 if (!OPEN_HANDLE(Printer)) {
3669 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3670 return ERROR_INVALID_HANDLE;
3673 get_current_user(&user, p);
3676 * a nice thing with NT is it doesn't listen to what you tell it.
3677 * when asked to send _only_ RAW datas, it tries to send datas
3680 * So I add checks like in NT Server ...
3682 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3683 * there's a bug in NT client-side code, so we'll fix it in the
3684 * server-side code. *nnnnnggggh!*
3687 if (info_1->p_datatype != 0) {
3688 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3689 if (strcmp(datatype, "RAW") != 0) {
3691 return ERROR_INVALID_DATATYPE;
3695 /* get the share number of the printer */
3696 if (!get_printer_snum(handle, &snum)) {
3697 return ERROR_INVALID_HANDLE;
3700 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3702 Printer->jobid = print_job_start(&user, snum, jobname);
3704 /* An error occured in print_job_start() so return an appropriate
3707 if (Printer->jobid == -1) {
3708 return map_nt_error_from_unix(errno);
3711 Printer->document_started=True;
3712 (*jobid) = Printer->jobid;
3717 /********************************************************************
3718 * api_spoolss_getprinter
3719 * called from the spoolss dispatcher
3721 ********************************************************************/
3722 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3724 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3726 if (!OPEN_HANDLE(Printer)) {
3727 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3728 return ERROR_INVALID_HANDLE;
3731 Printer->document_started=False;
3732 print_job_end(Printer->jobid,True);
3733 /* error codes unhandled so far ... */
3738 /****************************************************************************
3739 ****************************************************************************/
3740 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3743 uint32 *buffer_written)
3745 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3747 if (!OPEN_HANDLE(Printer)) {
3748 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3749 return ERROR_INVALID_HANDLE;
3752 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3758 /********************************************************************
3759 * api_spoolss_getprinter
3760 * called from the spoolss dispatcher
3762 ********************************************************************/
3763 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3766 struct current_user user;
3767 int snum, errcode = ERROR_INVALID_FUNCTION;
3768 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3770 get_current_user(&user, p);
3772 if (!OPEN_HANDLE(Printer)) {
3773 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3774 return ERROR_INVALID_HANDLE;
3777 if (!get_printer_snum(handle, &snum))
3778 return ERROR_INVALID_HANDLE;
3781 case PRINTER_CONTROL_PAUSE:
3782 if (print_queue_pause(&user, snum, &errcode)) {
3786 case PRINTER_CONTROL_RESUME:
3787 case PRINTER_CONTROL_UNPAUSE:
3788 if (print_queue_resume(&user, snum, &errcode)) {
3792 case PRINTER_CONTROL_PURGE:
3793 if (print_queue_purge(&user, snum, &errcode)) {
3798 return ERROR_INVALID_LEVEL;
3804 /********************************************************************
3805 * api_spoolss_abortprinter
3806 ********************************************************************/
3808 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3810 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3813 /********************************************************************
3814 * called by spoolss_api_setprinter
3815 * when updating a printer description
3816 ********************************************************************/
3817 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3818 const SPOOL_PRINTER_INFO_LEVEL *info,
3819 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3821 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3822 struct current_user user;
3826 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3828 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3829 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3830 OUR_HANDLE(handle)));
3832 result = ERROR_INVALID_HANDLE;
3836 /* NT seems to like setting the security descriptor even though
3837 nothing may have actually changed. This causes annoying
3838 dialog boxes when the user doesn't have permission to change
3839 the security descriptor. */
3841 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3843 if (DEBUGLEVEL >= 10) {
3847 acl = old_secdesc_ctr->sec->dacl;
3848 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3849 PRINTERNAME(snum), acl->num_aces));
3851 for (i = 0; i < acl->num_aces; i++) {
3854 sid_to_string(sid_str, &acl->ace[i].sid);
3856 DEBUG(10, ("%s 0x%08x\n", sid_str,
3857 acl->ace[i].info.mask));
3860 acl = secdesc_ctr->sec->dacl;
3863 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3864 PRINTERNAME(snum), acl->num_aces));
3866 for (i = 0; i < acl->num_aces; i++) {
3869 sid_to_string(sid_str, &acl->ace[i].sid);
3871 DEBUG(10, ("%s 0x%08x\n", sid_str,
3872 acl->ace[i].info.mask));
3875 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3879 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3881 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3882 result = NT_STATUS_NO_PROBLEMO;
3886 /* Work out which user is performing the operation */
3888 get_current_user(&user, p);
3890 /* Check the user has permissions to change the security
3891 descriptor. By experimentation with two NT machines, the user
3892 requires Full Access to the printer to change security
3895 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3896 result = ERROR_ACCESS_DENIED;
3900 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3903 free_sec_desc_buf(&new_secdesc_ctr);
3904 free_sec_desc_buf(&old_secdesc_ctr);
3909 /********************************************************************
3910 Do Samba sanity checks on a printer info struct.
3911 this has changed purpose: it now "canonicalises" printer
3912 info from a client rather than just checking it is correct
3913 ********************************************************************/
3915 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3917 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3918 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3920 /* we force some elements to "correct" values */
3921 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3922 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3923 global_myname, lp_servicename(snum));
3924 fstrcpy(info->sharename, lp_servicename(snum));
3925 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3926 | PRINTER_ATTRIBUTE_LOCAL \
3927 | PRINTER_ATTRIBUTE_RAW_ONLY \
3928 | PRINTER_ATTRIBUTE_QUEUED ;
3933 /****************************************************************************
3934 ****************************************************************************/
3935 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3937 pid_t local_pid = sys_getpid();
3938 char *cmd = lp_addprinter_cmd();
3943 pstring driverlocation;
3947 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3948 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3952 /* build driver path... only 9X architecture is needed for legacy reasons */
3953 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3955 /* change \ to \\ for the shell */
3956 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3958 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3959 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3960 cmd, printer->info_2->printername, printer->info_2->sharename,
3961 printer->info_2->portname, printer->info_2->drivername,
3962 printer->info_2->location, driverlocation);
3966 /* Convert script args to unix-codepage */
3967 dos_to_unix(command, True);
3968 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3969 ret = smbrun(command, tmp_file, False);
3970 DEBUGADD(10,("returned [%d]\n", ret));
3978 /* Get lines and convert them back to dos-codepage */
3979 qlines = file_lines_load(tmp_file, &numlines, True);
3980 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3981 DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
3985 /* Set the portname to what the script says the portname should be. */
3986 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3987 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3989 /* Send SIGHUP to process group... is there a better way? */
3994 file_lines_free(qlines);
3998 /* Return true if two devicemodes are equal */
4000 #define DEVMODE_CHECK_INT(field) \
4001 if (d1->field != d2->field) { \
4002 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4003 d1->field, d2->field)); \
4007 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4009 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4012 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4013 return False; /* if either is exclusively NULL are not equal */
4016 if (!strequal(d1->devicename, d2->devicename) ||
4017 !strequal(d1->formname, d2->formname)) {
4018 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
4022 DEVMODE_CHECK_INT(specversion);
4023 DEVMODE_CHECK_INT(driverversion);
4024 DEVMODE_CHECK_INT(driverextra);
4025 DEVMODE_CHECK_INT(orientation);
4026 DEVMODE_CHECK_INT(papersize);
4027 DEVMODE_CHECK_INT(paperlength);
4028 DEVMODE_CHECK_INT(paperwidth);
4029 DEVMODE_CHECK_INT(scale);
4030 DEVMODE_CHECK_INT(copies);
4031 DEVMODE_CHECK_INT(defaultsource);
4032 DEVMODE_CHECK_INT(printquality);
4033 DEVMODE_CHECK_INT(color);
4034 DEVMODE_CHECK_INT(duplex);
4035 DEVMODE_CHECK_INT(yresolution);
4036 DEVMODE_CHECK_INT(ttoption);
4037 DEVMODE_CHECK_INT(collate);
4038 DEVMODE_CHECK_INT(logpixels);
4040 DEVMODE_CHECK_INT(fields);
4041 DEVMODE_CHECK_INT(bitsperpel);
4042 DEVMODE_CHECK_INT(pelswidth);
4043 DEVMODE_CHECK_INT(pelsheight);
4044 DEVMODE_CHECK_INT(displayflags);
4045 DEVMODE_CHECK_INT(displayfrequency);
4046 DEVMODE_CHECK_INT(icmmethod);
4047 DEVMODE_CHECK_INT(icmintent);
4048 DEVMODE_CHECK_INT(mediatype);
4049 DEVMODE_CHECK_INT(dithertype);
4050 DEVMODE_CHECK_INT(reserved1);
4051 DEVMODE_CHECK_INT(reserved2);
4052 DEVMODE_CHECK_INT(panningwidth);
4053 DEVMODE_CHECK_INT(panningheight);
4055 /* compare the private data if it exists */
4056 if (!d1->driverextra && !d2->driverextra) goto equal;
4059 DEVMODE_CHECK_INT(driverextra);
4061 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4062 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4067 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4071 /* Return true if two NT_PRINTER_PARAM structures are equal */
4073 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4074 NT_PRINTER_PARAM *p2)
4076 if (!p1 && !p2) goto equal;
4078 if ((!p1 && p2) || (p1 && !p2)) {
4079 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4083 /* Compare lists of printer parameters */
4087 NT_PRINTER_PARAM *q = p1;
4089 /* Find the parameter in the second structure */
4093 if (strequal(p1->value, q->value)) {
4095 if (p1->type != q->type) {
4096 DEBUG(10, ("nt_printer_param_equal():"
4097 "types for %s differ (%d != %d)\n",
4098 p1->value, p1->type,
4103 if (p1->data_len != q->data_len) {
4104 DEBUG(10, ("nt_printer_param_equal():"
4105 "len for %s differs (%d != %d)\n",
4106 p1->value, p1->data_len,
4111 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4114 DEBUG(10, ("nt_printer_param_equal():"
4115 "data for %s differs\n", p1->value));
4125 DEBUG(10, ("nt_printer_param_equal(): param %s "
4126 "does not exist\n", p1->value));
4135 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4139 /********************************************************************
4140 * Called by update_printer when trying to work out whether to
4141 * actually update printer info.
4142 ********************************************************************/
4144 #define PI_CHECK_INT(field) \
4145 if (pi1->field != pi2->field) { \
4146 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4147 pi1->field, pi2->field)); \
4151 #define PI_CHECK_STR(field) \
4152 if (!strequal(pi1->field, pi2->field)) { \
4153 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4154 pi1->field, pi2->field)); \
4158 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4159 NT_PRINTER_INFO_LEVEL *p2)
4161 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4163 /* Trivial conditions */
4165 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4169 if ((!p1 && p2) || (p1 && !p2) ||
4170 (!p1->info_2 && p2->info_2) ||
4171 (p1->info_2 && !p2->info_2)) {
4172 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4177 /* Compare two nt_printer_info_level structures. Don't compare
4178 status or cjobs as they seem to have something to do with the
4184 PI_CHECK_INT(attributes);
4185 PI_CHECK_INT(priority);
4186 PI_CHECK_INT(default_priority);
4187 PI_CHECK_INT(starttime);
4188 PI_CHECK_INT(untiltime);
4189 PI_CHECK_INT(averageppm);
4191 /* Yuck - don't check the printername or servername as the
4192 add_a_printer() code plays games with them. You can't
4193 change the printername or the sharename through this interface
4196 PI_CHECK_STR(sharename);
4197 PI_CHECK_STR(portname);
4198 PI_CHECK_STR(drivername);
4199 PI_CHECK_STR(comment);
4200 PI_CHECK_STR(location);
4202 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4206 PI_CHECK_STR(sepfile);
4207 PI_CHECK_STR(printprocessor);
4208 PI_CHECK_STR(datatype);
4209 PI_CHECK_STR(parameters);
4211 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4215 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4219 PI_CHECK_INT(changeid);
4220 PI_CHECK_INT(c_setprinter);
4221 PI_CHECK_INT(setuptime);
4224 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4228 /********************************************************************
4229 * called by spoolss_api_setprinter
4230 * when updating a printer description
4231 ********************************************************************/
4233 static uint32 update_printer(POLICY_HND *handle, uint32 level,
4234 const SPOOL_PRINTER_INFO_LEVEL *info,
4235 DEVICEMODE *devmode)
4238 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4239 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4242 DEBUG(8,("update_printer\n"));
4244 result = NT_STATUS_NO_PROBLEMO;
4247 DEBUG(0,("Send a mail to samba@samba.org\n"));
4248 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4249 result = ERROR_INVALID_LEVEL;
4253 if (!OPEN_HANDLE(Printer)) {
4254 result = ERROR_INVALID_HANDLE;
4258 if (!get_printer_snum(handle, &snum)) {
4259 result = ERROR_INVALID_HANDLE;
4263 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4264 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4265 result = ERROR_INVALID_HANDLE;
4269 DEBUGADD(8,("Converting info_2 struct\n"));
4272 * convert_printer_info converts the incoming
4273 * info from the client and overwrites the info
4274 * just read from the tdb in the pointer 'printer'.
4277 convert_printer_info(info, printer, level);
4279 if (info->info_2->devmode_ptr != 0) {
4280 /* we have a valid devmode
4281 convert it and link it*/
4283 DEBUGADD(8,("Converting the devicemode struct\n"));
4284 if (!convert_devicemode(printer->info_2->printername, devmode,
4285 &printer->info_2->devmode)) {
4286 result = ERROR_NOT_ENOUGH_MEMORY;
4291 /* Do sanity check on the requested changes for Samba */
4293 if (!check_printer_ok(printer->info_2, snum)) {
4294 result = ERROR_INVALID_PARAMETER;
4298 /* NT likes to call this function even though nothing has actually
4299 changed. Check this so the user doesn't end up with an
4300 annoying permission denied dialog box. */
4302 if (nt_printer_info_level_equal(printer, old_printer)) {
4303 DEBUG(3, ("printer info has not changed\n"));
4304 result = NT_STATUS_NO_PROBLEMO;
4308 /* Check calling user has permission to update printer description */
4310 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4311 DEBUG(3, ("printer property change denied by security "
4313 result = ERROR_ACCESS_DENIED;
4317 /* Call addprinter hook */
4319 if (*lp_addprinter_cmd() )
4320 if ( !add_printer_hook(printer) ) {
4321 result = ERROR_ACCESS_DENIED;
4325 /* Update printer info */
4327 if (add_a_printer(*printer, 2)!=0) {
4328 /* I don't really know what to return here !!! */
4329 result = ERROR_ACCESS_DENIED;
4334 free_a_printer(&printer, 2);
4335 free_a_printer(&old_printer, 2);
4337 srv_spoolss_sendnotify(handle);
4342 /****************************************************************************
4343 ****************************************************************************/
4344 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
4345 const SPOOL_PRINTER_INFO_LEVEL *info,
4346 DEVMODE_CTR devmode_ctr,
4347 SEC_DESC_BUF *secdesc_ctr,
4348 uint32 command, pipes_struct *p)
4350 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4352 if (!OPEN_HANDLE(Printer)) {
4353 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4354 return ERROR_INVALID_HANDLE;
4357 /* check the level */
4360 return control_printer(handle, command, p);
4362 return update_printer(handle, level, info, devmode_ctr.devmode);
4364 return update_printer_sec(handle, level, info, p,
4367 return ERROR_INVALID_LEVEL;
4371 /****************************************************************************
4372 ****************************************************************************/
4373 uint32 _spoolss_fcpn(POLICY_HND *handle)
4375 Printer_entry *Printer= find_printer_index_by_hnd(handle);
4377 if (!OPEN_HANDLE(Printer)) {
4378 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4379 return ERROR_INVALID_HANDLE;
4382 if (Printer->notify.client_connected==True)
4383 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4384 return ERROR_INVALID_HANDLE;
4386 Printer->notify.flags=0;
4387 Printer->notify.options=0;
4388 Printer->notify.localmachine[0]='\0';
4389 Printer->notify.printerlocal=0;
4390 if (Printer->notify.option)
4391 safe_free(Printer->notify.option->ctr.type);
4392 safe_free(Printer->notify.option);
4393 Printer->notify.option=NULL;
4394 Printer->notify.client_connected=False;
4396 return NT_STATUS_NO_PROBLEMO;
4399 /****************************************************************************
4400 ****************************************************************************/
4401 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
4402 NEW_BUFFER *buffer, uint32 offered,
4406 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4407 returns for AddJob. AddJob
4408 must fail on non-local
4412 /****************************************************************************
4413 ****************************************************************************/
4414 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4415 int position, int snum)
4421 t=gmtime(&queue->time);
4422 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4424 job_info->jobid=queue->job;
4425 init_unistr(&job_info->printername, lp_servicename(snum));
4426 init_unistr(&job_info->machinename, temp_name);
4427 init_unistr(&job_info->username, queue->user);
4428 init_unistr(&job_info->document, queue->file);
4429 init_unistr(&job_info->datatype, "RAW");
4430 init_unistr(&job_info->text_status, "");
4431 job_info->status=nt_printj_status(queue->status);
4432 job_info->priority=queue->priority;
4433 job_info->position=position;
4434 job_info->totalpages=0;
4435 job_info->pagesprinted=0;
4437 make_systemtime(&job_info->submitted, t);
4440 /****************************************************************************
4441 ****************************************************************************/
4442 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4443 int position, int snum,
4444 NT_PRINTER_INFO_LEVEL *ntprinter)
4450 t=gmtime(&queue->time);
4451 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4453 job_info->jobid=queue->job;
4455 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4457 init_unistr(&job_info->printername, chaine);
4459 init_unistr(&job_info->machinename, temp_name);
4460 init_unistr(&job_info->username, queue->user);
4461 init_unistr(&job_info->document, queue->file);
4462 init_unistr(&job_info->notifyname, queue->user);
4463 init_unistr(&job_info->datatype, "RAW");
4464 init_unistr(&job_info->printprocessor, "winprint");
4465 init_unistr(&job_info->parameters, "");
4466 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4467 init_unistr(&job_info->text_status, "");
4469 /* and here the security descriptor */
4471 job_info->status=nt_printj_status(queue->status);
4472 job_info->priority=queue->priority;
4473 job_info->position=position;
4474 job_info->starttime=0;
4475 job_info->untiltime=0;
4476 job_info->totalpages=0;
4477 job_info->size=queue->size;
4478 make_systemtime(&(job_info->submitted), t);
4479 job_info->timeelapsed=0;
4480 job_info->pagesprinted=0;
4482 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4489 /****************************************************************************
4490 Enumjobs at level 1.
4491 ****************************************************************************/
4492 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4493 NEW_BUFFER *buffer, uint32 offered,
4494 uint32 *needed, uint32 *returned)
4499 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4503 return ERROR_NOT_ENOUGH_MEMORY;
4506 for (i=0; i<*returned; i++)
4507 fill_job_info_1(&info[i], &queue[i], i, snum);
4511 /* check the required size. */
4512 for (i=0; i<*returned; i++)
4513 (*needed) += spoolss_size_job_info_1(&info[i]);
4515 if (!alloc_buffer_size(buffer, *needed)) {
4517 return ERROR_INSUFFICIENT_BUFFER;
4520 /* fill the buffer with the structures */
4521 for (i=0; i<*returned; i++)
4522 new_smb_io_job_info_1("", buffer, &info[i], 0);
4527 if (*needed > offered) {
4529 return ERROR_INSUFFICIENT_BUFFER;
4532 return NT_STATUS_NO_PROBLEMO;
4535 /****************************************************************************
4536 Enumjobs at level 2.
4537 ****************************************************************************/
4538 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4539 NEW_BUFFER *buffer, uint32 offered,
4540 uint32 *needed, uint32 *returned)
4542 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4546 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4549 return ERROR_NOT_ENOUGH_MEMORY;
4552 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4554 return ERROR_NOT_ENOUGH_MEMORY;
4557 for (i=0; i<*returned; i++)
4558 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4560 free_a_printer(&ntprinter, 2);
4563 /* check the required size. */
4564 for (i=0; i<*returned; i++)
4565 (*needed) += spoolss_size_job_info_2(&info[i]);
4567 if (!alloc_buffer_size(buffer, *needed)) {
4569 return ERROR_INSUFFICIENT_BUFFER;
4572 /* fill the buffer with the structures */
4573 for (i=0; i<*returned; i++)
4574 new_smb_io_job_info_2("", buffer, &info[i], 0);
4577 for (i = 0; i < *returned; i++)
4578 free_job_info_2(&info[i]);
4582 if (*needed > offered) {
4584 return ERROR_INSUFFICIENT_BUFFER;
4587 return NT_STATUS_NO_PROBLEMO;
4590 /****************************************************************************
4592 ****************************************************************************/
4593 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4594 NEW_BUFFER *buffer, uint32 offered,
4595 uint32 *needed, uint32 *returned)
4598 print_queue_struct *queue=NULL;
4599 print_status_struct prt_status;
4601 DEBUG(4,("_spoolss_enumjobs\n"));
4603 ZERO_STRUCT(prt_status);
4608 if (!get_printer_snum(handle, &snum))
4609 return ERROR_INVALID_HANDLE;
4611 *returned = print_queue_status(snum, &queue, &prt_status);
4612 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4614 if (*returned == 0) {
4616 return NT_STATUS_NO_PROBLEMO;
4621 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4623 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4627 return ERROR_INVALID_LEVEL;
4632 /****************************************************************************
4633 ****************************************************************************/
4634 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4639 /****************************************************************************
4640 ****************************************************************************/
4641 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4642 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4644 struct current_user user;
4645 print_status_struct prt_status;
4646 int snum, errcode = ERROR_INVALID_FUNCTION;
4648 memset(&prt_status, 0, sizeof(prt_status));
4650 if (!get_printer_snum(handle, &snum)) {
4651 return ERROR_INVALID_HANDLE;
4654 if (!print_job_exists(jobid)) {
4655 return ERROR_INVALID_PRINTER_NAME;
4658 get_current_user(&user, p);
4661 case JOB_CONTROL_CANCEL:
4662 case JOB_CONTROL_DELETE:
4663 if (print_job_delete(&user, jobid, &errcode)) {
4667 case JOB_CONTROL_PAUSE:
4668 if (print_job_pause(&user, jobid, &errcode)) {
4672 case JOB_CONTROL_RESTART:
4673 case JOB_CONTROL_RESUME:
4674 if (print_job_resume(&user, jobid, &errcode)) {
4679 return ERROR_INVALID_LEVEL;
4685 /****************************************************************************
4686 Enumerates all printer drivers at level 1.
4687 ****************************************************************************/
4688 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4693 fstring *list = NULL;
4695 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4696 DRIVER_INFO_1 *driver_info_1=NULL;
4700 #define MAX_VERSION 4
4702 for (version=0; version<MAX_VERSION; version++) {
4704 ndrivers=get_ntdrivers(&list, architecture, version);
4705 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4708 return ERROR_NOT_ENOUGH_MEMORY;
4711 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4713 return ERROR_NOT_ENOUGH_MEMORY;
4717 for (i=0; i<ndrivers; i++) {
4719 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4720 ZERO_STRUCT(driver);
4721 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4725 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4726 free_a_printer_driver(driver, 3);
4729 *returned+=ndrivers;
4733 /* check the required size. */
4734 for (i=0; i<*returned; i++) {
4735 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4736 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4739 if (!alloc_buffer_size(buffer, *needed)) {
4740 safe_free(driver_info_1);
4741 return ERROR_INSUFFICIENT_BUFFER;
4744 /* fill the buffer with the form structures */
4745 for (i=0; i<*returned; i++) {
4746 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4747 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4750 safe_free(driver_info_1);
4752 if (*needed > offered) {
4754 return ERROR_INSUFFICIENT_BUFFER;
4757 return NT_STATUS_NO_PROBLEMO;
4760 /****************************************************************************
4761 Enumerates all printer drivers at level 2.
4762 ****************************************************************************/
4763 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4768 fstring *list = NULL;
4770 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4771 DRIVER_INFO_2 *driver_info_2=NULL;
4775 #define MAX_VERSION 4
4777 for (version=0; version<MAX_VERSION; version++) {
4779 ndrivers=get_ntdrivers(&list, architecture, version);
4780 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4783 return ERROR_NOT_ENOUGH_MEMORY;
4786 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4788 return ERROR_NOT_ENOUGH_MEMORY;
4792 for (i=0; i<ndrivers; i++) {
4795 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4796 ZERO_STRUCT(driver);
4797 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4801 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4802 free_a_printer_driver(driver, 3);
4805 *returned+=ndrivers;
4809 /* check the required size. */
4810 for (i=0; i<*returned; i++) {
4811 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4812 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4815 if (!alloc_buffer_size(buffer, *needed)) {
4816 safe_free(driver_info_2);
4817 return ERROR_INSUFFICIENT_BUFFER;
4820 /* fill the buffer with the form structures */
4821 for (i=0; i<*returned; i++) {
4822 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4823 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4826 safe_free(driver_info_2);
4828 if (*needed > offered) {
4830 return ERROR_INSUFFICIENT_BUFFER;
4833 return NT_STATUS_NO_PROBLEMO;
4836 /****************************************************************************
4837 Enumerates all printer drivers at level 3.
4838 ****************************************************************************/
4839 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4844 fstring *list = NULL;
4846 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4847 DRIVER_INFO_3 *driver_info_3=NULL;
4851 #define MAX_VERSION 4
4853 for (version=0; version<MAX_VERSION; version++) {
4855 ndrivers=get_ntdrivers(&list, architecture, version);
4856 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4859 return ERROR_NOT_ENOUGH_MEMORY;
4862 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4864 return ERROR_NOT_ENOUGH_MEMORY;
4868 for (i=0; i<ndrivers; i++) {
4871 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4872 ZERO_STRUCT(driver);
4873 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4877 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4878 free_a_printer_driver(driver, 3);
4881 *returned+=ndrivers;
4885 /* check the required size. */
4886 for (i=0; i<*returned; i++) {
4887 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4888 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4891 if (!alloc_buffer_size(buffer, *needed)) {
4892 safe_free(driver_info_3);
4893 return ERROR_INSUFFICIENT_BUFFER;
4896 /* fill the buffer with the driver structures */
4897 for (i=0; i<*returned; i++) {
4898 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4899 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4902 for (i=0; i<*returned; i++)
4903 safe_free(driver_info_3[i].dependentfiles);
4905 safe_free(driver_info_3);
4907 if (*needed > offered) {
4909 return ERROR_INSUFFICIENT_BUFFER;
4912 return NT_STATUS_NO_PROBLEMO;
4915 /****************************************************************************
4916 Enumerates all printer drivers.
4917 ****************************************************************************/
4918 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4919 NEW_BUFFER *buffer, uint32 offered,
4920 uint32 *needed, uint32 *returned)
4922 fstring *list = NULL;
4924 fstring architecture;
4926 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4927 fstrcpy(servername, global_myname);
4931 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4935 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4937 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4939 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4943 return ERROR_INVALID_LEVEL;
4947 /****************************************************************************
4948 ****************************************************************************/
4949 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4951 form->flag=list->flag;
4952 init_unistr(&form->name, list->name);
4953 form->width=list->width;
4954 form->length=list->length;
4955 form->left=list->left;
4956 form->top=list->top;
4957 form->right=list->right;
4958 form->bottom=list->bottom;
4961 /****************************************************************************
4962 ****************************************************************************/
4963 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4964 NEW_BUFFER *buffer, uint32 offered,
4965 uint32 *needed, uint32 *numofforms)
4967 nt_forms_struct *list=NULL;
4972 DEBUG(4,("_new_spoolss_enumforms\n"));
4973 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4974 DEBUGADD(5,("Info level [%d]\n", level));
4976 *numofforms = get_ntforms(&list);
4977 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4979 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4983 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4985 return ERROR_NOT_ENOUGH_MEMORY;
4988 /* construct the list of form structures */
4989 for (i=0; i<*numofforms; i++) {
4990 DEBUGADD(6,("Filling form number [%d]\n",i));
4991 fill_form_1(&forms_1[i], &list[i]);
4996 /* check the required size. */
4997 for (i=0; i<*numofforms; i++) {
4998 DEBUGADD(6,("adding form [%d]'s size\n",i));
4999 buffer_size += spoolss_size_form_1(&forms_1[i]);
5002 *needed=buffer_size;
5004 if (!alloc_buffer_size(buffer, buffer_size)){
5006 return ERROR_INSUFFICIENT_BUFFER;
5009 /* fill the buffer with the form structures */
5010 for (i=0; i<*numofforms; i++) {
5011 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5012 new_smb_io_form_1("", buffer, &forms_1[i], 0);
5017 if (*needed > offered) {
5019 return ERROR_INSUFFICIENT_BUFFER;
5022 return NT_STATUS_NO_PROBLEMO;
5026 return ERROR_INVALID_LEVEL;
5031 /****************************************************************************
5032 ****************************************************************************/
5033 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5035 nt_forms_struct *list=NULL;
5041 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5043 DEBUG(4,("_spoolss_getform\n"));
5044 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5045 DEBUGADD(5,("Info level [%d]\n", level));
5047 numofforms = get_ntforms(&list);
5048 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5050 if (numofforms == 0)
5051 return ERROR_NO_MORE_ITEMS;
5056 /* Check if the requested name is in the list of form structures */
5057 for (i=0; i<numofforms; i++) {
5059 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5061 if (strequal(form_name, list[i].name)) {
5062 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5063 fill_form_1(&form_1, &list[i]);
5070 /* check the required size. */
5072 *needed=spoolss_size_form_1(&form_1);
5074 if (!alloc_buffer_size(buffer, buffer_size)){
5075 return ERROR_INSUFFICIENT_BUFFER;
5078 if (*needed > offered) {
5079 return ERROR_INSUFFICIENT_BUFFER;
5082 /* fill the buffer with the form structures */
5083 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5084 new_smb_io_form_1("", buffer, &form_1, 0);
5086 return NT_STATUS_NO_PROBLEMO;
5090 return ERROR_INVALID_LEVEL;
5094 /****************************************************************************
5095 ****************************************************************************/
5096 static void fill_port_1(PORT_INFO_1 *port, char *name)
5098 init_unistr(&port->port_name, name);
5101 /****************************************************************************
5102 ****************************************************************************/
5103 static void fill_port_2(PORT_INFO_2 *port, char *name)
5105 init_unistr(&port->port_name, name);
5106 init_unistr(&port->monitor_name, "Local Monitor");
5107 init_unistr(&port->description, "Local Port");
5108 #define PORT_TYPE_WRITE 1
5109 port->port_type=PORT_TYPE_WRITE;
5113 /****************************************************************************
5115 ****************************************************************************/
5116 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5118 PORT_INFO_1 *ports=NULL;
5121 if (*lp_enumports_cmd()) {
5122 pid_t local_pid = sys_getpid();
5123 char *cmd = lp_enumports_cmd();
5131 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5132 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5136 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5137 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
5140 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5141 ret = smbrun(command, tmp_file, False);
5142 DEBUG(10,("Returned [%d]\n", ret));
5145 /* Is this the best error to return here? */
5146 return ERROR_ACCESS_DENIED;
5150 qlines = file_lines_load(tmp_file, &numlines,True);
5151 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5152 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5156 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5157 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5158 file_lines_free(qlines);
5159 return ERROR_NOT_ENOUGH_MEMORY;
5162 for (i=0; i<numlines; i++) {
5163 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5164 fill_port_1(&ports[i], qlines[i]);
5167 file_lines_free(qlines);
5170 *returned = numlines;
5173 *returned = 1; /* Sole Samba port returned. */
5175 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5176 return ERROR_NOT_ENOUGH_MEMORY;
5178 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5180 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5183 /* check the required size. */
5184 for (i=0; i<*returned; i++) {
5185 DEBUGADD(6,("adding port [%d]'s size\n", i));
5186 *needed += spoolss_size_port_info_1(&ports[i]);
5189 if (!alloc_buffer_size(buffer, *needed)) {
5191 return ERROR_INSUFFICIENT_BUFFER;
5194 /* fill the buffer with the ports structures */
5195 for (i=0; i<*returned; i++) {
5196 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5197 new_smb_io_port_1("", buffer, &ports[i], 0);
5202 if (*needed > offered) {
5204 return ERROR_INSUFFICIENT_BUFFER;
5207 return NT_STATUS_NO_PROBLEMO;
5210 /****************************************************************************
5212 ****************************************************************************/
5214 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5216 PORT_INFO_2 *ports=NULL;
5219 if (*lp_enumports_cmd()) {
5220 pid_t local_pid = sys_getpid();
5221 char *cmd = lp_enumports_cmd();
5229 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5230 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5234 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5235 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
5238 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5239 ret = smbrun(command, tmp_file, False);
5240 DEBUGADD(10,("returned [%d]\n", ret));
5243 /* Is this the best error to return here? */
5244 return ERROR_ACCESS_DENIED;
5248 qlines = file_lines_load(tmp_file, &numlines,True);
5249 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5250 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5254 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5255 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5256 file_lines_free(qlines);
5257 return ERROR_NOT_ENOUGH_MEMORY;
5260 for (i=0; i<numlines; i++) {
5261 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5262 fill_port_2(&(ports[i]), qlines[i]);
5265 file_lines_free(qlines);
5268 *returned = numlines;
5274 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5275 return ERROR_NOT_ENOUGH_MEMORY;
5277 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5279 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5282 /* check the required size. */
5283 for (i=0; i<*returned; i++) {
5284 DEBUGADD(6,("adding port [%d]'s size\n", i));
5285 *needed += spoolss_size_port_info_2(&ports[i]);
5288 if (!alloc_buffer_size(buffer, *needed)) {
5290 return ERROR_INSUFFICIENT_BUFFER;
5293 /* fill the buffer with the ports structures */
5294 for (i=0; i<*returned; i++) {
5295 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5296 new_smb_io_port_2("", buffer, &ports[i], 0);
5301 if (*needed > offered) {
5303 return ERROR_INSUFFICIENT_BUFFER;
5306 return NT_STATUS_NO_PROBLEMO;
5309 /****************************************************************************
5311 ****************************************************************************/
5312 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
5313 NEW_BUFFER *buffer, uint32 offered,
5314 uint32 *needed, uint32 *returned)
5316 DEBUG(4,("_spoolss_enumports\n"));
5323 return enumports_level_1(buffer, offered, needed, returned);
5325 return enumports_level_2(buffer, offered, needed, returned);
5327 return ERROR_INVALID_LEVEL;
5331 /****************************************************************************
5332 ****************************************************************************/
5333 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5334 const SPOOL_PRINTER_INFO_LEVEL *info,
5335 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5336 uint32 user_switch, const SPOOL_USER_CTR *user,
5339 NT_PRINTER_INFO_LEVEL *printer = NULL;
5343 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5344 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5345 return ERROR_NOT_ENOUGH_MEMORY;
5348 ZERO_STRUCTP(printer);
5350 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5351 convert_printer_info(info, printer, 2);
5353 if (*lp_addprinter_cmd() )
5354 if ( !add_printer_hook(printer) ) {
5355 free_a_printer(&printer,2);
5356 return ERROR_ACCESS_DENIED;
5359 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5360 printer->info_2->sharename);
5362 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5363 free_a_printer(&printer,2);
5364 return ERROR_ACCESS_DENIED;
5367 /* you must be a printer admin to add a new printer */
5368 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5369 free_a_printer(&printer,2);
5370 return ERROR_ACCESS_DENIED;
5374 * Do sanity check on the requested changes for Samba.
5377 if (!check_printer_ok(printer->info_2, snum)) {
5378 free_a_printer(&printer,2);
5379 return ERROR_INVALID_PARAMETER;
5382 /* write the ASCII on disk */
5383 if (add_a_printer(*printer, 2) != 0) {
5384 free_a_printer(&printer,2);
5385 return ERROR_ACCESS_DENIED;
5388 if (!open_printer_hnd(handle, name)) {
5389 /* Handle open failed - remove addition. */
5390 del_a_printer(printer->info_2->sharename);
5391 free_a_printer(&printer,2);
5392 return ERROR_ACCESS_DENIED;
5395 free_a_printer(&printer,2);
5397 srv_spoolss_sendnotify(handle);
5399 return NT_STATUS_NO_PROBLEMO;
5402 /****************************************************************************
5403 ****************************************************************************/
5404 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5405 const SPOOL_PRINTER_INFO_LEVEL *info,
5406 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5407 uint32 user_switch, const SPOOL_USER_CTR *user,
5412 /* we don't handle yet */
5413 /* but I know what to do ... */
5414 return ERROR_INVALID_LEVEL;
5416 return spoolss_addprinterex_level_2(uni_srv_name, info,
5417 unk0, unk1, unk2, unk3,
5418 user_switch, user, handle);
5420 return ERROR_INVALID_LEVEL;
5424 /****************************************************************************
5425 ****************************************************************************/
5426 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5427 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5429 uint32 err = NT_STATUS_NO_PROBLEMO;
5430 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5431 struct current_user user;
5433 ZERO_STRUCT(driver);
5435 get_current_user(&user, p);
5437 convert_printer_driver_info(info, &driver, level);
5439 DEBUG(5,("Cleaning driver's information\n"));
5440 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5443 DEBUG(5,("Moving driver to final destination\n"));
5444 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5446 err = ERROR_ACCESS_DENIED;
5450 if (add_a_printer_driver(driver, level)!=0) {
5451 err = ERROR_ACCESS_DENIED;
5456 free_a_printer_driver(driver, level);
5460 /****************************************************************************
5461 ****************************************************************************/
5462 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5464 init_unistr(&info->name, name);
5467 /****************************************************************************
5468 ****************************************************************************/
5469 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5473 pstring short_archi;
5474 DRIVER_DIRECTORY_1 *info=NULL;
5476 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5478 if (get_short_archi(short_archi, long_archi)==FALSE)
5479 return ERROR_INVALID_ENVIRONMENT;
5481 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5482 return ERROR_NOT_ENOUGH_MEMORY;
5484 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5486 DEBUG(4,("printer driver directory: [%s]\n", path));
5488 fill_driverdir_1(info, path);
5490 *needed += spoolss_size_driverdir_info_1(info);
5492 if (!alloc_buffer_size(buffer, *needed)) {
5494 return ERROR_INSUFFICIENT_BUFFER;
5497 new_smb_io_driverdir_1("", buffer, info, 0);
5501 if (*needed > offered)
5502 return ERROR_INSUFFICIENT_BUFFER;
5504 return NT_STATUS_NO_PROBLEMO;
5507 /****************************************************************************
5508 ****************************************************************************/
5509 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5510 NEW_BUFFER *buffer, uint32 offered,
5513 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5519 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5521 return ERROR_INVALID_LEVEL;
5525 /****************************************************************************
5526 ****************************************************************************/
5527 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5528 uint32 in_value_len, uint32 in_data_len,
5529 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5531 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5533 NT_PRINTER_INFO_LEVEL *printer = NULL;
5538 uint32 biggest_valuesize;
5539 uint32 biggest_datasize;
5541 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5546 ZERO_STRUCT(printer);
5548 *out_max_value_len=0;
5554 *out_max_data_len=0;
5558 DEBUG(5,("spoolss_enumprinterdata\n"));
5560 if (!OPEN_HANDLE(Printer)) {
5561 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5562 return ERROR_INVALID_HANDLE;
5565 if (!get_printer_snum(handle, &snum))
5566 return ERROR_INVALID_HANDLE;
5568 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5569 return ERROR_INVALID_HANDLE;
5572 * The NT machine wants to know the biggest size of value and data
5574 * cf: MSDN EnumPrinterData remark section
5576 if ( (in_value_len==0) && (in_data_len==0) ) {
5577 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5581 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5582 * if this parameter size doesn't exist.
5583 * Ok - my opinion here is that the client is not asking for the greatest
5584 * possible size of all the parameters, but is asking specifically for the size needed
5585 * for this specific parameter. In that case we can remove the loop below and
5586 * simplify this lookup code considerably. JF - comments welcome. JRA.
5589 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5591 free_a_printer(&printer, 2);
5592 return ERROR_NO_MORE_ITEMS;
5600 biggest_valuesize=0;
5603 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5604 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5605 if (data_len > biggest_datasize) biggest_datasize=data_len;
5607 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5615 * I think this is correct, it doesn't break APW and
5616 * allows Gerald's Win32 test programs to work correctly,
5617 * but may need altering.... JRA.
5620 if (param_index == 0) {
5621 /* No parameters found. */
5622 free_a_printer(&printer, 2);
5623 return ERROR_NO_MORE_ITEMS;
5626 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5627 *out_value_len=2*(1+biggest_valuesize);
5628 *out_data_len=biggest_datasize;
5630 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5632 free_a_printer(&printer, 2);
5633 return NT_STATUS_NO_PROBLEMO;
5637 * the value len is wrong in NT sp3
5638 * that's the number of bytes not the number of unicode chars
5641 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5643 free_a_printer(&printer, 2);
5644 return ERROR_NO_MORE_ITEMS;
5647 free_a_printer(&printer, 2);
5651 * - counted in bytes in the request
5652 * - counted in UNICODE chars in the max reply
5653 * - counted in bytes in the real size
5655 * take a pause *before* coding not *during* coding
5658 *out_max_value_len=(in_value_len/sizeof(uint16));
5659 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5661 return ERROR_NOT_ENOUGH_MEMORY;
5664 ZERO_STRUCTP(*out_value);
5665 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5669 /* the data is counted in bytes */
5670 *out_max_data_len=in_data_len;
5671 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5673 return ERROR_NOT_ENOUGH_MEMORY;
5676 memset(*data_out,'\0',in_data_len);
5677 memcpy(*data_out, data, (size_t)data_len);
5678 *out_data_len=data_len;
5682 return NT_STATUS_NO_PROBLEMO;
5685 /****************************************************************************
5686 ****************************************************************************/
5687 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5688 const UNISTR2 *value,
5693 uint32 numeric_data)
5695 NT_PRINTER_INFO_LEVEL *printer = NULL;
5696 NT_PRINTER_PARAM *param = NULL, old_param;
5698 uint32 status = 0x0;
5699 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5701 DEBUG(5,("spoolss_setprinterdata\n"));
5703 if (!OPEN_HANDLE(Printer)) {
5704 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5705 return ERROR_INVALID_HANDLE;
5708 if (!get_printer_snum(handle, &snum))
5709 return ERROR_INVALID_HANDLE;
5711 status = get_a_printer(&printer, 2, lp_servicename(snum));
5713 return ERROR_INVALID_NAME;
5715 convert_specific_param(¶m, value , type, data, real_len);
5717 /* Check if we are making any changes or not. Return true if
5718 nothing is actually changing. */
5720 ZERO_STRUCT(old_param);
5722 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5723 &old_param.type, (unsigned int *)&old_param.data_len)) {
5725 if (param->type == old_param.type &&
5726 param->data_len == old_param.data_len &&
5727 memcmp(param->data, old_param.data,
5728 old_param.data_len) == 0) {
5730 DEBUG(3, ("setprinterdata hasn't changed\n"));
5731 status = NT_STATUS_NO_PROBLEMO;
5738 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5739 DEBUG(3, ("security descriptor change denied by existing "
5740 "security descriptor\n"));
5741 status = ERROR_ACCESS_DENIED;
5745 unlink_specific_param_if_exist(printer->info_2, param);
5747 add_a_specific_param(printer->info_2, ¶m);
5748 status = mod_a_printer(*printer, 2);
5751 free_a_printer(&printer, 2);
5753 free_nt_printer_param(¶m);
5754 safe_free(old_param.data);
5759 /****************************************************************************
5760 ****************************************************************************/
5761 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5763 NT_PRINTER_INFO_LEVEL *printer = NULL;
5764 NT_PRINTER_PARAM param;
5766 uint32 status = 0x0;
5767 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5769 DEBUG(5,("spoolss_deleteprinterdata\n"));
5771 if (!OPEN_HANDLE(Printer)) {
5772 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5773 return ERROR_INVALID_HANDLE;
5776 if (!get_printer_snum(handle, &snum))
5777 return ERROR_INVALID_HANDLE;
5779 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5780 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
5781 "change denied by existing security descriptor\n"));
5782 return ERROR_ACCESS_DENIED;
5785 status = get_a_printer(&printer, 2, lp_servicename(snum));
5787 return ERROR_INVALID_NAME;
5789 ZERO_STRUCTP(¶m);
5790 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5792 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5793 status = ERROR_INVALID_PARAMETER;
5795 status = mod_a_printer(*printer, 2);
5797 free_a_printer(&printer, 2);
5801 /****************************************************************************
5802 ****************************************************************************/
5803 uint32 _spoolss_addform( POLICY_HND *handle,
5808 nt_forms_struct *list=NULL;
5809 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5811 DEBUG(5,("spoolss_addform\n"));
5813 if (!OPEN_HANDLE(Printer)) {
5814 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5815 return ERROR_INVALID_HANDLE;
5818 count=get_ntforms(&list);
5819 if(!add_a_form(&list, form, &count))
5820 return ERROR_NOT_ENOUGH_MEMORY;
5821 write_ntforms(&list, count);
5828 /****************************************************************************
5829 ****************************************************************************/
5830 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5834 nt_forms_struct *list=NULL;
5835 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5837 DEBUG(5,("spoolss_deleteform\n"));
5839 if (!OPEN_HANDLE(Printer)) {
5840 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5841 return ERROR_INVALID_HANDLE;
5844 count = get_ntforms(&list);
5845 if(!delete_a_form(&list, form_name, &count, &ret))
5846 return ERROR_INVALID_PARAMETER;
5853 /****************************************************************************
5854 ****************************************************************************/
5855 uint32 _spoolss_setform( POLICY_HND *handle,
5856 const UNISTR2 *uni_name,
5861 nt_forms_struct *list=NULL;
5862 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5864 DEBUG(5,("spoolss_setform\n"));
5866 if (!OPEN_HANDLE(Printer)) {
5867 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5868 return ERROR_INVALID_HANDLE;
5870 count=get_ntforms(&list);
5871 update_a_form(&list, form, count);
5872 write_ntforms(&list, count);
5879 /****************************************************************************
5880 enumprintprocessors level 1.
5881 ****************************************************************************/
5882 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5884 PRINTPROCESSOR_1 *info_1=NULL;
5886 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5887 return ERROR_NOT_ENOUGH_MEMORY;
5891 init_unistr(&info_1->name, "winprint");
5893 *needed += spoolss_size_printprocessor_info_1(info_1);
5895 if (!alloc_buffer_size(buffer, *needed))
5896 return ERROR_INSUFFICIENT_BUFFER;
5898 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5902 if (*needed > offered) {
5904 return ERROR_INSUFFICIENT_BUFFER;
5907 return NT_STATUS_NO_PROBLEMO;
5910 /****************************************************************************
5911 ****************************************************************************/
5912 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5913 NEW_BUFFER *buffer, uint32 offered,
5914 uint32 *needed, uint32 *returned)
5916 DEBUG(5,("spoolss_enumprintprocessors\n"));
5919 * Enumerate the print processors ...
5921 * Just reply with "winprint", to keep NT happy
5922 * and I can use my nice printer checker.
5930 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5932 return ERROR_INVALID_LEVEL;
5936 /****************************************************************************
5937 enumprintprocdatatypes level 1.
5938 ****************************************************************************/
5939 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5941 PRINTPROCDATATYPE_1 *info_1=NULL;
5943 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5944 return ERROR_NOT_ENOUGH_MEMORY;
5948 init_unistr(&info_1->name, "RAW");
5950 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5952 if (!alloc_buffer_size(buffer, *needed))
5953 return ERROR_INSUFFICIENT_BUFFER;
5955 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5959 if (*needed > offered) {
5961 return ERROR_INSUFFICIENT_BUFFER;
5964 return NT_STATUS_NO_PROBLEMO;
5967 /****************************************************************************
5968 ****************************************************************************/
5969 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5970 NEW_BUFFER *buffer, uint32 offered,
5971 uint32 *needed, uint32 *returned)
5973 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5980 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5982 return ERROR_INVALID_LEVEL;
5986 /****************************************************************************
5987 enumprintmonitors level 1.
5988 ****************************************************************************/
5989 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5991 PRINTMONITOR_1 *info_1=NULL;
5993 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5994 return ERROR_NOT_ENOUGH_MEMORY;
5998 init_unistr(&info_1->name, "Local Port");
6000 *needed += spoolss_size_printmonitor_info_1(info_1);
6002 if (!alloc_buffer_size(buffer, *needed))
6003 return ERROR_INSUFFICIENT_BUFFER;
6005 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6009 if (*needed > offered) {
6011 return ERROR_INSUFFICIENT_BUFFER;
6014 return NT_STATUS_NO_PROBLEMO;
6017 /****************************************************************************
6018 enumprintmonitors level 2.
6019 ****************************************************************************/
6020 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6022 PRINTMONITOR_2 *info_2=NULL;
6024 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6025 return ERROR_NOT_ENOUGH_MEMORY;
6029 init_unistr(&info_2->name, "Local Port");
6030 init_unistr(&info_2->environment, "Windows NT X86");
6031 init_unistr(&info_2->dll_name, "localmon.dll");
6033 *needed += spoolss_size_printmonitor_info_2(info_2);
6035 if (!alloc_buffer_size(buffer, *needed))
6036 return ERROR_INSUFFICIENT_BUFFER;
6038 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6042 if (*needed > offered) {
6044 return ERROR_INSUFFICIENT_BUFFER;
6047 return NT_STATUS_NO_PROBLEMO;
6050 /****************************************************************************
6051 ****************************************************************************/
6052 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
6053 NEW_BUFFER *buffer, uint32 offered,
6054 uint32 *needed, uint32 *returned)
6056 DEBUG(5,("spoolss_enumprintmonitors\n"));
6059 * Enumerate the print monitors ...
6061 * Just reply with "Local Port", to keep NT happy
6062 * and I can use my nice printer checker.
6070 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6072 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6074 return ERROR_INVALID_LEVEL;
6078 /****************************************************************************
6079 ****************************************************************************/
6080 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6084 JOB_INFO_1 *info_1=NULL;
6086 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6088 if (info_1 == NULL) {
6090 return ERROR_NOT_ENOUGH_MEMORY;
6093 for (i=0; i<count && found==False; i++) {
6094 if (queue[i].job==(int)jobid)
6101 /* I shoud reply something else ... I can't find the good one */
6102 return NT_STATUS_NO_PROBLEMO;
6105 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6109 *needed += spoolss_size_job_info_1(info_1);
6111 if (!alloc_buffer_size(buffer, *needed)) {
6113 return ERROR_INSUFFICIENT_BUFFER;
6116 new_smb_io_job_info_1("", buffer, info_1, 0);
6120 if (*needed > offered)
6121 return ERROR_INSUFFICIENT_BUFFER;
6123 return NT_STATUS_NO_PROBLEMO;
6127 /****************************************************************************
6128 ****************************************************************************/
6129 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6134 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6136 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6138 ZERO_STRUCTP(info_2);
6140 if (info_2 == NULL) {
6142 return ERROR_NOT_ENOUGH_MEMORY;
6145 for (i=0; i<count && found==False; i++) {
6146 if (queue[i].job==(int)jobid)
6153 /* I shoud reply something else ... I can't find the good one */
6154 return NT_STATUS_NO_PROBLEMO;
6157 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6159 return ERROR_NOT_ENOUGH_MEMORY;
6162 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6164 free_a_printer(&ntprinter, 2);
6167 *needed += spoolss_size_job_info_2(info_2);
6169 if (!alloc_buffer_size(buffer, *needed)) {
6171 return ERROR_INSUFFICIENT_BUFFER;
6174 new_smb_io_job_info_2("", buffer, info_2, 0);
6176 free_job_info_2(info_2);
6179 if (*needed > offered)
6180 return ERROR_INSUFFICIENT_BUFFER;
6182 return NT_STATUS_NO_PROBLEMO;
6185 /****************************************************************************
6186 ****************************************************************************/
6187 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
6188 NEW_BUFFER *buffer, uint32 offered,
6193 print_queue_struct *queue=NULL;
6194 print_status_struct prt_status;
6196 DEBUG(5,("spoolss_getjob\n"));
6198 memset(&prt_status, 0, sizeof(prt_status));
6202 if (!get_printer_snum(handle, &snum))
6203 return ERROR_INVALID_HANDLE;
6205 count = print_queue_status(snum, &queue, &prt_status);
6207 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6208 count, prt_status.status, prt_status.message));
6212 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6214 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6217 return ERROR_INVALID_LEVEL;