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 const 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 if (!print_access_check(&user, snum, printer_default->access_required)) {
769 DEBUG(3, ("access DENIED for printer open\n"));
770 close_printer_handle(handle);
771 return ERROR_ACCESS_DENIED;
775 * If we have a default device pointer in the
776 * printer_default struct, then we need to get
777 * the printer info from the tdb and if there is
778 * no default devicemode there then we do a *SET*
779 * here ! This is insanity.... JRA.
782 if (printer_default->devmode_cont.devmode != NULL) {
783 result = printer_write_default_dev( snum, printer_default);
785 close_printer_handle(handle);
790 return NT_STATUS_NO_PROBLEMO;
795 /****************************************************************************
796 ****************************************************************************/
797 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
798 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
802 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
811 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
812 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
816 printer->info_3=NULL;
817 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
820 printer->info_6=NULL;
821 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
830 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
831 NT_DEVICEMODE **pp_nt_devmode)
833 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
836 * Ensure nt_devmode is a valid pointer
837 * as we will be overwriting it.
840 if (nt_devmode == NULL)
841 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
844 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
845 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
847 nt_devmode->specversion=devmode->specversion;
848 nt_devmode->driverversion=devmode->driverversion;
849 nt_devmode->size=devmode->size;
850 nt_devmode->fields=devmode->fields;
851 nt_devmode->orientation=devmode->orientation;
852 nt_devmode->papersize=devmode->papersize;
853 nt_devmode->paperlength=devmode->paperlength;
854 nt_devmode->paperwidth=devmode->paperwidth;
855 nt_devmode->scale=devmode->scale;
856 nt_devmode->copies=devmode->copies;
857 nt_devmode->defaultsource=devmode->defaultsource;
858 nt_devmode->printquality=devmode->printquality;
859 nt_devmode->color=devmode->color;
860 nt_devmode->duplex=devmode->duplex;
861 nt_devmode->yresolution=devmode->yresolution;
862 nt_devmode->ttoption=devmode->ttoption;
863 nt_devmode->collate=devmode->collate;
865 nt_devmode->logpixels=devmode->logpixels;
866 nt_devmode->bitsperpel=devmode->bitsperpel;
867 nt_devmode->pelswidth=devmode->pelswidth;
868 nt_devmode->pelsheight=devmode->pelsheight;
869 nt_devmode->displayflags=devmode->displayflags;
870 nt_devmode->displayfrequency=devmode->displayfrequency;
871 nt_devmode->icmmethod=devmode->icmmethod;
872 nt_devmode->icmintent=devmode->icmintent;
873 nt_devmode->mediatype=devmode->mediatype;
874 nt_devmode->dithertype=devmode->dithertype;
875 nt_devmode->reserved1=devmode->reserved1;
876 nt_devmode->reserved2=devmode->reserved2;
877 nt_devmode->panningwidth=devmode->panningwidth;
878 nt_devmode->panningheight=devmode->panningheight;
881 * Only change private and driverextra if the incoming devmode
882 * has a new one. JRA.
885 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
886 safe_free(nt_devmode->private);
887 nt_devmode->driverextra=devmode->driverextra;
888 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
890 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
893 *pp_nt_devmode = nt_devmode;
898 /********************************************************************
899 * api_spoolss_closeprinter
900 ********************************************************************/
901 uint32 _spoolss_closeprinter(POLICY_HND *handle)
903 Printer_entry *Printer=find_printer_index_by_hnd(handle);
905 if (Printer && Printer->document_started)
906 _spoolss_enddocprinter(handle); /* print job was not closed */
908 if (!close_printer_handle(handle))
909 return ERROR_INVALID_HANDLE;
911 return NT_STATUS_NO_PROBLEMO;
914 /********************************************************************
915 * api_spoolss_deleteprinter
916 ********************************************************************/
917 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
919 Printer_entry *Printer=find_printer_index_by_hnd(handle);
922 if (Printer && Printer->document_started)
923 _spoolss_enddocprinter(handle); /* print job was not closed */
925 result = delete_printer_handle(handle);
927 if (result == ERROR_SUCCESS) {
928 srv_spoolss_sendnotify(handle);
934 /********************************************************************
935 GetPrinterData on a printer server Handle.
936 ********************************************************************/
937 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
941 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
943 if (!strcmp(value, "BeepEnabled")) {
945 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
947 SIVAL(*data, 0, 0x01);
952 if (!strcmp(value, "EventLog")) {
954 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
956 SIVAL(*data, 0, 0x1B);
961 if (!strcmp(value, "NetPopup")) {
963 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
965 SIVAL(*data, 0, 0x01);
970 if (!strcmp(value, "MajorVersion")) {
972 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
974 SIVAL(*data, 0, 0x02);
979 if (!strcmp(value, "DefaultSpoolDirectory")) {
980 pstring string="You are using a Samba server";
982 *needed = 2*(strlen(string)+1);
983 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
985 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
987 /* it's done by hand ready to go on the wire */
988 for (i=0; i<strlen(string); i++) {
989 (*data)[2*i]=string[i];
995 if (!strcmp(value, "Architecture")) {
996 pstring string="Windows NT x86";
998 *needed = 2*(strlen(string)+1);
999 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1001 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1002 for (i=0; i<strlen(string); i++) {
1003 (*data)[2*i]=string[i];
1004 (*data)[2*i+1]='\0';
1012 /********************************************************************
1013 GetPrinterData on a printer Handle.
1014 ********************************************************************/
1015 static BOOL getprinterdata_printer(POLICY_HND *handle,
1016 fstring value, uint32 *type,
1017 uint8 **data, uint32 *needed, uint32 in_size )
1019 NT_PRINTER_INFO_LEVEL *printer = NULL;
1023 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1025 DEBUG(5,("getprinterdata_printer\n"));
1027 if (!OPEN_HANDLE(Printer)) {
1028 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1032 if(!get_printer_snum(handle, &snum))
1035 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1038 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1039 free_a_printer(&printer, 2);
1043 free_a_printer(&printer, 2);
1045 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1048 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
1052 memset(*data, 0, in_size *sizeof(uint8));
1053 /* copy the min(in_size, len) */
1054 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1061 DEBUG(5,("getprinterdata_printer:copy done\n"));
1068 /********************************************************************
1069 * spoolss_getprinterdata
1070 ********************************************************************/
1071 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
1080 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1083 * Reminder: when it's a string, the length is in BYTES
1084 * even if UNICODE is negociated.
1091 /* in case of problem, return some default values */
1095 DEBUG(4,("_spoolss_getprinterdata\n"));
1097 if (!OPEN_HANDLE(Printer)) {
1098 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1099 return ERROR_NOT_ENOUGH_MEMORY;
1100 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1101 return ERROR_INVALID_HANDLE;
1104 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1106 if (handle_is_printserver(handle))
1107 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1109 found= getprinterdata_printer(handle, value, type, data, needed, *out_size);
1112 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1113 /* reply this param doesn't exist */
1115 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
1116 return ERROR_NOT_ENOUGH_MEMORY;
1117 memset(*data, '\0', *out_size*sizeof(uint8));
1122 return ERROR_INVALID_PARAMETER;
1125 if (*needed > *out_size)
1126 return ERROR_MORE_DATA;
1128 return NT_STATUS_NO_PROBLEMO;
1132 /***************************************************************************
1133 connect to the client
1134 ****************************************************************************/
1135 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1140 * If it's the first connection, contact the client
1141 * and connect to the IPC$ share anonumously
1143 if (smb_connections==0) {
1144 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1146 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1152 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1158 /********************************************************************
1160 * ReplyFindFirstPrinterChangeNotifyEx
1162 * jfmxxxx: before replying OK: status=0
1163 * should do a rpc call to the workstation asking ReplyOpenPrinter
1164 * have to code it, later.
1166 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1167 * called from api_spoolss_rffpcnex
1168 ********************************************************************/
1169 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1170 const UNISTR2 *localmachine, uint32 printerlocal,
1171 SPOOL_NOTIFY_OPTION *option)
1173 /* store the notify value in the printer struct */
1175 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1177 if (!OPEN_HANDLE(Printer)) {
1178 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1179 return ERROR_INVALID_HANDLE;
1182 Printer->notify.flags=flags;
1183 Printer->notify.options=options;
1184 Printer->notify.printerlocal=printerlocal;
1185 Printer->notify.option=option;
1186 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1188 /* connect to the client machine and send a ReplyOpenPrinter */
1189 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1190 Printer->notify.printerlocal, 1,
1191 &Printer->notify.client_hnd))
1192 Printer->notify.client_connected=True;
1194 return NT_STATUS_NO_PROBLEMO;
1197 /*******************************************************************
1198 * fill a notify_info_data with the servername
1199 ********************************************************************/
1200 static void spoolss_notify_server_name(int snum,
1201 SPOOL_NOTIFY_INFO_DATA *data,
1202 print_queue_struct *queue,
1203 NT_PRINTER_INFO_LEVEL *printer,
1204 TALLOC_CTX *mem_ctx)
1206 pstring temp_name, temp;
1209 snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1211 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1213 data->notify_data.data.length = len / 2 - 1;
1214 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1216 if (!data->notify_data.data.string) {
1217 data->notify_data.data.length = 0;
1221 memcpy(data->notify_data.data.string, temp, len);
1224 /*******************************************************************
1225 * fill a notify_info_data with the printername (not including the servername).
1226 ********************************************************************/
1227 static void spoolss_notify_printer_name(int snum,
1228 SPOOL_NOTIFY_INFO_DATA *data,
1229 print_queue_struct *queue,
1230 NT_PRINTER_INFO_LEVEL *printer,
1231 TALLOC_CTX *mem_ctx)
1236 /* the notify name should not contain the \\server\ part */
1237 char *p = strrchr(printer->info_2->printername, '\\');
1240 p = printer->info_2->printername;
1245 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1247 data->notify_data.data.length = len / 2 - 1;
1248 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1250 if (!data->notify_data.data.string) {
1251 data->notify_data.data.length = 0;
1255 memcpy(data->notify_data.data.string, temp, len);
1258 /*******************************************************************
1259 * fill a notify_info_data with the servicename
1260 ********************************************************************/
1261 static void spoolss_notify_share_name(int snum,
1262 SPOOL_NOTIFY_INFO_DATA *data,
1263 print_queue_struct *queue,
1264 NT_PRINTER_INFO_LEVEL *printer,
1265 TALLOC_CTX *mem_ctx)
1270 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1271 sizeof(temp) - 2, True);
1273 data->notify_data.data.length = len / 2 - 1;
1274 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1276 if (!data->notify_data.data.string) {
1277 data->notify_data.data.length = 0;
1281 memcpy(data->notify_data.data.string, temp, len);
1284 /*******************************************************************
1285 * fill a notify_info_data with the port name
1286 ********************************************************************/
1287 static void spoolss_notify_port_name(int snum,
1288 SPOOL_NOTIFY_INFO_DATA *data,
1289 print_queue_struct *queue,
1290 NT_PRINTER_INFO_LEVEL *printer,
1291 TALLOC_CTX *mem_ctx)
1296 /* even if it's strange, that's consistant in all the code */
1298 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1299 sizeof(temp) - 2, True);
1301 data->notify_data.data.length = len / 2 - 1;
1302 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1304 if (!data->notify_data.data.string) {
1305 data->notify_data.data.length = 0;
1309 memcpy(data->notify_data.data.string, temp, len);
1312 /*******************************************************************
1313 * fill a notify_info_data with the printername
1314 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1315 * but it doesn't exist, have to see what to do
1316 ********************************************************************/
1317 static void spoolss_notify_driver_name(int snum,
1318 SPOOL_NOTIFY_INFO_DATA *data,
1319 print_queue_struct *queue,
1320 NT_PRINTER_INFO_LEVEL *printer,
1321 TALLOC_CTX *mem_ctx)
1326 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1327 sizeof(temp) - 2, True);
1329 data->notify_data.data.length = len / 2 - 1;
1330 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1332 if (!data->notify_data.data.string) {
1333 data->notify_data.data.length = 0;
1337 memcpy(data->notify_data.data.string, temp, len);
1340 /*******************************************************************
1341 * fill a notify_info_data with the comment
1342 ********************************************************************/
1343 static void spoolss_notify_comment(int snum,
1344 SPOOL_NOTIFY_INFO_DATA *data,
1345 print_queue_struct *queue,
1346 NT_PRINTER_INFO_LEVEL *printer,
1347 TALLOC_CTX *mem_ctx)
1352 if (*printer->info_2->comment == '\0')
1353 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1354 sizeof(temp) - 2, True);
1356 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1357 sizeof(temp) - 2, True);
1359 data->notify_data.data.length = len / 2 - 1;
1360 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1362 if (!data->notify_data.data.string) {
1363 data->notify_data.data.length = 0;
1367 memcpy(data->notify_data.data.string, temp, len);
1370 /*******************************************************************
1371 * fill a notify_info_data with the comment
1372 * jfm:xxxx incorrect, have to create a new smb.conf option
1373 * location = "Room 1, floor 2, building 3"
1374 ********************************************************************/
1375 static void spoolss_notify_location(int snum,
1376 SPOOL_NOTIFY_INFO_DATA *data,
1377 print_queue_struct *queue,
1378 NT_PRINTER_INFO_LEVEL *printer,
1379 TALLOC_CTX *mem_ctx)
1384 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1385 sizeof(temp) - 2, True);
1387 data->notify_data.data.length = len / 2 - 1;
1388 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1390 if (!data->notify_data.data.string) {
1391 data->notify_data.data.length = 0;
1395 memcpy(data->notify_data.data.string, temp, len);
1398 /*******************************************************************
1399 * fill a notify_info_data with the device mode
1400 * jfm:xxxx don't to it for know but that's a real problem !!!
1401 ********************************************************************/
1402 static void spoolss_notify_devmode(int snum,
1403 SPOOL_NOTIFY_INFO_DATA *data,
1404 print_queue_struct *queue,
1405 NT_PRINTER_INFO_LEVEL *printer,
1406 TALLOC_CTX *mem_ctx)
1410 /*******************************************************************
1411 * fill a notify_info_data with the separator file name
1412 * jfm:xxxx just return no file could add an option to smb.conf
1413 * separator file = "separator.txt"
1414 ********************************************************************/
1415 static void spoolss_notify_sepfile(int snum,
1416 SPOOL_NOTIFY_INFO_DATA *data,
1417 print_queue_struct *queue,
1418 NT_PRINTER_INFO_LEVEL *printer,
1419 TALLOC_CTX *mem_ctx)
1424 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1425 sizeof(temp) - 2, True);
1427 data->notify_data.data.length = len / 2 - 1;
1428 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1430 if (!data->notify_data.data.string) {
1431 data->notify_data.data.length = 0;
1435 memcpy(data->notify_data.data.string, temp, len);
1438 /*******************************************************************
1439 * fill a notify_info_data with the print processor
1440 * jfm:xxxx return always winprint to indicate we don't do anything to it
1441 ********************************************************************/
1442 static void spoolss_notify_print_processor(int snum,
1443 SPOOL_NOTIFY_INFO_DATA *data,
1444 print_queue_struct *queue,
1445 NT_PRINTER_INFO_LEVEL *printer,
1446 TALLOC_CTX *mem_ctx)
1451 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
1452 sizeof(temp) - 2, True);
1454 data->notify_data.data.length = len / 2 - 1;
1455 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1457 if (!data->notify_data.data.string) {
1458 data->notify_data.data.length = 0;
1462 memcpy(data->notify_data.data.string, temp, len);
1465 /*******************************************************************
1466 * fill a notify_info_data with the print processor options
1467 * jfm:xxxx send an empty string
1468 ********************************************************************/
1469 static void spoolss_notify_parameters(int snum,
1470 SPOOL_NOTIFY_INFO_DATA *data,
1471 print_queue_struct *queue,
1472 NT_PRINTER_INFO_LEVEL *printer,
1473 TALLOC_CTX *mem_ctx)
1478 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1479 sizeof(temp) - 2, True);
1481 data->notify_data.data.length = len / 2 - 1;
1482 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1484 if (!data->notify_data.data.string) {
1485 data->notify_data.data.length = 0;
1489 memcpy(data->notify_data.data.string, temp, len);
1492 /*******************************************************************
1493 * fill a notify_info_data with the data type
1494 * jfm:xxxx always send RAW as data type
1495 ********************************************************************/
1496 static void spoolss_notify_datatype(int snum,
1497 SPOOL_NOTIFY_INFO_DATA *data,
1498 print_queue_struct *queue,
1499 NT_PRINTER_INFO_LEVEL *printer,
1500 TALLOC_CTX *mem_ctx)
1505 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1506 sizeof(pstring) - 2, True);
1508 data->notify_data.data.length = len / 2 - 1;
1509 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1511 if (!data->notify_data.data.string) {
1512 data->notify_data.data.length = 0;
1516 memcpy(data->notify_data.data.string, temp, len);
1519 /*******************************************************************
1520 * fill a notify_info_data with the security descriptor
1521 * jfm:xxxx send an null pointer to say no security desc
1522 * have to implement security before !
1523 ********************************************************************/
1524 static void spoolss_notify_security_desc(int snum,
1525 SPOOL_NOTIFY_INFO_DATA *data,
1526 print_queue_struct *queue,
1527 NT_PRINTER_INFO_LEVEL *printer,
1528 TALLOC_CTX *mem_ctx)
1530 data->notify_data.data.length=0;
1531 data->notify_data.data.string = NULL;
1534 /*******************************************************************
1535 * fill a notify_info_data with the attributes
1536 * jfm:xxxx a samba printer is always shared
1537 ********************************************************************/
1538 static void spoolss_notify_attributes(int snum,
1539 SPOOL_NOTIFY_INFO_DATA *data,
1540 print_queue_struct *queue,
1541 NT_PRINTER_INFO_LEVEL *printer,
1542 TALLOC_CTX *mem_ctx)
1544 data->notify_data.value[0] = printer->info_2->attributes;
1547 /*******************************************************************
1548 * fill a notify_info_data with the priority
1549 ********************************************************************/
1550 static void spoolss_notify_priority(int snum,
1551 SPOOL_NOTIFY_INFO_DATA *data,
1552 print_queue_struct *queue,
1553 NT_PRINTER_INFO_LEVEL *printer,
1554 TALLOC_CTX *mem_ctx)
1556 data->notify_data.value[0] = printer->info_2->priority;
1559 /*******************************************************************
1560 * fill a notify_info_data with the default priority
1561 ********************************************************************/
1562 static void spoolss_notify_default_priority(int snum,
1563 SPOOL_NOTIFY_INFO_DATA *data,
1564 print_queue_struct *queue,
1565 NT_PRINTER_INFO_LEVEL *printer,
1566 TALLOC_CTX *mem_ctx)
1568 data->notify_data.value[0] = printer->info_2->default_priority;
1571 /*******************************************************************
1572 * fill a notify_info_data with the start time
1573 ********************************************************************/
1574 static void spoolss_notify_start_time(int snum,
1575 SPOOL_NOTIFY_INFO_DATA *data,
1576 print_queue_struct *queue,
1577 NT_PRINTER_INFO_LEVEL *printer,
1578 TALLOC_CTX *mem_ctx)
1580 data->notify_data.value[0] = printer->info_2->starttime;
1583 /*******************************************************************
1584 * fill a notify_info_data with the until time
1585 ********************************************************************/
1586 static void spoolss_notify_until_time(int snum,
1587 SPOOL_NOTIFY_INFO_DATA *data,
1588 print_queue_struct *queue,
1589 NT_PRINTER_INFO_LEVEL *printer,
1590 TALLOC_CTX *mem_ctx)
1592 data->notify_data.value[0] = printer->info_2->untiltime;
1595 /*******************************************************************
1596 * fill a notify_info_data with the status
1597 ********************************************************************/
1598 static void spoolss_notify_status(int snum,
1599 SPOOL_NOTIFY_INFO_DATA *data,
1600 print_queue_struct *queue,
1601 NT_PRINTER_INFO_LEVEL *printer,
1602 TALLOC_CTX *mem_ctx)
1606 print_queue_struct *q=NULL;
1607 print_status_struct status;
1609 memset(&status, 0, sizeof(status));
1610 count = print_queue_status(snum, &q, &status);
1611 data->notify_data.value[0]=(uint32) status.status;
1615 /*******************************************************************
1616 * fill a notify_info_data with the number of jobs queued
1617 ********************************************************************/
1618 static void spoolss_notify_cjobs(int snum,
1619 SPOOL_NOTIFY_INFO_DATA *data,
1620 print_queue_struct *queue,
1621 NT_PRINTER_INFO_LEVEL *printer,
1622 TALLOC_CTX *mem_ctx)
1624 print_queue_struct *q=NULL;
1625 print_status_struct status;
1627 memset(&status, 0, sizeof(status));
1628 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1632 /*******************************************************************
1633 * fill a notify_info_data with the average ppm
1634 ********************************************************************/
1635 static void spoolss_notify_average_ppm(int snum,
1636 SPOOL_NOTIFY_INFO_DATA *data,
1637 print_queue_struct *queue,
1638 NT_PRINTER_INFO_LEVEL *printer,
1639 TALLOC_CTX *mem_ctx)
1641 /* always respond 8 pages per minutes */
1642 /* a little hard ! */
1643 data->notify_data.value[0] = printer->info_2->averageppm;
1646 /*******************************************************************
1647 * fill a notify_info_data with username
1648 ********************************************************************/
1649 static void spoolss_notify_username(int snum,
1650 SPOOL_NOTIFY_INFO_DATA *data,
1651 print_queue_struct *queue,
1652 NT_PRINTER_INFO_LEVEL *printer,
1653 TALLOC_CTX *mem_ctx)
1658 len = (uint32)dos_PutUniCode(temp, queue->user,
1659 sizeof(temp) - 2, True);
1661 data->notify_data.data.length = len / 2 - 1;
1662 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1664 if (!data->notify_data.data.string) {
1665 data->notify_data.data.length = 0;
1669 memcpy(data->notify_data.data.string, temp, len);
1672 /*******************************************************************
1673 * fill a notify_info_data with job status
1674 ********************************************************************/
1675 static void spoolss_notify_job_status(int snum,
1676 SPOOL_NOTIFY_INFO_DATA *data,
1677 print_queue_struct *queue,
1678 NT_PRINTER_INFO_LEVEL *printer,
1679 TALLOC_CTX *mem_ctx)
1681 data->notify_data.value[0]=nt_printj_status(queue->status);
1684 /*******************************************************************
1685 * fill a notify_info_data with job name
1686 ********************************************************************/
1687 static void spoolss_notify_job_name(int snum,
1688 SPOOL_NOTIFY_INFO_DATA *data,
1689 print_queue_struct *queue,
1690 NT_PRINTER_INFO_LEVEL *printer,
1691 TALLOC_CTX *mem_ctx)
1696 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1699 data->notify_data.data.length = len / 2 - 1;
1700 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1702 if (!data->notify_data.data.string) {
1703 data->notify_data.data.length = 0;
1707 memcpy(data->notify_data.data.string, temp, len);
1710 /*******************************************************************
1711 * fill a notify_info_data with job status
1712 ********************************************************************/
1713 static void spoolss_notify_job_status_string(int snum,
1714 SPOOL_NOTIFY_INFO_DATA *data,
1715 print_queue_struct *queue,
1716 NT_PRINTER_INFO_LEVEL *printer,
1717 TALLOC_CTX *mem_ctx)
1719 char *p = "unknown";
1723 switch (queue->status) {
1728 p = ""; /* NT provides the paused string */
1738 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1740 data->notify_data.data.length = len / 2 - 1;
1741 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1743 if (!data->notify_data.data.string) {
1744 data->notify_data.data.length = 0;
1748 memcpy(data->notify_data.data.string, temp, len);
1751 /*******************************************************************
1752 * fill a notify_info_data with job time
1753 ********************************************************************/
1754 static void spoolss_notify_job_time(int snum,
1755 SPOOL_NOTIFY_INFO_DATA *data,
1756 print_queue_struct *queue,
1757 NT_PRINTER_INFO_LEVEL *printer,
1758 TALLOC_CTX *mem_ctx)
1760 data->notify_data.value[0]=0x0;
1763 /*******************************************************************
1764 * fill a notify_info_data with job size
1765 ********************************************************************/
1766 static void spoolss_notify_job_size(int snum,
1767 SPOOL_NOTIFY_INFO_DATA *data,
1768 print_queue_struct *queue,
1769 NT_PRINTER_INFO_LEVEL *printer,
1770 TALLOC_CTX *mem_ctx)
1772 data->notify_data.value[0]=queue->size;
1775 /*******************************************************************
1776 * fill a notify_info_data with job position
1777 ********************************************************************/
1778 static void spoolss_notify_job_position(int snum,
1779 SPOOL_NOTIFY_INFO_DATA *data,
1780 print_queue_struct *queue,
1781 NT_PRINTER_INFO_LEVEL *printer,
1782 TALLOC_CTX *mem_ctx)
1784 data->notify_data.value[0]=queue->job;
1787 /*******************************************************************
1788 * fill a notify_info_data with submitted time
1789 ********************************************************************/
1790 static void spoolss_notify_submitted_time(int snum,
1791 SPOOL_NOTIFY_INFO_DATA *data,
1792 print_queue_struct *queue,
1793 NT_PRINTER_INFO_LEVEL *printer,
1794 TALLOC_CTX *mem_ctx)
1799 t=gmtime(&queue->time);
1801 len = sizeof(SYSTEMTIME);
1803 data->notify_data.data.length = len;
1804 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1806 if (!data->notify_data.data.string) {
1807 data->notify_data.data.length = 0;
1811 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1816 struct s_notify_info_data_table
1822 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1823 print_queue_struct *queue,
1824 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
1827 struct s_notify_info_data_table notify_info_data_table[] =
1829 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1830 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1831 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1832 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1833 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1834 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1835 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1836 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1837 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1838 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1839 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1840 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1841 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1842 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1843 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1844 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1845 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1846 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1847 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1848 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1849 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1850 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1851 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1852 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1853 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1854 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1855 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1856 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1857 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1858 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1859 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1860 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1861 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1862 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1863 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1864 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1865 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1866 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1867 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1868 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1869 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1870 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1871 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1872 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1873 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1874 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1875 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1876 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1877 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1878 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1879 { END, END, "", END, NULL }
1882 /*******************************************************************
1883 return the size of info_data structure
1884 ********************************************************************/
1885 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1889 while (notify_info_data_table[i].type != END)
1891 if ( (notify_info_data_table[i].type == type ) &&
1892 (notify_info_data_table[i].field == field ) )
1894 return (notify_info_data_table[i].size);
1901 /*******************************************************************
1902 return the type of notify_info_data
1903 ********************************************************************/
1904 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1908 while (notify_info_data_table[i].type != END)
1910 if ( (notify_info_data_table[i].type == type ) &&
1911 (notify_info_data_table[i].field == field ) )
1913 if (notify_info_data_table[i].size == POINTER)
1927 /****************************************************************************
1928 ****************************************************************************/
1929 static int search_notify(uint16 type, uint16 field, int *value)
1934 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1936 if ( (notify_info_data_table[j].type == type ) &&
1937 (notify_info_data_table[j].field == field ) )
1942 if ( found && (notify_info_data_table[j].fn != NULL) )
1948 /****************************************************************************
1949 ****************************************************************************/
1950 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1952 info_data->type = type;
1953 info_data->field = field;
1954 info_data->reserved = 0;
1956 info_data->size = size_of_notify_info_data(type, field);
1957 info_data->enc_type = type_of_notify_info_data(type, field);
1961 /*******************************************************************
1963 * fill a notify_info struct with info asked
1965 ********************************************************************/
1966 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
1967 snum, SPOOL_NOTIFY_OPTION_TYPE
1968 *option_type, uint32 id,
1969 TALLOC_CTX *mem_ctx)
1975 SPOOL_NOTIFY_INFO_DATA *current_data;
1976 NT_PRINTER_INFO_LEVEL *printer = NULL;
1977 print_queue_struct *queue=NULL;
1979 type=option_type->type;
1981 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1982 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1983 option_type->count, lp_servicename(snum)));
1985 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1988 for(field_num=0; field_num<option_type->count; field_num++) {
1989 field = option_type->fields[field_num];
1990 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1992 if (!search_notify(type, field, &j) )
1995 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1998 current_data=&info->data[info->count];
2000 construct_info_data(current_data, type, field, id);
2002 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2003 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2005 notify_info_data_table[j].fn(snum, current_data, queue,
2011 free_a_printer(&printer, 2);
2015 /*******************************************************************
2017 * fill a notify_info struct with info asked
2019 ********************************************************************/
2020 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2021 SPOOL_NOTIFY_INFO *info,
2022 NT_PRINTER_INFO_LEVEL *printer,
2023 int snum, SPOOL_NOTIFY_OPTION_TYPE
2024 *option_type, uint32 id,
2025 TALLOC_CTX *mem_ctx)
2031 SPOOL_NOTIFY_INFO_DATA *current_data;
2033 DEBUG(4,("construct_notify_jobs_info\n"));
2035 type = option_type->type;
2037 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2038 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2039 option_type->count));
2041 for(field_num=0; field_num<option_type->count; field_num++) {
2042 field = option_type->fields[field_num];
2044 if (!search_notify(type, field, &j) )
2047 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2051 current_data=&(info->data[info->count]);
2053 construct_info_data(current_data, type, field, id);
2054 notify_info_data_table[j].fn(snum, current_data, queue,
2063 * JFM: The enumeration is not that simple, it's even non obvious.
2065 * let's take an example: I want to monitor the PRINTER SERVER for
2066 * the printer's name and the number of jobs currently queued.
2067 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2068 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2070 * I have 3 printers on the back of my server.
2072 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2075 * 1 printer 1 name 1
2076 * 2 printer 1 cjob 1
2077 * 3 printer 2 name 2
2078 * 4 printer 2 cjob 2
2079 * 5 printer 3 name 3
2080 * 6 printer 3 name 3
2082 * that's the print server case, the printer case is even worse.
2087 /*******************************************************************
2089 * enumerate all printers on the printserver
2090 * fill a notify_info struct with info asked
2092 ********************************************************************/
2093 static uint32 printserver_notify_info(const POLICY_HND *hnd,
2094 SPOOL_NOTIFY_INFO *info,
2095 TALLOC_CTX *mem_ctx)
2098 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2099 int n_services=lp_numservices();
2102 SPOOL_NOTIFY_OPTION *option;
2103 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2105 DEBUG(4,("printserver_notify_info\n"));
2107 option=Printer->notify.option;
2113 for (i=0; i<option->count; i++) {
2114 option_type=&(option->ctr.type[i]);
2116 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2119 for (snum=0; snum<n_services; snum++)
2120 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2121 if (construct_notify_printer_info
2122 (info, snum, option_type, id, mem_ctx))
2127 * Debugging information, don't delete.
2130 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2131 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2132 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2134 for (i=0; i<info->count; i++) {
2135 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2136 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2137 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2141 return NT_STATUS_NO_PROBLEMO;
2144 /*******************************************************************
2146 * fill a notify_info struct with info asked
2148 ********************************************************************/
2149 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2150 TALLOC_CTX *mem_ctx)
2153 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2156 SPOOL_NOTIFY_OPTION *option;
2157 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2159 print_queue_struct *queue=NULL;
2160 print_status_struct status;
2162 DEBUG(4,("printer_notify_info\n"));
2164 option=Printer->notify.option;
2170 get_printer_snum(hnd, &snum);
2172 for (i=0; i<option->count; i++) {
2173 option_type=&option->ctr.type[i];
2175 switch ( option_type->type ) {
2176 case PRINTER_NOTIFY_TYPE:
2177 if(construct_notify_printer_info(info, snum,
2183 case JOB_NOTIFY_TYPE: {
2184 NT_PRINTER_INFO_LEVEL *printer = NULL;
2186 memset(&status, 0, sizeof(status));
2187 count = print_queue_status(snum, &queue, &status);
2189 if (get_a_printer(&printer, 2,
2190 lp_servicename(snum)) != 0)
2193 for (j=0; j<count; j++) {
2194 construct_notify_jobs_info(&queue[j], info,
2201 free_a_printer(&printer, 2);
2211 * Debugging information, don't delete.
2214 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2215 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2216 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2218 for (i=0; i<info->count; i++) {
2219 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2220 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2221 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2224 return NT_STATUS_NO_PROBLEMO;
2227 /********************************************************************
2229 ********************************************************************/
2230 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
2231 SPOOL_NOTIFY_OPTION *option, TALLOC_CTX *mem_ctx,
2232 SPOOL_NOTIFY_INFO *info)
2234 Printer_entry *Printer=find_printer_index_by_hnd(handle);
2235 uint32 result = ERROR_INVALID_HANDLE;
2237 if (!OPEN_HANDLE(Printer)) {
2238 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2239 OUR_HANDLE(handle)));
2243 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2245 /* jfm: the change value isn't used right now.
2246 * we will honour it when
2247 * a) we'll be able to send notification to the client
2248 * b) we'll have a way to communicate between the spoolss process.
2250 * same thing for option->flags
2251 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2252 * I don't have a global notification system, I'm sending back all the
2253 * informations even when _NOTHING_ has changed.
2256 /* just discard the SPOOL_NOTIFY_OPTION */
2258 safe_free(option->ctr.type);
2260 switch (Printer->printer_type) {
2261 case PRINTER_HANDLE_IS_PRINTSERVER:
2262 result = printserver_notify_info(handle, info,
2266 case PRINTER_HANDLE_IS_PRINTER:
2267 result = printer_notify_info(handle, info, mem_ctx);
2275 /********************************************************************
2276 * construct_printer_info_0
2277 * fill a printer_info_0 struct
2278 ********************************************************************/
2279 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2283 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2284 counter_printer_0 *session_counter;
2285 uint32 global_counter;
2289 print_queue_struct *queue=NULL;
2290 print_status_struct status;
2292 memset(&status, 0, sizeof(status));
2294 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2297 count = print_queue_status(snum, &queue, &status);
2299 /* check if we already have a counter for this printer */
2300 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2302 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2303 if (session_counter->snum == snum)
2307 /* it's the first time, add it to the list */
2308 if (session_counter==NULL) {
2309 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2310 free_a_printer(&ntprinter, 2);
2313 ZERO_STRUCTP(session_counter);
2314 session_counter->snum=snum;
2315 session_counter->counter=0;
2316 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2320 session_counter->counter++;
2323 * the global_counter should be stored in a TDB as it's common to all the clients
2324 * and should be zeroed on samba startup
2326 global_counter=session_counter->counter;
2328 pstrcpy(chaine,ntprinter->info_2->printername);
2330 init_unistr(&printer->printername, chaine);
2332 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2333 init_unistr(&printer->servername, chaine);
2335 printer->cjobs = count;
2336 printer->total_jobs = 0;
2337 printer->total_bytes = 0;
2339 setuptime = (time_t)ntprinter->info_2->setuptime;
2340 t=gmtime(&setuptime);
2342 printer->year = t->tm_year+1900;
2343 printer->month = t->tm_mon+1;
2344 printer->dayofweek = t->tm_wday;
2345 printer->day = t->tm_mday;
2346 printer->hour = t->tm_hour;
2347 printer->minute = t->tm_min;
2348 printer->second = t->tm_sec;
2349 printer->milliseconds = 0;
2351 printer->global_counter = global_counter;
2352 printer->total_pages = 0;
2353 printer->major_version = 0x0004; /* NT 4 */
2354 printer->build_version = 0x0565; /* build 1381 */
2355 printer->unknown7 = 0x1;
2356 printer->unknown8 = 0x0;
2357 printer->unknown9 = 0x0;
2358 printer->session_counter = session_counter->counter;
2359 printer->unknown11 = 0x0;
2360 printer->printer_errors = 0x0; /* number of print failure */
2361 printer->unknown13 = 0x0;
2362 printer->unknown14 = 0x1;
2363 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2364 printer->unknown16 = 0x0;
2365 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2366 printer->unknown18 = 0x0;
2367 printer->status = nt_printq_status(status.status);
2368 printer->unknown20 = 0x0;
2369 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2370 printer->unknown22 = 0x0;
2371 printer->unknown23 = 0x6; /* 6 ???*/
2372 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2373 printer->unknown25 = 0;
2374 printer->unknown26 = 0;
2375 printer->unknown27 = 0;
2376 printer->unknown28 = 0;
2377 printer->unknown29 = 0;
2380 free_a_printer(&ntprinter,2);
2384 /********************************************************************
2385 * construct_printer_info_1
2386 * fill a printer_info_1 struct
2387 ********************************************************************/
2388 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2392 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2394 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2397 printer->flags=flags;
2399 if (*ntprinter->info_2->comment == '\0') {
2400 init_unistr(&printer->comment, lp_comment(snum));
2401 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2402 ntprinter->info_2->drivername, lp_comment(snum));
2405 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2406 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2407 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2410 snprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2412 init_unistr(&printer->description, chaine);
2413 init_unistr(&printer->name, chaine2);
2415 free_a_printer(&ntprinter,2);
2420 /****************************************************************************
2421 Free a DEVMODE struct.
2422 ****************************************************************************/
2424 static void free_dev_mode(DEVICEMODE *dev)
2430 safe_free(dev->private);
2435 /****************************************************************************
2436 Create a DEVMODE struct. Returns malloced memory.
2437 ****************************************************************************/
2439 static DEVICEMODE *construct_dev_mode(int snum)
2443 NT_PRINTER_INFO_LEVEL *printer = NULL;
2444 NT_DEVICEMODE *ntdevmode = NULL;
2445 DEVICEMODE *devmode = NULL;
2447 DEBUG(7,("construct_dev_mode\n"));
2449 DEBUGADD(8,("getting printer characteristics\n"));
2451 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2452 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2456 ZERO_STRUCTP(devmode);
2458 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2461 if (printer->info_2->devmode)
2462 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2464 if (ntdevmode == NULL)
2467 DEBUGADD(8,("loading DEVICEMODE\n"));
2469 snprintf(adevice, sizeof(adevice), printer->info_2->printername);
2470 init_unistr(&devmode->devicename, adevice);
2472 snprintf(aform, sizeof(aform), ntdevmode->formname);
2473 init_unistr(&devmode->formname, aform);
2475 devmode->specversion = ntdevmode->specversion;
2476 devmode->driverversion = ntdevmode->driverversion;
2477 devmode->size = ntdevmode->size;
2478 devmode->driverextra = ntdevmode->driverextra;
2479 devmode->fields = ntdevmode->fields;
2481 devmode->orientation = ntdevmode->orientation;
2482 devmode->papersize = ntdevmode->papersize;
2483 devmode->paperlength = ntdevmode->paperlength;
2484 devmode->paperwidth = ntdevmode->paperwidth;
2485 devmode->scale = ntdevmode->scale;
2486 devmode->copies = ntdevmode->copies;
2487 devmode->defaultsource = ntdevmode->defaultsource;
2488 devmode->printquality = ntdevmode->printquality;
2489 devmode->color = ntdevmode->color;
2490 devmode->duplex = ntdevmode->duplex;
2491 devmode->yresolution = ntdevmode->yresolution;
2492 devmode->ttoption = ntdevmode->ttoption;
2493 devmode->collate = ntdevmode->collate;
2494 devmode->icmmethod = ntdevmode->icmmethod;
2495 devmode->icmintent = ntdevmode->icmintent;
2496 devmode->mediatype = ntdevmode->mediatype;
2497 devmode->dithertype = ntdevmode->dithertype;
2499 if (ntdevmode->private != NULL) {
2500 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2504 free_nt_devicemode(&ntdevmode);
2505 free_a_printer(&printer,2);
2512 free_nt_devicemode(&ntdevmode);
2514 free_a_printer(&printer,2);
2515 free_dev_mode(devmode);
2520 /********************************************************************
2521 * construct_printer_info_2
2522 * fill a printer_info_2 struct
2523 ********************************************************************/
2525 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2528 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2530 print_queue_struct *queue=NULL;
2531 print_status_struct status;
2532 memset(&status, 0, sizeof(status));
2534 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2537 memset(&status, 0, sizeof(status));
2538 count = print_queue_status(snum, &queue, &status);
2540 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2541 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2542 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2543 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2544 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2546 if (*ntprinter->info_2->comment == '\0')
2547 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2549 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2551 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2552 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2553 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2554 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2555 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2557 printer->attributes = ntprinter->info_2->attributes;
2559 printer->priority = ntprinter->info_2->priority; /* priority */
2560 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2561 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2562 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2563 printer->status = nt_printq_status(status.status); /* status */
2564 printer->cjobs = count; /* jobs */
2565 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2567 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2568 DEBUG(8, ("Returning NULL Devicemode!\n"));
2571 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2572 /* steal the printer info sec_desc structure. [badly done]. */
2573 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2574 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2575 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2576 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2579 printer->secdesc = NULL;
2582 free_a_printer(&ntprinter, 2);
2587 /********************************************************************
2588 * construct_printer_info_3
2589 * fill a printer_info_3 struct
2590 ********************************************************************/
2591 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2593 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2594 PRINTER_INFO_3 *printer = NULL;
2596 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2600 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2601 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2605 ZERO_STRUCTP(printer);
2607 printer->flags = 4; /* These are the components of the SD we are returning. */
2608 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2609 /* steal the printer info sec_desc structure. [badly done]. */
2610 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2614 * Set the flags for the components we are returning.
2617 if (printer->secdesc->owner_sid)
2618 printer->flags |= OWNER_SECURITY_INFORMATION;
2620 if (printer->secdesc->grp_sid)
2621 printer->flags |= GROUP_SECURITY_INFORMATION;
2623 if (printer->secdesc->dacl)
2624 printer->flags |= DACL_SECURITY_INFORMATION;
2626 if (printer->secdesc->sacl)
2627 printer->flags |= SACL_SECURITY_INFORMATION;
2630 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2631 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2632 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2635 free_a_printer(&ntprinter, 2);
2637 *pp_printer = printer;
2641 /********************************************************************
2642 Spoolss_enumprinters.
2643 ********************************************************************/
2644 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2648 int n_services=lp_numservices();
2649 PRINTER_INFO_1 *printers=NULL;
2650 PRINTER_INFO_1 current_prt;
2652 DEBUG(4,("enum_all_printers_info_1\n"));
2654 for (snum=0; snum<n_services; snum++) {
2655 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2656 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2658 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2659 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2661 return ERROR_NOT_ENOUGH_MEMORY;
2663 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2664 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2670 /* check the required size. */
2671 for (i=0; i<*returned; i++)
2672 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2674 if (!alloc_buffer_size(buffer, *needed))
2675 return ERROR_INSUFFICIENT_BUFFER;
2677 /* fill the buffer with the structures */
2678 for (i=0; i<*returned; i++)
2679 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2682 safe_free(printers);
2684 if (*needed > offered) {
2686 return ERROR_INSUFFICIENT_BUFFER;
2689 return NT_STATUS_NO_PROBLEMO;
2692 /********************************************************************
2693 enum_all_printers_info_1_local.
2694 *********************************************************************/
2695 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2697 DEBUG(4,("enum_all_printers_info_1_local\n"));
2699 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2702 /********************************************************************
2703 enum_all_printers_info_1_name.
2704 *********************************************************************/
2705 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2708 DEBUG(4,("enum_all_printers_info_1_name\n"));
2710 fstrcpy(temp, "\\\\");
2711 fstrcat(temp, global_myname);
2713 if (strequal(name, temp)) {
2714 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2717 return ERROR_INVALID_NAME;
2720 /********************************************************************
2721 enum_all_printers_info_1_remote.
2722 *********************************************************************/
2723 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2725 PRINTER_INFO_1 *printer;
2726 fstring printername;
2729 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2731 /* JFM: currently it's more a place holder than anything else.
2732 * In the spooler world there is a notion of server registration.
2733 * the print servers are registring (sp ?) on the PDC (in the same domain)
2735 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2738 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2739 return ERROR_NOT_ENOUGH_MEMORY;
2743 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2744 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2745 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2747 init_unistr(&printer->description, desc);
2748 init_unistr(&printer->name, printername);
2749 init_unistr(&printer->comment, comment);
2750 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2752 /* check the required size. */
2753 *needed += spoolss_size_printer_info_1(printer);
2755 if (!alloc_buffer_size(buffer, *needed)) {
2757 return ERROR_INSUFFICIENT_BUFFER;
2760 /* fill the buffer with the structures */
2761 new_smb_io_printer_info_1("", buffer, printer, 0);
2766 if (*needed > offered) {
2768 return ERROR_INSUFFICIENT_BUFFER;
2771 return NT_STATUS_NO_PROBLEMO;
2774 /********************************************************************
2775 enum_all_printers_info_1_network.
2776 *********************************************************************/
2777 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2779 DEBUG(4,("enum_all_printers_info_1_network\n"));
2781 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2784 /********************************************************************
2785 * api_spoolss_enumprinters
2787 * called from api_spoolss_enumprinters (see this to understand)
2788 ********************************************************************/
2789 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2793 int n_services=lp_numservices();
2794 PRINTER_INFO_2 *printers=NULL;
2795 PRINTER_INFO_2 current_prt;
2797 for (snum=0; snum<n_services; snum++) {
2798 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2799 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2801 if (construct_printer_info_2(¤t_prt, snum)) {
2802 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2803 return ERROR_NOT_ENOUGH_MEMORY;
2804 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2805 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2811 /* check the required size. */
2812 for (i=0; i<*returned; i++)
2813 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2815 if (!alloc_buffer_size(buffer, *needed)) {
2816 for (i=0; i<*returned; i++) {
2817 free_devmode(printers[i].devmode);
2818 free_sec_desc(&printers[i].secdesc);
2820 safe_free(printers);
2821 return ERROR_INSUFFICIENT_BUFFER;
2824 /* fill the buffer with the structures */
2825 for (i=0; i<*returned; i++)
2826 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2829 for (i=0; i<*returned; i++) {
2830 free_devmode(printers[i].devmode);
2831 free_sec_desc(&printers[i].secdesc);
2833 safe_free(printers);
2835 if (*needed > offered) {
2837 return ERROR_INSUFFICIENT_BUFFER;
2840 return NT_STATUS_NO_PROBLEMO;
2843 /********************************************************************
2844 * handle enumeration of printers at level 1
2845 ********************************************************************/
2846 static uint32 enumprinters_level1( uint32 flags, fstring name,
2847 NEW_BUFFER *buffer, uint32 offered,
2848 uint32 *needed, uint32 *returned)
2850 /* Not all the flags are equals */
2852 if (flags & PRINTER_ENUM_LOCAL)
2853 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2855 if (flags & PRINTER_ENUM_NAME)
2856 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2858 if (flags & PRINTER_ENUM_REMOTE)
2859 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2861 if (flags & PRINTER_ENUM_NETWORK)
2862 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
2864 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2867 /********************************************************************
2868 * handle enumeration of printers at level 2
2869 ********************************************************************/
2870 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2871 NEW_BUFFER *buffer, uint32 offered,
2872 uint32 *needed, uint32 *returned)
2876 fstrcpy(temp, "\\\\");
2877 fstrcat(temp, global_myname);
2879 if (flags & PRINTER_ENUM_LOCAL) {
2880 if (strequal(servername, temp))
2881 return enum_all_printers_info_2(buffer, offered, needed, returned);
2883 return enum_all_printers_info_2(buffer, offered, needed, returned);
2886 if (flags & PRINTER_ENUM_NAME) {
2887 if (strequal(servername, temp))
2888 return enum_all_printers_info_2(buffer, offered, needed, returned);
2890 return ERROR_INVALID_NAME;
2893 if (flags & PRINTER_ENUM_REMOTE)
2894 return ERROR_INVALID_LEVEL;
2896 return NT_STATUS_NO_PROBLEMO;
2899 /********************************************************************
2900 * handle enumeration of printers at level 5
2901 ********************************************************************/
2902 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2903 NEW_BUFFER *buffer, uint32 offered,
2904 uint32 *needed, uint32 *returned)
2906 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2907 return NT_STATUS_NO_PROBLEMO;
2910 /********************************************************************
2911 * api_spoolss_enumprinters
2913 * called from api_spoolss_enumprinters (see this to understand)
2914 ********************************************************************/
2915 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2916 NEW_BUFFER *buffer, uint32 offered,
2917 uint32 *needed, uint32 *returned)
2921 DEBUG(4,("_spoolss_enumprinters\n"));
2928 * flags==PRINTER_ENUM_NAME
2929 * if name=="" then enumerates all printers
2930 * if name!="" then enumerate the printer
2931 * flags==PRINTER_ENUM_REMOTE
2932 * name is NULL, enumerate printers
2933 * Level 2: name!="" enumerates printers, name can't be NULL
2934 * Level 3: doesn't exist
2935 * Level 4: does a local registry lookup
2936 * Level 5: same as Level 2
2939 unistr2_to_ascii(name, servername, sizeof(name)-1);
2944 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2946 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2948 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2952 return ERROR_INVALID_LEVEL;
2956 /****************************************************************************
2957 ****************************************************************************/
2958 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2960 PRINTER_INFO_0 *printer=NULL;
2962 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2963 return ERROR_NOT_ENOUGH_MEMORY;
2965 construct_printer_info_0(printer, snum);
2967 /* check the required size. */
2968 *needed += spoolss_size_printer_info_0(printer);
2970 if (!alloc_buffer_size(buffer, *needed)) {
2972 return ERROR_INSUFFICIENT_BUFFER;
2975 /* fill the buffer with the structures */
2976 new_smb_io_printer_info_0("", buffer, printer, 0);
2981 if (*needed > offered) {
2982 return ERROR_INSUFFICIENT_BUFFER;
2985 return NT_STATUS_NO_PROBLEMO;
2988 /****************************************************************************
2989 ****************************************************************************/
2990 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2992 PRINTER_INFO_1 *printer=NULL;
2994 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2995 return ERROR_NOT_ENOUGH_MEMORY;
2997 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
2999 /* check the required size. */
3000 *needed += spoolss_size_printer_info_1(printer);
3002 if (!alloc_buffer_size(buffer, *needed)) {
3004 return ERROR_INSUFFICIENT_BUFFER;
3007 /* fill the buffer with the structures */
3008 new_smb_io_printer_info_1("", buffer, printer, 0);
3013 if (*needed > offered) {
3014 return ERROR_INSUFFICIENT_BUFFER;
3017 return NT_STATUS_NO_PROBLEMO;
3020 /****************************************************************************
3021 ****************************************************************************/
3022 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3024 PRINTER_INFO_2 *printer=NULL;
3026 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3027 return ERROR_NOT_ENOUGH_MEMORY;
3029 construct_printer_info_2(printer, snum);
3031 /* check the required size. */
3032 *needed += spoolss_size_printer_info_2(printer);
3034 if (!alloc_buffer_size(buffer, *needed)) {
3035 free_printer_info_2(printer);
3036 return ERROR_INSUFFICIENT_BUFFER;
3039 /* fill the buffer with the structures */
3040 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
3041 free_printer_info_2(printer);
3042 return ERROR_NOT_ENOUGH_MEMORY;
3046 free_printer_info_2(printer);
3048 if (*needed > offered) {
3049 return ERROR_INSUFFICIENT_BUFFER;
3052 return NT_STATUS_NO_PROBLEMO;
3055 /****************************************************************************
3056 ****************************************************************************/
3057 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3059 PRINTER_INFO_3 *printer=NULL;
3061 if (!construct_printer_info_3(&printer, snum))
3062 return ERROR_NOT_ENOUGH_MEMORY;
3064 /* check the required size. */
3065 *needed += spoolss_size_printer_info_3(printer);
3067 if (!alloc_buffer_size(buffer, *needed)) {
3068 free_printer_info_3(printer);
3069 return ERROR_INSUFFICIENT_BUFFER;
3072 /* fill the buffer with the structures */
3073 new_smb_io_printer_info_3("", buffer, printer, 0);
3076 free_printer_info_3(printer);
3078 if (*needed > offered) {
3079 return ERROR_INSUFFICIENT_BUFFER;
3082 return NT_STATUS_NO_PROBLEMO;
3085 /****************************************************************************
3086 ****************************************************************************/
3087 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
3088 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3094 if (!get_printer_snum(handle, &snum))
3095 return ERROR_INVALID_HANDLE;
3099 return getprinter_level_0(snum, buffer, offered, needed);
3101 return getprinter_level_1(snum, buffer, offered, needed);
3103 return getprinter_level_2(snum, buffer, offered, needed);
3105 return getprinter_level_3(snum, buffer, offered, needed);
3107 return ERROR_INVALID_LEVEL;
3111 /********************************************************************
3112 * fill a DRIVER_INFO_1 struct
3113 ********************************************************************/
3114 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3116 init_unistr( &info->name, driver.info_3->name);
3119 /********************************************************************
3120 * construct_printer_driver_info_1
3121 ********************************************************************/
3122 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3124 NT_PRINTER_INFO_LEVEL *printer = NULL;
3125 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3127 ZERO_STRUCT(driver);
3129 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3130 return ERROR_INVALID_PRINTER_NAME;
3132 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3133 return ERROR_UNKNOWN_PRINTER_DRIVER;
3135 fill_printer_driver_info_1(info, driver, servername, architecture);
3137 free_a_printer(&printer,2);
3139 return NT_STATUS_NO_PROBLEMO;
3142 /********************************************************************
3143 * construct_printer_driver_info_2
3144 * fill a printer_info_2 struct
3145 ********************************************************************/
3146 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3150 info->version=driver.info_3->cversion;
3152 init_unistr( &info->name, driver.info_3->name );
3153 init_unistr( &info->architecture, driver.info_3->environment );
3156 if (strlen(driver.info_3->driverpath)) {
3157 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3158 init_unistr( &info->driverpath, temp );
3160 init_unistr( &info->driverpath, "" );
3162 if (strlen(driver.info_3->datafile)) {
3163 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3164 init_unistr( &info->datafile, temp );
3166 init_unistr( &info->datafile, "" );
3168 if (strlen(driver.info_3->configfile)) {
3169 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3170 init_unistr( &info->configfile, temp );
3172 init_unistr( &info->configfile, "" );
3175 /********************************************************************
3176 * construct_printer_driver_info_2
3177 * fill a printer_info_2 struct
3178 ********************************************************************/
3179 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3181 NT_PRINTER_INFO_LEVEL *printer = NULL;
3182 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3184 ZERO_STRUCT(printer);
3185 ZERO_STRUCT(driver);
3187 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3188 return ERROR_INVALID_PRINTER_NAME;
3190 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3191 return ERROR_UNKNOWN_PRINTER_DRIVER;
3193 fill_printer_driver_info_2(info, driver, servername);
3195 free_a_printer(&printer,2);
3197 return NT_STATUS_NO_PROBLEMO;
3200 /********************************************************************
3201 * copy a strings array and convert to UNICODE
3203 * convert an array of ascii string to a UNICODE string
3204 ********************************************************************/
3205 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3212 DEBUG(6,("init_unistr_array\n"));
3216 if (char_array == NULL)
3220 if (!v) v = ""; /* hack to handle null lists */
3222 if (strlen(v) == 0) break;
3223 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3224 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3225 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3226 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3229 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3234 (*uni_array)[j]=0x0000;
3237 DEBUGADD(6,("last one:done\n"));
3240 /********************************************************************
3241 * construct_printer_info_3
3242 * fill a printer_info_3 struct
3243 ********************************************************************/
3244 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3250 info->version=driver.info_3->cversion;
3252 init_unistr( &info->name, driver.info_3->name );
3253 init_unistr( &info->architecture, driver.info_3->environment );
3255 if (strlen(driver.info_3->driverpath)) {
3256 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3257 init_unistr( &info->driverpath, temp );
3259 init_unistr( &info->driverpath, "" );
3261 if (strlen(driver.info_3->datafile)) {
3262 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3263 init_unistr( &info->datafile, temp );
3265 init_unistr( &info->datafile, "" );
3267 if (strlen(driver.info_3->configfile)) {
3268 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3269 init_unistr( &info->configfile, temp );
3271 init_unistr( &info->configfile, "" );
3273 if (strlen(driver.info_3->helpfile)) {
3274 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3275 init_unistr( &info->helpfile, temp );
3277 init_unistr( &info->helpfile, "" );
3279 init_unistr( &info->monitorname, driver.info_3->monitorname );
3280 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3282 info->dependentfiles=NULL;
3283 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3286 /********************************************************************
3287 * construct_printer_info_3
3288 * fill a printer_info_3 struct
3289 ********************************************************************/
3290 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3292 NT_PRINTER_INFO_LEVEL *printer = NULL;
3293 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3295 ZERO_STRUCT(driver);
3297 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3298 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3300 return ERROR_INVALID_PRINTER_NAME;
3302 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3303 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3305 free_a_printer(&printer,2);
3306 return ERROR_UNKNOWN_PRINTER_DRIVER;
3309 fill_printer_driver_info_3(info, driver, servername);
3311 free_a_printer(&printer,2);
3313 return NT_STATUS_NO_PROBLEMO;
3316 /********************************************************************
3317 * construct_printer_info_6
3318 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3319 ********************************************************************/
3321 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3327 memset(&nullstr, '\0', sizeof(fstring));
3329 info->version=driver.info_3->cversion;
3331 init_unistr( &info->name, driver.info_3->name );
3332 init_unistr( &info->architecture, driver.info_3->environment );
3334 if (strlen(driver.info_3->driverpath)) {
3335 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3336 init_unistr( &info->driverpath, temp );
3338 init_unistr( &info->driverpath, "" );
3340 if (strlen(driver.info_3->datafile)) {
3341 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3342 init_unistr( &info->datafile, temp );
3344 init_unistr( &info->datafile, "" );
3346 if (strlen(driver.info_3->configfile)) {
3347 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3348 init_unistr( &info->configfile, temp );
3350 init_unistr( &info->configfile, "" );
3352 if (strlen(driver.info_3->helpfile)) {
3353 snprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3354 init_unistr( &info->helpfile, temp );
3356 init_unistr( &info->helpfile, "" );
3358 init_unistr( &info->monitorname, driver.info_3->monitorname );
3359 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3361 info->dependentfiles=NULL;
3362 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3364 info->previousdrivernames=NULL;
3365 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3367 info->driver_date.low=0;
3368 info->driver_date.high=0;
3371 info->driver_version_low=0;
3372 info->driver_version_high=0;
3374 init_unistr( &info->mfgname, "");
3375 init_unistr( &info->oem_url, "");
3376 init_unistr( &info->hardware_id, "");
3377 init_unistr( &info->provider, "");
3380 /********************************************************************
3381 * construct_printer_info_6
3382 * fill a printer_info_6 struct
3383 ********************************************************************/
3384 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3386 NT_PRINTER_INFO_LEVEL *printer = NULL;
3387 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3389 ZERO_STRUCT(driver);
3391 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3392 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3394 return ERROR_INVALID_PRINTER_NAME;
3396 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3397 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3400 * Is this a W2k client ?
3404 free_a_printer(&printer,2);
3405 return ERROR_UNKNOWN_PRINTER_DRIVER;
3408 /* Yes - try again with a WinNT driver. */
3410 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3411 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3413 free_a_printer(&printer,2);
3414 return ERROR_UNKNOWN_PRINTER_DRIVER;
3418 fill_printer_driver_info_6(info, driver, servername);
3420 free_a_printer(&printer,2);
3422 return NT_STATUS_NO_PROBLEMO;
3425 /****************************************************************************
3426 ****************************************************************************/
3428 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3430 safe_free(info->dependentfiles);
3433 /****************************************************************************
3434 ****************************************************************************/
3436 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3438 safe_free(info->dependentfiles);
3442 /****************************************************************************
3443 ****************************************************************************/
3444 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3446 DRIVER_INFO_1 *info=NULL;
3449 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3450 return ERROR_NOT_ENOUGH_MEMORY;
3452 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3453 if (status != NT_STATUS_NO_PROBLEMO) {
3458 /* check the required size. */
3459 *needed += spoolss_size_printer_driver_info_1(info);
3461 if (!alloc_buffer_size(buffer, *needed)) {
3463 return ERROR_INSUFFICIENT_BUFFER;
3466 /* fill the buffer with the structures */
3467 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3472 if (*needed > offered)
3473 return ERROR_INSUFFICIENT_BUFFER;
3475 return NT_STATUS_NO_PROBLEMO;
3478 /****************************************************************************
3479 ****************************************************************************/
3480 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3482 DRIVER_INFO_2 *info=NULL;
3485 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3486 return ERROR_NOT_ENOUGH_MEMORY;
3488 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3489 if (status != NT_STATUS_NO_PROBLEMO) {
3494 /* check the required size. */
3495 *needed += spoolss_size_printer_driver_info_2(info);
3497 if (!alloc_buffer_size(buffer, *needed)) {
3499 return ERROR_INSUFFICIENT_BUFFER;
3502 /* fill the buffer with the structures */
3503 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3508 if (*needed > offered)
3509 return ERROR_INSUFFICIENT_BUFFER;
3511 return NT_STATUS_NO_PROBLEMO;
3514 /****************************************************************************
3515 ****************************************************************************/
3516 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3523 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3524 if (status != NT_STATUS_NO_PROBLEMO) {
3528 /* check the required size. */
3529 *needed += spoolss_size_printer_driver_info_3(&info);
3531 if (!alloc_buffer_size(buffer, *needed)) {
3532 free_printer_driver_info_3(&info);
3533 return ERROR_INSUFFICIENT_BUFFER;
3536 /* fill the buffer with the structures */
3537 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3539 free_printer_driver_info_3(&info);
3541 if (*needed > offered)
3542 return ERROR_INSUFFICIENT_BUFFER;
3544 return NT_STATUS_NO_PROBLEMO;
3547 /****************************************************************************
3548 ****************************************************************************/
3549 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3556 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3557 if (status != NT_STATUS_NO_PROBLEMO) {
3561 /* check the required size. */
3562 *needed += spoolss_size_printer_driver_info_6(&info);
3564 if (!alloc_buffer_size(buffer, *needed)) {
3565 free_printer_driver_info_6(&info);
3566 return ERROR_INSUFFICIENT_BUFFER;
3569 /* fill the buffer with the structures */
3570 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3572 free_printer_driver_info_6(&info);
3574 if (*needed > offered)
3575 return ERROR_INSUFFICIENT_BUFFER;
3577 return NT_STATUS_NO_PROBLEMO;
3580 /****************************************************************************
3581 ****************************************************************************/
3582 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3583 uint32 clientmajorversion, uint32 clientminorversion,
3584 NEW_BUFFER *buffer, uint32 offered,
3585 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3588 fstring architecture;
3591 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3594 *servermajorversion=0;
3595 *serverminorversion=0;
3597 pstrcpy(servername, global_myname);
3598 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3600 if (!get_printer_snum(handle, &snum))
3601 return ERROR_INVALID_HANDLE;
3605 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3607 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3609 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3611 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3613 return ERROR_INVALID_LEVEL;
3617 /****************************************************************************
3618 ****************************************************************************/
3619 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3621 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3623 if (OPEN_HANDLE(Printer)) {
3624 Printer->page_started=True;
3628 DEBUG(3,("Error in startpageprinter printer handle\n"));
3629 return ERROR_INVALID_HANDLE;
3632 /****************************************************************************
3633 ****************************************************************************/
3634 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3636 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3638 if (!OPEN_HANDLE(Printer)) {
3639 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3640 return ERROR_INVALID_HANDLE;
3643 Printer->page_started=False;
3645 return NT_STATUS_NO_PROBLEMO;
3648 /********************************************************************
3649 * api_spoolss_getprinter
3650 * called from the spoolss dispatcher
3652 ********************************************************************/
3653 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3654 pipes_struct *p, DOC_INFO *docinfo,
3657 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3661 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3662 struct current_user user;
3664 if (!OPEN_HANDLE(Printer)) {
3665 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3666 return ERROR_INVALID_HANDLE;
3669 get_current_user(&user, p);
3672 * a nice thing with NT is it doesn't listen to what you tell it.
3673 * when asked to send _only_ RAW datas, it tries to send datas
3676 * So I add checks like in NT Server ...
3678 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3679 * there's a bug in NT client-side code, so we'll fix it in the
3680 * server-side code. *nnnnnggggh!*
3683 if (info_1->p_datatype != 0) {
3684 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3685 if (strcmp(datatype, "RAW") != 0) {
3687 return ERROR_INVALID_DATATYPE;
3691 /* get the share number of the printer */
3692 if (!get_printer_snum(handle, &snum)) {
3693 return ERROR_INVALID_HANDLE;
3696 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3698 Printer->jobid = print_job_start(&user, snum, jobname);
3700 /* An error occured in print_job_start() so return an appropriate
3703 if (Printer->jobid == -1) {
3704 return map_nt_error_from_unix(errno);
3707 Printer->document_started=True;
3708 (*jobid) = Printer->jobid;
3713 /********************************************************************
3714 * api_spoolss_getprinter
3715 * called from the spoolss dispatcher
3717 ********************************************************************/
3718 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3720 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3722 if (!OPEN_HANDLE(Printer)) {
3723 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3724 return ERROR_INVALID_HANDLE;
3727 Printer->document_started=False;
3728 print_job_end(Printer->jobid,True);
3729 /* error codes unhandled so far ... */
3734 /****************************************************************************
3735 ****************************************************************************/
3736 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3739 uint32 *buffer_written)
3741 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3743 if (!OPEN_HANDLE(Printer)) {
3744 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3745 return ERROR_INVALID_HANDLE;
3748 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3754 /********************************************************************
3755 * api_spoolss_getprinter
3756 * called from the spoolss dispatcher
3758 ********************************************************************/
3759 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3762 struct current_user user;
3763 int snum, errcode = ERROR_INVALID_FUNCTION;
3764 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3766 get_current_user(&user, p);
3768 if (!OPEN_HANDLE(Printer)) {
3769 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3770 return ERROR_INVALID_HANDLE;
3773 if (!get_printer_snum(handle, &snum))
3774 return ERROR_INVALID_HANDLE;
3777 case PRINTER_CONTROL_PAUSE:
3778 if (print_queue_pause(&user, snum, &errcode)) {
3782 case PRINTER_CONTROL_RESUME:
3783 case PRINTER_CONTROL_UNPAUSE:
3784 if (print_queue_resume(&user, snum, &errcode)) {
3788 case PRINTER_CONTROL_PURGE:
3789 if (print_queue_purge(&user, snum, &errcode)) {
3794 return ERROR_INVALID_LEVEL;
3800 /********************************************************************
3801 * api_spoolss_abortprinter
3802 ********************************************************************/
3804 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3806 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3809 /********************************************************************
3810 * called by spoolss_api_setprinter
3811 * when updating a printer description
3812 ********************************************************************/
3813 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3814 const SPOOL_PRINTER_INFO_LEVEL *info,
3815 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3817 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3818 struct current_user user;
3822 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3824 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3825 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3826 OUR_HANDLE(handle)));
3828 result = ERROR_INVALID_HANDLE;
3832 /* NT seems to like setting the security descriptor even though
3833 nothing may have actually changed. This causes annoying
3834 dialog boxes when the user doesn't have permission to change
3835 the security descriptor. */
3837 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3839 if (DEBUGLEVEL >= 10) {
3843 acl = old_secdesc_ctr->sec->dacl;
3844 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3845 PRINTERNAME(snum), acl->num_aces));
3847 for (i = 0; i < acl->num_aces; i++) {
3850 sid_to_string(sid_str, &acl->ace[i].sid);
3852 DEBUG(10, ("%s 0x%08x\n", sid_str,
3853 acl->ace[i].info.mask));
3856 acl = secdesc_ctr->sec->dacl;
3859 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3860 PRINTERNAME(snum), acl->num_aces));
3862 for (i = 0; i < acl->num_aces; i++) {
3865 sid_to_string(sid_str, &acl->ace[i].sid);
3867 DEBUG(10, ("%s 0x%08x\n", sid_str,
3868 acl->ace[i].info.mask));
3871 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3875 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3877 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3878 result = NT_STATUS_NO_PROBLEMO;
3882 /* Work out which user is performing the operation */
3884 get_current_user(&user, p);
3886 /* Check the user has permissions to change the security
3887 descriptor. By experimentation with two NT machines, the user
3888 requires Full Access to the printer to change security
3891 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3892 result = ERROR_ACCESS_DENIED;
3896 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3899 free_sec_desc_buf(&new_secdesc_ctr);
3900 free_sec_desc_buf(&old_secdesc_ctr);
3905 /********************************************************************
3906 Do Samba sanity checks on a printer info struct.
3907 this has changed purpose: it now "canonicalises" printer
3908 info from a client rather than just checking it is correct
3909 ********************************************************************/
3911 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3913 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3914 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
3916 /* we force some elements to "correct" values */
3917 slprintf(info->servername, sizeof(info->servername), "\\\\%s", global_myname);
3918 slprintf(info->printername, sizeof(info->printername), "\\\\%s\\%s",
3919 global_myname, lp_servicename(snum));
3920 fstrcpy(info->sharename, lp_servicename(snum));
3921 info->attributes = PRINTER_ATTRIBUTE_SHARED \
3922 | PRINTER_ATTRIBUTE_LOCAL \
3923 | PRINTER_ATTRIBUTE_RAW_ONLY \
3924 | PRINTER_ATTRIBUTE_QUEUED ;
3929 /****************************************************************************
3930 ****************************************************************************/
3931 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3933 pid_t local_pid = sys_getpid();
3934 char *cmd = lp_addprinter_cmd();
3939 pstring driverlocation;
3943 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3944 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3948 /* build driver path... only 9X architecture is needed for legacy reasons */
3949 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3951 /* change \ to \\ for the shell */
3952 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3954 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3955 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3956 cmd, printer->info_2->printername, printer->info_2->sharename,
3957 printer->info_2->portname, printer->info_2->drivername,
3958 printer->info_2->location, driverlocation);
3962 /* Convert script args to unix-codepage */
3963 dos_to_unix(command, True);
3964 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3965 ret = smbrun(command, tmp_file, False);
3966 DEBUGADD(10,("returned [%d]\n", ret));
3974 /* Get lines and convert them back to dos-codepage */
3975 qlines = file_lines_load(tmp_file, &numlines, True);
3976 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3977 DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
3981 /* Set the portname to what the script says the portname should be. */
3982 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3983 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
3985 /* Send SIGHUP to process group... is there a better way? */
3990 file_lines_free(qlines);
3994 /* Return true if two devicemodes are equal */
3996 #define DEVMODE_CHECK_INT(field) \
3997 if (d1->field != d2->field) { \
3998 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
3999 d1->field, d2->field)); \
4003 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4005 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4008 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4009 return False; /* if either is exclusively NULL are not equal */
4012 if (!strequal(d1->devicename, d2->devicename) ||
4013 !strequal(d1->formname, d2->formname)) {
4014 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
4018 DEVMODE_CHECK_INT(specversion);
4019 DEVMODE_CHECK_INT(driverversion);
4020 DEVMODE_CHECK_INT(driverextra);
4021 DEVMODE_CHECK_INT(orientation);
4022 DEVMODE_CHECK_INT(papersize);
4023 DEVMODE_CHECK_INT(paperlength);
4024 DEVMODE_CHECK_INT(paperwidth);
4025 DEVMODE_CHECK_INT(scale);
4026 DEVMODE_CHECK_INT(copies);
4027 DEVMODE_CHECK_INT(defaultsource);
4028 DEVMODE_CHECK_INT(printquality);
4029 DEVMODE_CHECK_INT(color);
4030 DEVMODE_CHECK_INT(duplex);
4031 DEVMODE_CHECK_INT(yresolution);
4032 DEVMODE_CHECK_INT(ttoption);
4033 DEVMODE_CHECK_INT(collate);
4034 DEVMODE_CHECK_INT(logpixels);
4036 DEVMODE_CHECK_INT(fields);
4037 DEVMODE_CHECK_INT(bitsperpel);
4038 DEVMODE_CHECK_INT(pelswidth);
4039 DEVMODE_CHECK_INT(pelsheight);
4040 DEVMODE_CHECK_INT(displayflags);
4041 DEVMODE_CHECK_INT(displayfrequency);
4042 DEVMODE_CHECK_INT(icmmethod);
4043 DEVMODE_CHECK_INT(icmintent);
4044 DEVMODE_CHECK_INT(mediatype);
4045 DEVMODE_CHECK_INT(dithertype);
4046 DEVMODE_CHECK_INT(reserved1);
4047 DEVMODE_CHECK_INT(reserved2);
4048 DEVMODE_CHECK_INT(panningwidth);
4049 DEVMODE_CHECK_INT(panningheight);
4051 /* compare the private data if it exists */
4052 if (!d1->driverextra && !d2->driverextra) goto equal;
4055 DEVMODE_CHECK_INT(driverextra);
4057 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4058 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4063 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4067 /* Return true if two NT_PRINTER_PARAM structures are equal */
4069 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4070 NT_PRINTER_PARAM *p2)
4072 if (!p1 && !p2) goto equal;
4074 if ((!p1 && p2) || (p1 && !p2)) {
4075 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4079 /* Compare lists of printer parameters */
4083 NT_PRINTER_PARAM *q = p1;
4085 /* Find the parameter in the second structure */
4089 if (strequal(p1->value, q->value)) {
4091 if (p1->type != q->type) {
4092 DEBUG(10, ("nt_printer_param_equal():"
4093 "types for %s differ (%d != %d)\n",
4094 p1->value, p1->type,
4099 if (p1->data_len != q->data_len) {
4100 DEBUG(10, ("nt_printer_param_equal():"
4101 "len for %s differs (%d != %d)\n",
4102 p1->value, p1->data_len,
4107 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4110 DEBUG(10, ("nt_printer_param_equal():"
4111 "data for %s differs\n", p1->value));
4121 DEBUG(10, ("nt_printer_param_equal(): param %s "
4122 "does not exist\n", p1->value));
4131 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4135 /********************************************************************
4136 * Called by update_printer when trying to work out whether to
4137 * actually update printer info.
4138 ********************************************************************/
4140 #define PI_CHECK_INT(field) \
4141 if (pi1->field != pi2->field) { \
4142 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4143 pi1->field, pi2->field)); \
4147 #define PI_CHECK_STR(field) \
4148 if (!strequal(pi1->field, pi2->field)) { \
4149 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4150 pi1->field, pi2->field)); \
4154 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4155 NT_PRINTER_INFO_LEVEL *p2)
4157 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4159 /* Trivial conditions */
4161 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4165 if ((!p1 && p2) || (p1 && !p2) ||
4166 (!p1->info_2 && p2->info_2) ||
4167 (p1->info_2 && !p2->info_2)) {
4168 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4173 /* Compare two nt_printer_info_level structures. Don't compare
4174 status or cjobs as they seem to have something to do with the
4180 PI_CHECK_INT(attributes);
4181 PI_CHECK_INT(priority);
4182 PI_CHECK_INT(default_priority);
4183 PI_CHECK_INT(starttime);
4184 PI_CHECK_INT(untiltime);
4185 PI_CHECK_INT(averageppm);
4187 /* Yuck - don't check the printername or servername as the
4188 add_a_printer() code plays games with them. You can't
4189 change the printername or the sharename through this interface
4192 PI_CHECK_STR(sharename);
4193 PI_CHECK_STR(portname);
4194 PI_CHECK_STR(drivername);
4195 PI_CHECK_STR(comment);
4196 PI_CHECK_STR(location);
4198 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4202 PI_CHECK_STR(sepfile);
4203 PI_CHECK_STR(printprocessor);
4204 PI_CHECK_STR(datatype);
4205 PI_CHECK_STR(parameters);
4207 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4211 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4215 PI_CHECK_INT(changeid);
4216 PI_CHECK_INT(c_setprinter);
4217 PI_CHECK_INT(setuptime);
4220 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4224 /********************************************************************
4225 * called by spoolss_api_setprinter
4226 * when updating a printer description
4227 ********************************************************************/
4229 static uint32 update_printer(POLICY_HND *handle, uint32 level,
4230 const SPOOL_PRINTER_INFO_LEVEL *info,
4231 DEVICEMODE *devmode)
4234 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4235 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4238 DEBUG(8,("update_printer\n"));
4240 result = NT_STATUS_NO_PROBLEMO;
4243 DEBUG(0,("Send a mail to samba@samba.org\n"));
4244 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4245 result = ERROR_INVALID_LEVEL;
4249 if (!OPEN_HANDLE(Printer)) {
4250 result = ERROR_INVALID_HANDLE;
4254 if (!get_printer_snum(handle, &snum)) {
4255 result = ERROR_INVALID_HANDLE;
4259 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4260 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4261 result = ERROR_INVALID_HANDLE;
4265 DEBUGADD(8,("Converting info_2 struct\n"));
4268 * convert_printer_info converts the incoming
4269 * info from the client and overwrites the info
4270 * just read from the tdb in the pointer 'printer'.
4273 convert_printer_info(info, printer, level);
4275 if (info->info_2->devmode_ptr != 0) {
4276 /* we have a valid devmode
4277 convert it and link it*/
4279 DEBUGADD(8,("Converting the devicemode struct\n"));
4280 if (!convert_devicemode(printer->info_2->printername, devmode,
4281 &printer->info_2->devmode)) {
4282 result = ERROR_NOT_ENOUGH_MEMORY;
4287 /* Do sanity check on the requested changes for Samba */
4289 if (!check_printer_ok(printer->info_2, snum)) {
4290 result = ERROR_INVALID_PARAMETER;
4294 /* NT likes to call this function even though nothing has actually
4295 changed. Check this so the user doesn't end up with an
4296 annoying permission denied dialog box. */
4298 if (nt_printer_info_level_equal(printer, old_printer)) {
4299 DEBUG(3, ("printer info has not changed\n"));
4300 result = NT_STATUS_NO_PROBLEMO;
4304 /* Check calling user has permission to update printer description */
4306 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4307 DEBUG(3, ("printer property change denied by security "
4309 result = ERROR_ACCESS_DENIED;
4313 /* Call addprinter hook */
4315 if (*lp_addprinter_cmd() )
4316 if ( !add_printer_hook(printer) ) {
4317 result = ERROR_ACCESS_DENIED;
4321 /* Update printer info */
4323 if (add_a_printer(*printer, 2)!=0) {
4324 /* I don't really know what to return here !!! */
4325 result = ERROR_ACCESS_DENIED;
4330 free_a_printer(&printer, 2);
4331 free_a_printer(&old_printer, 2);
4333 srv_spoolss_sendnotify(handle);
4338 /****************************************************************************
4339 ****************************************************************************/
4340 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
4341 const SPOOL_PRINTER_INFO_LEVEL *info,
4342 DEVMODE_CTR devmode_ctr,
4343 SEC_DESC_BUF *secdesc_ctr,
4344 uint32 command, pipes_struct *p)
4346 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4348 if (!OPEN_HANDLE(Printer)) {
4349 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4350 return ERROR_INVALID_HANDLE;
4353 /* check the level */
4356 return control_printer(handle, command, p);
4358 return update_printer(handle, level, info, devmode_ctr.devmode);
4360 return update_printer_sec(handle, level, info, p,
4363 return ERROR_INVALID_LEVEL;
4367 /****************************************************************************
4368 ****************************************************************************/
4369 uint32 _spoolss_fcpn(POLICY_HND *handle)
4371 Printer_entry *Printer= find_printer_index_by_hnd(handle);
4373 if (!OPEN_HANDLE(Printer)) {
4374 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4375 return ERROR_INVALID_HANDLE;
4378 if (Printer->notify.client_connected==True)
4379 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4380 return ERROR_INVALID_HANDLE;
4382 Printer->notify.flags=0;
4383 Printer->notify.options=0;
4384 Printer->notify.localmachine[0]='\0';
4385 Printer->notify.printerlocal=0;
4386 if (Printer->notify.option)
4387 safe_free(Printer->notify.option->ctr.type);
4388 safe_free(Printer->notify.option);
4389 Printer->notify.option=NULL;
4390 Printer->notify.client_connected=False;
4392 return NT_STATUS_NO_PROBLEMO;
4395 /****************************************************************************
4396 ****************************************************************************/
4397 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
4398 NEW_BUFFER *buffer, uint32 offered,
4402 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4403 returns for AddJob. AddJob
4404 must fail on non-local
4408 /****************************************************************************
4409 ****************************************************************************/
4410 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4411 int position, int snum)
4417 t=gmtime(&queue->time);
4418 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4420 job_info->jobid=queue->job;
4421 init_unistr(&job_info->printername, lp_servicename(snum));
4422 init_unistr(&job_info->machinename, temp_name);
4423 init_unistr(&job_info->username, queue->user);
4424 init_unistr(&job_info->document, queue->file);
4425 init_unistr(&job_info->datatype, "RAW");
4426 init_unistr(&job_info->text_status, "");
4427 job_info->status=nt_printj_status(queue->status);
4428 job_info->priority=queue->priority;
4429 job_info->position=position;
4430 job_info->totalpages=0;
4431 job_info->pagesprinted=0;
4433 make_systemtime(&job_info->submitted, t);
4436 /****************************************************************************
4437 ****************************************************************************/
4438 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4439 int position, int snum,
4440 NT_PRINTER_INFO_LEVEL *ntprinter)
4446 t=gmtime(&queue->time);
4447 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
4449 job_info->jobid=queue->job;
4451 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4453 init_unistr(&job_info->printername, chaine);
4455 init_unistr(&job_info->machinename, temp_name);
4456 init_unistr(&job_info->username, queue->user);
4457 init_unistr(&job_info->document, queue->file);
4458 init_unistr(&job_info->notifyname, queue->user);
4459 init_unistr(&job_info->datatype, "RAW");
4460 init_unistr(&job_info->printprocessor, "winprint");
4461 init_unistr(&job_info->parameters, "");
4462 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4463 init_unistr(&job_info->text_status, "");
4465 /* and here the security descriptor */
4467 job_info->status=nt_printj_status(queue->status);
4468 job_info->priority=queue->priority;
4469 job_info->position=position;
4470 job_info->starttime=0;
4471 job_info->untiltime=0;
4472 job_info->totalpages=0;
4473 job_info->size=queue->size;
4474 make_systemtime(&(job_info->submitted), t);
4475 job_info->timeelapsed=0;
4476 job_info->pagesprinted=0;
4478 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4485 /****************************************************************************
4486 Enumjobs at level 1.
4487 ****************************************************************************/
4488 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4489 NEW_BUFFER *buffer, uint32 offered,
4490 uint32 *needed, uint32 *returned)
4495 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4499 return ERROR_NOT_ENOUGH_MEMORY;
4502 for (i=0; i<*returned; i++)
4503 fill_job_info_1(&info[i], &queue[i], i, snum);
4507 /* check the required size. */
4508 for (i=0; i<*returned; i++)
4509 (*needed) += spoolss_size_job_info_1(&info[i]);
4511 if (!alloc_buffer_size(buffer, *needed)) {
4513 return ERROR_INSUFFICIENT_BUFFER;
4516 /* fill the buffer with the structures */
4517 for (i=0; i<*returned; i++)
4518 new_smb_io_job_info_1("", buffer, &info[i], 0);
4523 if (*needed > offered) {
4525 return ERROR_INSUFFICIENT_BUFFER;
4528 return NT_STATUS_NO_PROBLEMO;
4531 /****************************************************************************
4532 Enumjobs at level 2.
4533 ****************************************************************************/
4534 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4535 NEW_BUFFER *buffer, uint32 offered,
4536 uint32 *needed, uint32 *returned)
4538 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4542 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4545 return ERROR_NOT_ENOUGH_MEMORY;
4548 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4550 return ERROR_NOT_ENOUGH_MEMORY;
4553 for (i=0; i<*returned; i++)
4554 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4556 free_a_printer(&ntprinter, 2);
4559 /* check the required size. */
4560 for (i=0; i<*returned; i++)
4561 (*needed) += spoolss_size_job_info_2(&info[i]);
4563 if (!alloc_buffer_size(buffer, *needed)) {
4565 return ERROR_INSUFFICIENT_BUFFER;
4568 /* fill the buffer with the structures */
4569 for (i=0; i<*returned; i++)
4570 new_smb_io_job_info_2("", buffer, &info[i], 0);
4573 for (i = 0; i < *returned; i++)
4574 free_job_info_2(&info[i]);
4578 if (*needed > offered) {
4580 return ERROR_INSUFFICIENT_BUFFER;
4583 return NT_STATUS_NO_PROBLEMO;
4586 /****************************************************************************
4588 ****************************************************************************/
4589 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4590 NEW_BUFFER *buffer, uint32 offered,
4591 uint32 *needed, uint32 *returned)
4594 print_queue_struct *queue=NULL;
4595 print_status_struct prt_status;
4597 DEBUG(4,("_spoolss_enumjobs\n"));
4599 ZERO_STRUCT(prt_status);
4604 if (!get_printer_snum(handle, &snum))
4605 return ERROR_INVALID_HANDLE;
4607 *returned = print_queue_status(snum, &queue, &prt_status);
4608 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4610 if (*returned == 0) {
4612 return NT_STATUS_NO_PROBLEMO;
4617 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4619 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4623 return ERROR_INVALID_LEVEL;
4628 /****************************************************************************
4629 ****************************************************************************/
4630 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4635 /****************************************************************************
4636 ****************************************************************************/
4637 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4638 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4640 struct current_user user;
4641 print_status_struct prt_status;
4642 int snum, errcode = ERROR_INVALID_FUNCTION;
4644 memset(&prt_status, 0, sizeof(prt_status));
4646 if (!get_printer_snum(handle, &snum)) {
4647 return ERROR_INVALID_HANDLE;
4650 if (!print_job_exists(jobid)) {
4651 return ERROR_INVALID_PRINTER_NAME;
4654 get_current_user(&user, p);
4657 case JOB_CONTROL_CANCEL:
4658 case JOB_CONTROL_DELETE:
4659 if (print_job_delete(&user, jobid, &errcode)) {
4663 case JOB_CONTROL_PAUSE:
4664 if (print_job_pause(&user, jobid, &errcode)) {
4668 case JOB_CONTROL_RESTART:
4669 case JOB_CONTROL_RESUME:
4670 if (print_job_resume(&user, jobid, &errcode)) {
4675 return ERROR_INVALID_LEVEL;
4681 /****************************************************************************
4682 Enumerates all printer drivers at level 1.
4683 ****************************************************************************/
4684 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4689 fstring *list = NULL;
4691 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4692 DRIVER_INFO_1 *driver_info_1=NULL;
4696 #define MAX_VERSION 4
4698 for (version=0; version<MAX_VERSION; version++) {
4700 ndrivers=get_ntdrivers(&list, architecture, version);
4701 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4704 return ERROR_NOT_ENOUGH_MEMORY;
4707 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4709 return ERROR_NOT_ENOUGH_MEMORY;
4713 for (i=0; i<ndrivers; i++) {
4715 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4716 ZERO_STRUCT(driver);
4717 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4721 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4722 free_a_printer_driver(driver, 3);
4725 *returned+=ndrivers;
4729 /* check the required size. */
4730 for (i=0; i<*returned; i++) {
4731 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4732 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4735 if (!alloc_buffer_size(buffer, *needed)) {
4736 safe_free(driver_info_1);
4737 return ERROR_INSUFFICIENT_BUFFER;
4740 /* fill the buffer with the form structures */
4741 for (i=0; i<*returned; i++) {
4742 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4743 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4746 safe_free(driver_info_1);
4748 if (*needed > offered) {
4750 return ERROR_INSUFFICIENT_BUFFER;
4753 return NT_STATUS_NO_PROBLEMO;
4756 /****************************************************************************
4757 Enumerates all printer drivers at level 2.
4758 ****************************************************************************/
4759 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4764 fstring *list = NULL;
4766 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4767 DRIVER_INFO_2 *driver_info_2=NULL;
4771 #define MAX_VERSION 4
4773 for (version=0; version<MAX_VERSION; version++) {
4775 ndrivers=get_ntdrivers(&list, architecture, version);
4776 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4779 return ERROR_NOT_ENOUGH_MEMORY;
4782 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4784 return ERROR_NOT_ENOUGH_MEMORY;
4788 for (i=0; i<ndrivers; i++) {
4791 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4792 ZERO_STRUCT(driver);
4793 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4797 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4798 free_a_printer_driver(driver, 3);
4801 *returned+=ndrivers;
4805 /* check the required size. */
4806 for (i=0; i<*returned; i++) {
4807 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4808 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4811 if (!alloc_buffer_size(buffer, *needed)) {
4812 safe_free(driver_info_2);
4813 return ERROR_INSUFFICIENT_BUFFER;
4816 /* fill the buffer with the form structures */
4817 for (i=0; i<*returned; i++) {
4818 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4819 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4822 safe_free(driver_info_2);
4824 if (*needed > offered) {
4826 return ERROR_INSUFFICIENT_BUFFER;
4829 return NT_STATUS_NO_PROBLEMO;
4832 /****************************************************************************
4833 Enumerates all printer drivers at level 3.
4834 ****************************************************************************/
4835 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4840 fstring *list = NULL;
4842 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4843 DRIVER_INFO_3 *driver_info_3=NULL;
4847 #define MAX_VERSION 4
4849 for (version=0; version<MAX_VERSION; version++) {
4851 ndrivers=get_ntdrivers(&list, architecture, version);
4852 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4855 return ERROR_NOT_ENOUGH_MEMORY;
4858 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4860 return ERROR_NOT_ENOUGH_MEMORY;
4864 for (i=0; i<ndrivers; i++) {
4867 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4868 ZERO_STRUCT(driver);
4869 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4873 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4874 free_a_printer_driver(driver, 3);
4877 *returned+=ndrivers;
4881 /* check the required size. */
4882 for (i=0; i<*returned; i++) {
4883 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4884 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4887 if (!alloc_buffer_size(buffer, *needed)) {
4888 safe_free(driver_info_3);
4889 return ERROR_INSUFFICIENT_BUFFER;
4892 /* fill the buffer with the driver structures */
4893 for (i=0; i<*returned; i++) {
4894 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4895 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
4898 for (i=0; i<*returned; i++)
4899 safe_free(driver_info_3[i].dependentfiles);
4901 safe_free(driver_info_3);
4903 if (*needed > offered) {
4905 return ERROR_INSUFFICIENT_BUFFER;
4908 return NT_STATUS_NO_PROBLEMO;
4911 /****************************************************************************
4912 Enumerates all printer drivers.
4913 ****************************************************************************/
4914 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
4915 NEW_BUFFER *buffer, uint32 offered,
4916 uint32 *needed, uint32 *returned)
4918 fstring *list = NULL;
4920 fstring architecture;
4922 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4923 fstrcpy(servername, global_myname);
4927 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
4931 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
4933 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
4935 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
4939 return ERROR_INVALID_LEVEL;
4943 /****************************************************************************
4944 ****************************************************************************/
4945 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
4947 form->flag=list->flag;
4948 init_unistr(&form->name, list->name);
4949 form->width=list->width;
4950 form->length=list->length;
4951 form->left=list->left;
4952 form->top=list->top;
4953 form->right=list->right;
4954 form->bottom=list->bottom;
4957 /****************************************************************************
4958 ****************************************************************************/
4959 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
4960 NEW_BUFFER *buffer, uint32 offered,
4961 uint32 *needed, uint32 *numofforms)
4963 nt_forms_struct *list=NULL;
4968 DEBUG(4,("_new_spoolss_enumforms\n"));
4969 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
4970 DEBUGADD(5,("Info level [%d]\n", level));
4972 *numofforms = get_ntforms(&list);
4973 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
4975 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
4979 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
4981 return ERROR_NOT_ENOUGH_MEMORY;
4984 /* construct the list of form structures */
4985 for (i=0; i<*numofforms; i++) {
4986 DEBUGADD(6,("Filling form number [%d]\n",i));
4987 fill_form_1(&forms_1[i], &list[i]);
4992 /* check the required size. */
4993 for (i=0; i<*numofforms; i++) {
4994 DEBUGADD(6,("adding form [%d]'s size\n",i));
4995 buffer_size += spoolss_size_form_1(&forms_1[i]);
4998 *needed=buffer_size;
5000 if (!alloc_buffer_size(buffer, buffer_size)){
5002 return ERROR_INSUFFICIENT_BUFFER;
5005 /* fill the buffer with the form structures */
5006 for (i=0; i<*numofforms; i++) {
5007 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5008 new_smb_io_form_1("", buffer, &forms_1[i], 0);
5013 if (*needed > offered) {
5015 return ERROR_INSUFFICIENT_BUFFER;
5018 return NT_STATUS_NO_PROBLEMO;
5022 return ERROR_INVALID_LEVEL;
5027 /****************************************************************************
5028 ****************************************************************************/
5029 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5031 nt_forms_struct *list=NULL;
5037 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5039 DEBUG(4,("_spoolss_getform\n"));
5040 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5041 DEBUGADD(5,("Info level [%d]\n", level));
5043 numofforms = get_ntforms(&list);
5044 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5046 if (numofforms == 0)
5047 return ERROR_NO_MORE_ITEMS;
5052 /* Check if the requested name is in the list of form structures */
5053 for (i=0; i<numofforms; i++) {
5055 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5057 if (strequal(form_name, list[i].name)) {
5058 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5059 fill_form_1(&form_1, &list[i]);
5066 /* check the required size. */
5068 *needed=spoolss_size_form_1(&form_1);
5070 if (!alloc_buffer_size(buffer, buffer_size)){
5071 return ERROR_INSUFFICIENT_BUFFER;
5074 if (*needed > offered) {
5075 return ERROR_INSUFFICIENT_BUFFER;
5078 /* fill the buffer with the form structures */
5079 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5080 new_smb_io_form_1("", buffer, &form_1, 0);
5082 return NT_STATUS_NO_PROBLEMO;
5086 return ERROR_INVALID_LEVEL;
5090 /****************************************************************************
5091 ****************************************************************************/
5092 static void fill_port_1(PORT_INFO_1 *port, char *name)
5094 init_unistr(&port->port_name, name);
5097 /****************************************************************************
5098 ****************************************************************************/
5099 static void fill_port_2(PORT_INFO_2 *port, char *name)
5101 init_unistr(&port->port_name, name);
5102 init_unistr(&port->monitor_name, "Local Monitor");
5103 init_unistr(&port->description, "Local Port");
5104 #define PORT_TYPE_WRITE 1
5105 port->port_type=PORT_TYPE_WRITE;
5109 /****************************************************************************
5111 ****************************************************************************/
5112 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5114 PORT_INFO_1 *ports=NULL;
5117 if (*lp_enumports_cmd()) {
5118 pid_t local_pid = sys_getpid();
5119 char *cmd = lp_enumports_cmd();
5127 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5128 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5132 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5133 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
5136 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5137 ret = smbrun(command, tmp_file, False);
5138 DEBUG(10,("Returned [%d]\n", ret));
5141 /* Is this the best error to return here? */
5142 return ERROR_ACCESS_DENIED;
5146 qlines = file_lines_load(tmp_file, &numlines,True);
5147 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5148 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5152 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5153 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5154 file_lines_free(qlines);
5155 return ERROR_NOT_ENOUGH_MEMORY;
5158 for (i=0; i<numlines; i++) {
5159 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5160 fill_port_1(&ports[i], qlines[i]);
5163 file_lines_free(qlines);
5166 *returned = numlines;
5169 *returned = 1; /* Sole Samba port returned. */
5171 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5172 return ERROR_NOT_ENOUGH_MEMORY;
5174 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5176 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5179 /* check the required size. */
5180 for (i=0; i<*returned; i++) {
5181 DEBUGADD(6,("adding port [%d]'s size\n", i));
5182 *needed += spoolss_size_port_info_1(&ports[i]);
5185 if (!alloc_buffer_size(buffer, *needed)) {
5187 return ERROR_INSUFFICIENT_BUFFER;
5190 /* fill the buffer with the ports structures */
5191 for (i=0; i<*returned; i++) {
5192 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5193 new_smb_io_port_1("", buffer, &ports[i], 0);
5198 if (*needed > offered) {
5200 return ERROR_INSUFFICIENT_BUFFER;
5203 return NT_STATUS_NO_PROBLEMO;
5206 /****************************************************************************
5208 ****************************************************************************/
5210 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5212 PORT_INFO_2 *ports=NULL;
5215 if (*lp_enumports_cmd()) {
5216 pid_t local_pid = sys_getpid();
5217 char *cmd = lp_enumports_cmd();
5225 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5226 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5230 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
5231 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
5234 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5235 ret = smbrun(command, tmp_file, False);
5236 DEBUGADD(10,("returned [%d]\n", ret));
5239 /* Is this the best error to return here? */
5240 return ERROR_ACCESS_DENIED;
5244 qlines = file_lines_load(tmp_file, &numlines,True);
5245 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5246 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5250 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5251 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5252 file_lines_free(qlines);
5253 return ERROR_NOT_ENOUGH_MEMORY;
5256 for (i=0; i<numlines; i++) {
5257 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5258 fill_port_2(&(ports[i]), qlines[i]);
5261 file_lines_free(qlines);
5264 *returned = numlines;
5270 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5271 return ERROR_NOT_ENOUGH_MEMORY;
5273 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5275 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5278 /* check the required size. */
5279 for (i=0; i<*returned; i++) {
5280 DEBUGADD(6,("adding port [%d]'s size\n", i));
5281 *needed += spoolss_size_port_info_2(&ports[i]);
5284 if (!alloc_buffer_size(buffer, *needed)) {
5286 return ERROR_INSUFFICIENT_BUFFER;
5289 /* fill the buffer with the ports structures */
5290 for (i=0; i<*returned; i++) {
5291 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5292 new_smb_io_port_2("", buffer, &ports[i], 0);
5297 if (*needed > offered) {
5299 return ERROR_INSUFFICIENT_BUFFER;
5302 return NT_STATUS_NO_PROBLEMO;
5305 /****************************************************************************
5307 ****************************************************************************/
5308 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
5309 NEW_BUFFER *buffer, uint32 offered,
5310 uint32 *needed, uint32 *returned)
5312 DEBUG(4,("_spoolss_enumports\n"));
5319 return enumports_level_1(buffer, offered, needed, returned);
5321 return enumports_level_2(buffer, offered, needed, returned);
5323 return ERROR_INVALID_LEVEL;
5327 /****************************************************************************
5328 ****************************************************************************/
5329 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5330 const SPOOL_PRINTER_INFO_LEVEL *info,
5331 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5332 uint32 user_switch, const SPOOL_USER_CTR *user,
5335 NT_PRINTER_INFO_LEVEL *printer = NULL;
5339 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5340 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5341 return ERROR_NOT_ENOUGH_MEMORY;
5344 ZERO_STRUCTP(printer);
5346 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5347 convert_printer_info(info, printer, 2);
5349 if (*lp_addprinter_cmd() )
5350 if ( !add_printer_hook(printer) ) {
5351 free_a_printer(&printer,2);
5352 return ERROR_ACCESS_DENIED;
5355 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5356 printer->info_2->sharename);
5358 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5359 free_a_printer(&printer,2);
5360 return ERROR_ACCESS_DENIED;
5363 /* you must be a printer admin to add a new printer */
5364 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5365 free_a_printer(&printer,2);
5366 return ERROR_ACCESS_DENIED;
5370 * Do sanity check on the requested changes for Samba.
5373 if (!check_printer_ok(printer->info_2, snum)) {
5374 free_a_printer(&printer,2);
5375 return ERROR_INVALID_PARAMETER;
5378 /* write the ASCII on disk */
5379 if (add_a_printer(*printer, 2) != 0) {
5380 free_a_printer(&printer,2);
5381 return ERROR_ACCESS_DENIED;
5384 if (!open_printer_hnd(handle, name)) {
5385 /* Handle open failed - remove addition. */
5386 del_a_printer(printer->info_2->sharename);
5387 free_a_printer(&printer,2);
5388 return ERROR_ACCESS_DENIED;
5391 free_a_printer(&printer,2);
5393 srv_spoolss_sendnotify(handle);
5395 return NT_STATUS_NO_PROBLEMO;
5398 /****************************************************************************
5399 ****************************************************************************/
5400 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5401 const SPOOL_PRINTER_INFO_LEVEL *info,
5402 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5403 uint32 user_switch, const SPOOL_USER_CTR *user,
5408 /* we don't handle yet */
5409 /* but I know what to do ... */
5410 return ERROR_INVALID_LEVEL;
5412 return spoolss_addprinterex_level_2(uni_srv_name, info,
5413 unk0, unk1, unk2, unk3,
5414 user_switch, user, handle);
5416 return ERROR_INVALID_LEVEL;
5420 /****************************************************************************
5421 ****************************************************************************/
5422 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5423 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5425 uint32 err = NT_STATUS_NO_PROBLEMO;
5426 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5427 struct current_user user;
5429 ZERO_STRUCT(driver);
5431 get_current_user(&user, p);
5433 convert_printer_driver_info(info, &driver, level);
5435 DEBUG(5,("Cleaning driver's information\n"));
5436 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5439 DEBUG(5,("Moving driver to final destination\n"));
5440 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5442 err = ERROR_ACCESS_DENIED;
5446 if (add_a_printer_driver(driver, level)!=0) {
5447 err = ERROR_ACCESS_DENIED;
5452 free_a_printer_driver(driver, level);
5456 /****************************************************************************
5457 ****************************************************************************/
5458 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5460 init_unistr(&info->name, name);
5463 /****************************************************************************
5464 ****************************************************************************/
5465 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5469 pstring short_archi;
5470 DRIVER_DIRECTORY_1 *info=NULL;
5472 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5474 if (get_short_archi(short_archi, long_archi)==FALSE)
5475 return ERROR_INVALID_ENVIRONMENT;
5477 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5478 return ERROR_NOT_ENOUGH_MEMORY;
5480 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5482 DEBUG(4,("printer driver directory: [%s]\n", path));
5484 fill_driverdir_1(info, path);
5486 *needed += spoolss_size_driverdir_info_1(info);
5488 if (!alloc_buffer_size(buffer, *needed)) {
5490 return ERROR_INSUFFICIENT_BUFFER;
5493 new_smb_io_driverdir_1("", buffer, info, 0);
5497 if (*needed > offered)
5498 return ERROR_INSUFFICIENT_BUFFER;
5500 return NT_STATUS_NO_PROBLEMO;
5503 /****************************************************************************
5504 ****************************************************************************/
5505 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5506 NEW_BUFFER *buffer, uint32 offered,
5509 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5515 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5517 return ERROR_INVALID_LEVEL;
5521 /****************************************************************************
5522 ****************************************************************************/
5523 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5524 uint32 in_value_len, uint32 in_data_len,
5525 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5527 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5529 NT_PRINTER_INFO_LEVEL *printer = NULL;
5534 uint32 biggest_valuesize;
5535 uint32 biggest_datasize;
5537 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5542 ZERO_STRUCT(printer);
5544 *out_max_value_len=0;
5550 *out_max_data_len=0;
5554 DEBUG(5,("spoolss_enumprinterdata\n"));
5556 if (!OPEN_HANDLE(Printer)) {
5557 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5558 return ERROR_INVALID_HANDLE;
5561 if (!get_printer_snum(handle, &snum))
5562 return ERROR_INVALID_HANDLE;
5564 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5565 return ERROR_INVALID_HANDLE;
5568 * The NT machine wants to know the biggest size of value and data
5570 * cf: MSDN EnumPrinterData remark section
5572 if ( (in_value_len==0) && (in_data_len==0) ) {
5573 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5577 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5578 * if this parameter size doesn't exist.
5579 * Ok - my opinion here is that the client is not asking for the greatest
5580 * possible size of all the parameters, but is asking specifically for the size needed
5581 * for this specific parameter. In that case we can remove the loop below and
5582 * simplify this lookup code considerably. JF - comments welcome. JRA.
5585 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5587 free_a_printer(&printer, 2);
5588 return ERROR_NO_MORE_ITEMS;
5596 biggest_valuesize=0;
5599 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5600 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5601 if (data_len > biggest_datasize) biggest_datasize=data_len;
5603 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5611 * I think this is correct, it doesn't break APW and
5612 * allows Gerald's Win32 test programs to work correctly,
5613 * but may need altering.... JRA.
5616 if (param_index == 0) {
5617 /* No parameters found. */
5618 free_a_printer(&printer, 2);
5619 return ERROR_NO_MORE_ITEMS;
5622 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5623 *out_value_len=2*(1+biggest_valuesize);
5624 *out_data_len=biggest_datasize;
5626 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5628 free_a_printer(&printer, 2);
5629 return NT_STATUS_NO_PROBLEMO;
5633 * the value len is wrong in NT sp3
5634 * that's the number of bytes not the number of unicode chars
5637 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5639 free_a_printer(&printer, 2);
5640 return ERROR_NO_MORE_ITEMS;
5643 free_a_printer(&printer, 2);
5647 * - counted in bytes in the request
5648 * - counted in UNICODE chars in the max reply
5649 * - counted in bytes in the real size
5651 * take a pause *before* coding not *during* coding
5654 *out_max_value_len=(in_value_len/sizeof(uint16));
5655 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5657 return ERROR_NOT_ENOUGH_MEMORY;
5660 ZERO_STRUCTP(*out_value);
5661 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5665 /* the data is counted in bytes */
5666 *out_max_data_len=in_data_len;
5667 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5669 return ERROR_NOT_ENOUGH_MEMORY;
5672 memset(*data_out,'\0',in_data_len);
5673 memcpy(*data_out, data, (size_t)data_len);
5674 *out_data_len=data_len;
5678 return NT_STATUS_NO_PROBLEMO;
5681 /****************************************************************************
5682 ****************************************************************************/
5683 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5684 const UNISTR2 *value,
5689 uint32 numeric_data)
5691 NT_PRINTER_INFO_LEVEL *printer = NULL;
5692 NT_PRINTER_PARAM *param = NULL, old_param;
5694 uint32 status = 0x0;
5695 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5697 DEBUG(5,("spoolss_setprinterdata\n"));
5699 if (!OPEN_HANDLE(Printer)) {
5700 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5701 return ERROR_INVALID_HANDLE;
5704 if (!get_printer_snum(handle, &snum))
5705 return ERROR_INVALID_HANDLE;
5707 status = get_a_printer(&printer, 2, lp_servicename(snum));
5709 return ERROR_INVALID_NAME;
5711 convert_specific_param(¶m, value , type, data, real_len);
5713 /* Check if we are making any changes or not. Return true if
5714 nothing is actually changing. */
5716 ZERO_STRUCT(old_param);
5718 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5719 &old_param.type, (unsigned int *)&old_param.data_len)) {
5721 if (param->type == old_param.type &&
5722 param->data_len == old_param.data_len &&
5723 memcmp(param->data, old_param.data,
5724 old_param.data_len) == 0) {
5726 DEBUG(3, ("setprinterdata hasn't changed\n"));
5727 status = NT_STATUS_NO_PROBLEMO;
5734 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5735 DEBUG(3, ("security descriptor change denied by existing "
5736 "security descriptor\n"));
5737 status = ERROR_ACCESS_DENIED;
5741 unlink_specific_param_if_exist(printer->info_2, param);
5743 add_a_specific_param(printer->info_2, ¶m);
5744 status = mod_a_printer(*printer, 2);
5747 free_a_printer(&printer, 2);
5749 free_nt_printer_param(¶m);
5750 safe_free(old_param.data);
5755 /****************************************************************************
5756 ****************************************************************************/
5757 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5759 NT_PRINTER_INFO_LEVEL *printer = NULL;
5760 NT_PRINTER_PARAM param;
5762 uint32 status = 0x0;
5763 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5765 DEBUG(5,("spoolss_deleteprinterdata\n"));
5767 if (!OPEN_HANDLE(Printer)) {
5768 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5769 return ERROR_INVALID_HANDLE;
5772 if (!get_printer_snum(handle, &snum))
5773 return ERROR_INVALID_HANDLE;
5775 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5776 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
5777 "change denied by existing security descriptor\n"));
5778 return ERROR_ACCESS_DENIED;
5781 status = get_a_printer(&printer, 2, lp_servicename(snum));
5783 return ERROR_INVALID_NAME;
5785 ZERO_STRUCTP(¶m);
5786 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5788 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5789 status = ERROR_INVALID_PARAMETER;
5791 status = mod_a_printer(*printer, 2);
5793 free_a_printer(&printer, 2);
5797 /****************************************************************************
5798 ****************************************************************************/
5799 uint32 _spoolss_addform( POLICY_HND *handle,
5804 nt_forms_struct *list=NULL;
5805 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5807 DEBUG(5,("spoolss_addform\n"));
5809 if (!OPEN_HANDLE(Printer)) {
5810 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5811 return ERROR_INVALID_HANDLE;
5814 count=get_ntforms(&list);
5815 if(!add_a_form(&list, form, &count))
5816 return ERROR_NOT_ENOUGH_MEMORY;
5817 write_ntforms(&list, count);
5824 /****************************************************************************
5825 ****************************************************************************/
5826 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5830 nt_forms_struct *list=NULL;
5831 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5833 DEBUG(5,("spoolss_deleteform\n"));
5835 if (!OPEN_HANDLE(Printer)) {
5836 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5837 return ERROR_INVALID_HANDLE;
5840 count = get_ntforms(&list);
5841 if(!delete_a_form(&list, form_name, &count, &ret))
5842 return ERROR_INVALID_PARAMETER;
5849 /****************************************************************************
5850 ****************************************************************************/
5851 uint32 _spoolss_setform( POLICY_HND *handle,
5852 const UNISTR2 *uni_name,
5857 nt_forms_struct *list=NULL;
5858 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5860 DEBUG(5,("spoolss_setform\n"));
5862 if (!OPEN_HANDLE(Printer)) {
5863 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5864 return ERROR_INVALID_HANDLE;
5866 count=get_ntforms(&list);
5867 update_a_form(&list, form, count);
5868 write_ntforms(&list, count);
5875 /****************************************************************************
5876 enumprintprocessors level 1.
5877 ****************************************************************************/
5878 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5880 PRINTPROCESSOR_1 *info_1=NULL;
5882 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5883 return ERROR_NOT_ENOUGH_MEMORY;
5887 init_unistr(&info_1->name, "winprint");
5889 *needed += spoolss_size_printprocessor_info_1(info_1);
5891 if (!alloc_buffer_size(buffer, *needed))
5892 return ERROR_INSUFFICIENT_BUFFER;
5894 smb_io_printprocessor_info_1("", buffer, info_1, 0);
5898 if (*needed > offered) {
5900 return ERROR_INSUFFICIENT_BUFFER;
5903 return NT_STATUS_NO_PROBLEMO;
5906 /****************************************************************************
5907 ****************************************************************************/
5908 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
5909 NEW_BUFFER *buffer, uint32 offered,
5910 uint32 *needed, uint32 *returned)
5912 DEBUG(5,("spoolss_enumprintprocessors\n"));
5915 * Enumerate the print processors ...
5917 * Just reply with "winprint", to keep NT happy
5918 * and I can use my nice printer checker.
5926 return enumprintprocessors_level_1(buffer, offered, needed, returned);
5928 return ERROR_INVALID_LEVEL;
5932 /****************************************************************************
5933 enumprintprocdatatypes level 1.
5934 ****************************************************************************/
5935 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5937 PRINTPROCDATATYPE_1 *info_1=NULL;
5939 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
5940 return ERROR_NOT_ENOUGH_MEMORY;
5944 init_unistr(&info_1->name, "RAW");
5946 *needed += spoolss_size_printprocdatatype_info_1(info_1);
5948 if (!alloc_buffer_size(buffer, *needed))
5949 return ERROR_INSUFFICIENT_BUFFER;
5951 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
5955 if (*needed > offered) {
5957 return ERROR_INSUFFICIENT_BUFFER;
5960 return NT_STATUS_NO_PROBLEMO;
5963 /****************************************************************************
5964 ****************************************************************************/
5965 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
5966 NEW_BUFFER *buffer, uint32 offered,
5967 uint32 *needed, uint32 *returned)
5969 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5976 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
5978 return ERROR_INVALID_LEVEL;
5982 /****************************************************************************
5983 enumprintmonitors level 1.
5984 ****************************************************************************/
5985 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5987 PRINTMONITOR_1 *info_1=NULL;
5989 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
5990 return ERROR_NOT_ENOUGH_MEMORY;
5994 init_unistr(&info_1->name, "Local Port");
5996 *needed += spoolss_size_printmonitor_info_1(info_1);
5998 if (!alloc_buffer_size(buffer, *needed))
5999 return ERROR_INSUFFICIENT_BUFFER;
6001 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6005 if (*needed > offered) {
6007 return ERROR_INSUFFICIENT_BUFFER;
6010 return NT_STATUS_NO_PROBLEMO;
6013 /****************************************************************************
6014 enumprintmonitors level 2.
6015 ****************************************************************************/
6016 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6018 PRINTMONITOR_2 *info_2=NULL;
6020 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6021 return ERROR_NOT_ENOUGH_MEMORY;
6025 init_unistr(&info_2->name, "Local Port");
6026 init_unistr(&info_2->environment, "Windows NT X86");
6027 init_unistr(&info_2->dll_name, "localmon.dll");
6029 *needed += spoolss_size_printmonitor_info_2(info_2);
6031 if (!alloc_buffer_size(buffer, *needed))
6032 return ERROR_INSUFFICIENT_BUFFER;
6034 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6038 if (*needed > offered) {
6040 return ERROR_INSUFFICIENT_BUFFER;
6043 return NT_STATUS_NO_PROBLEMO;
6046 /****************************************************************************
6047 ****************************************************************************/
6048 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
6049 NEW_BUFFER *buffer, uint32 offered,
6050 uint32 *needed, uint32 *returned)
6052 DEBUG(5,("spoolss_enumprintmonitors\n"));
6055 * Enumerate the print monitors ...
6057 * Just reply with "Local Port", to keep NT happy
6058 * and I can use my nice printer checker.
6066 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6068 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6070 return ERROR_INVALID_LEVEL;
6074 /****************************************************************************
6075 ****************************************************************************/
6076 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6080 JOB_INFO_1 *info_1=NULL;
6082 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6084 if (info_1 == NULL) {
6086 return ERROR_NOT_ENOUGH_MEMORY;
6089 for (i=0; i<count && found==False; i++) {
6090 if (queue[i].job==(int)jobid)
6097 /* I shoud reply something else ... I can't find the good one */
6098 return NT_STATUS_NO_PROBLEMO;
6101 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6105 *needed += spoolss_size_job_info_1(info_1);
6107 if (!alloc_buffer_size(buffer, *needed)) {
6109 return ERROR_INSUFFICIENT_BUFFER;
6112 new_smb_io_job_info_1("", buffer, info_1, 0);
6116 if (*needed > offered)
6117 return ERROR_INSUFFICIENT_BUFFER;
6119 return NT_STATUS_NO_PROBLEMO;
6123 /****************************************************************************
6124 ****************************************************************************/
6125 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6130 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6132 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6134 ZERO_STRUCTP(info_2);
6136 if (info_2 == NULL) {
6138 return ERROR_NOT_ENOUGH_MEMORY;
6141 for (i=0; i<count && found==False; i++) {
6142 if (queue[i].job==(int)jobid)
6149 /* I shoud reply something else ... I can't find the good one */
6150 return NT_STATUS_NO_PROBLEMO;
6153 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6155 return ERROR_NOT_ENOUGH_MEMORY;
6158 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6160 free_a_printer(&ntprinter, 2);
6163 *needed += spoolss_size_job_info_2(info_2);
6165 if (!alloc_buffer_size(buffer, *needed)) {
6167 return ERROR_INSUFFICIENT_BUFFER;
6170 new_smb_io_job_info_2("", buffer, info_2, 0);
6172 free_job_info_2(info_2);
6175 if (*needed > offered)
6176 return ERROR_INSUFFICIENT_BUFFER;
6178 return NT_STATUS_NO_PROBLEMO;
6181 /****************************************************************************
6182 ****************************************************************************/
6183 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
6184 NEW_BUFFER *buffer, uint32 offered,
6189 print_queue_struct *queue=NULL;
6190 print_status_struct prt_status;
6192 DEBUG(5,("spoolss_getjob\n"));
6194 memset(&prt_status, 0, sizeof(prt_status));
6198 if (!get_printer_snum(handle, &snum))
6199 return ERROR_INVALID_HANDLE;
6201 count = print_queue_status(snum, &queue, &prt_status);
6203 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6204 count, prt_status.status, prt_status.message));
6208 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6210 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6213 return ERROR_INVALID_LEVEL;