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)
96 return JOB_STATUS_PAUSED;
98 return JOB_STATUS_SPOOLING;
100 return JOB_STATUS_PRINTING;
102 return JOB_STATUS_ERROR;
104 return JOB_STATUS_DELETING;
106 return JOB_STATUS_OFFLINE;
108 return JOB_STATUS_PAPEROUT;
110 return JOB_STATUS_PRINTED;
112 return JOB_STATUS_DELETED;
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
121 static int nt_printq_status(int v)
125 return PRINTER_STATUS_PAUSED;
134 /****************************************************************************
135 initialise printer handle states...
136 ****************************************************************************/
137 void init_printer_hnd(void)
139 ubi_dlInitList(&Printer_list);
140 ubi_dlInitList(&counter_list);
143 /****************************************************************************
144 Return a user struct for a pipe user.
145 ****************************************************************************/
147 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
149 if (p->ntlmssp_auth_validated) {
150 memcpy(user, &p->pipe_user, sizeof(struct current_user));
152 extern struct current_user current_user;
153 memcpy(user, ¤t_user, sizeof(struct current_user));
159 /****************************************************************************
160 create a unique printer handle
161 ****************************************************************************/
162 static void create_printer_hnd(POLICY_HND *hnd)
164 static uint32 prt_hnd_low = 0;
165 static uint32 prt_hnd_high = 0;
167 if (hnd == NULL) return;
169 /* i severely doubt that prt_hnd_high will ever be non-zero... */
171 if (prt_hnd_low == 0) prt_hnd_high++;
173 SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */
174 SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */
175 SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */
176 SIVAL(hnd->data, 12, time(NULL)); /* something random */
177 SIVAL(hnd->data, 16, sys_getpid()); /* something more random */
180 /****************************************************************************
181 find printer index by handle
182 ****************************************************************************/
183 static Printer_entry *find_printer_index_by_hnd(const POLICY_HND *hnd)
185 Printer_entry *find_printer;
187 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
189 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
191 if (memcmp(&(find_printer->printer_hnd), hnd, sizeof(*hnd)) == 0) {
192 DEBUG(4,("Found printer handle \n"));
193 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
198 DEBUG(3,("Whoops, Printer handle not found: "));
199 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
203 /****************************************************************************
205 ****************************************************************************/
206 static void clear_handle(POLICY_HND *hnd)
211 /***************************************************************************
212 Disconnect from the client
213 ****************************************************************************/
214 static BOOL srv_spoolss_replycloseprinter(POLICY_HND *handle)
218 /* weird if the test succeds !!! */
219 if (smb_connections==0) {
220 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
224 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
227 /* if it's the last connection, deconnect the IPC$ share */
228 if (smb_connections==1) {
229 if(!spoolss_disconnect_from_client(&cli))
232 message_deregister(MSG_PRINTER_NOTIFY);
240 /****************************************************************************
241 close printer index by handle
242 ****************************************************************************/
243 static BOOL close_printer_handle(POLICY_HND *hnd)
245 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
247 if (!OPEN_HANDLE(Printer)) {
248 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
252 if (Printer->notify.client_connected==True)
253 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
254 return ERROR_INVALID_HANDLE;
257 Printer->notify.flags=0;
258 Printer->notify.options=0;
259 Printer->notify.localmachine[0]='\0';
260 Printer->notify.printerlocal=0;
261 safe_free(Printer->notify.option);
262 Printer->notify.option=NULL;
263 Printer->notify.client_connected=False;
267 ubi_dlRemThis(&Printer_list, Printer);
274 /****************************************************************************
275 delete a printer given a handle
276 ****************************************************************************/
277 static uint32 delete_printer_handle(POLICY_HND *hnd)
279 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
281 if (!OPEN_HANDLE(Printer)) {
282 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
283 return ERROR_INVALID_HANDLE;
286 if (del_a_printer(Printer->dev.handlename) != 0) {
287 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
288 return ERROR_INVALID_HANDLE;
291 /* Check calling user has permission to delete printer. Note that
292 since we set the snum parameter to -1 only administrators can
293 delete the printer. This stops people with the Full Control
294 permission from deleting the printer. */
296 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
297 DEBUG(3, ("printer delete denied by security descriptor\n"));
298 return ERROR_ACCESS_DENIED;
301 if (*lp_deleteprinter_cmd()) {
303 pid_t local_pid = sys_getpid();
304 char *cmd = lp_deleteprinter_cmd();
311 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
312 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
316 /* Printer->dev.handlename equals portname equals sharename */
317 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
318 Printer->dev.handlename);
319 dos_to_unix(command, True); /* Convert printername to unix-codepage */
320 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
323 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
324 ret = smbrun(command, tmp_file, False);
327 return ERROR_INVALID_HANDLE; /* What to return here? */
329 DEBUGADD(10,("returned [%d]\n", ret));
330 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
333 /* Send SIGHUP to process group... is there a better way? */
336 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
338 return ERROR_SUCCESS;
340 return ERROR_ACCESS_DENIED;
343 return ERROR_SUCCESS;
346 /****************************************************************************
347 return the snum of a printer corresponding to an handle
348 ****************************************************************************/
349 static BOOL get_printer_snum(POLICY_HND *hnd, int *number)
351 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
353 if (!OPEN_HANDLE(Printer)) {
354 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
358 switch (Printer->printer_type) {
359 case PRINTER_HANDLE_IS_PRINTER:
360 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
361 *number = print_queue_snum(Printer->dev.handlename);
362 return (*number != -1);
363 case PRINTER_HANDLE_IS_PRINTSERVER:
370 /****************************************************************************
371 set printer handle type.
372 ****************************************************************************/
373 static BOOL set_printer_hnd_accesstype(POLICY_HND *hnd, uint32 access_required)
375 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
377 if (!OPEN_HANDLE(Printer)) {
378 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
382 DEBUG(4,("Setting printer access=%x\n", access_required));
383 Printer->access = access_required;
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
392 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
394 DEBUG(3,("Setting printer type=%s\n", handlename));
396 if ( strlen(handlename) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
401 /* it's a print server */
402 if (!strchr(handlename+2, '\\')) {
403 DEBUGADD(4,("Printer is a print server\n"));
404 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
408 DEBUGADD(4,("Printer is a printer\n"));
409 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
415 /****************************************************************************
416 Set printer handle name.
417 ****************************************************************************/
419 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
421 NT_PRINTER_INFO_LEVEL *printer = NULL;
423 int n_services=lp_numservices();
427 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
429 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
430 ZERO_STRUCT(Printer->dev.printerservername);
431 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
435 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
438 aprinter=strchr(handlename+2, '\\');
441 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
444 * store the Samba share name in it
445 * in back we have the long printer name
446 * need to iterate all the snum and do a
447 * get_a_printer each time to find the printer
448 * faster to do it here than later.
451 for (snum=0;snum<n_services && found==False;snum++) {
454 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
457 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
459 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
462 printername=strchr(printer->info_2->printername+2, '\\');
465 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
466 printer->info_2->printername, aprinter ));
468 if ( strlen(printername) != strlen(aprinter) ) {
469 free_a_printer(&printer, 2);
473 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
474 free_a_printer(&printer, 2);
482 * if we haven't found a printer with the given handlename
483 * then it can be a share name as you can open both \\server\printer and
488 * we still check if the printer description file exists as NT won't be happy
489 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
493 DEBUGADD(5,("Printer not found, checking for share now\n"));
495 for (snum=0;snum<n_services && found==False;snum++) {
497 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
500 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
502 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
505 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
506 printer->info_2->printername, aprinter ));
508 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
509 free_a_printer(&printer, 2);
513 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
514 free_a_printer(&printer, 2);
523 DEBUGADD(4,("Printer not found\n"));
528 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
529 printer->info_2->printername, lp_servicename(snum),snum));
531 ZERO_STRUCT(Printer->dev.handlename);
532 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
534 free_a_printer(&printer, 2);
539 /****************************************************************************
540 find first available printer slot. creates a printer handle for you.
541 ****************************************************************************/
543 static BOOL open_printer_hnd(POLICY_HND *hnd, char *name)
545 Printer_entry *new_printer;
547 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
549 create_printer_hnd(hnd);
551 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
554 ZERO_STRUCTP(new_printer);
556 new_printer->open = True;
557 new_printer->notify.option=NULL;
559 memcpy(&new_printer->printer_hnd, hnd, sizeof(*hnd));
561 ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
563 if (!set_printer_hnd_printertype(new_printer, name)) {
564 close_printer_handle(hnd);
568 if (!set_printer_hnd_name(new_printer, name)) {
569 close_printer_handle(hnd);
573 DEBUG(5, ("%d printer handles active\n",
574 (int)ubi_dlCount(&Printer_list)));
579 /********************************************************************
580 Return True is the handle is a print server.
581 ********************************************************************/
582 static BOOL handle_is_printserver(const POLICY_HND *handle)
584 Printer_entry *Printer=find_printer_index_by_hnd(handle);
586 if (!OPEN_HANDLE(Printer))
589 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
595 /****************************************************************************
596 allocate more memory for a BUFFER.
597 ****************************************************************************/
598 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
606 /* damn, I'm doing the reverse operation of prs_grow() :) */
607 if (buffer_size < prs_data_size(ps))
610 extra_space = buffer_size - prs_data_size(ps);
613 * save the offset and move to the end of the buffer
614 * prs_grow() checks the extra_space against the offset
616 old_offset=prs_offset(ps);
617 prs_set_offset(ps, prs_data_size(ps));
619 if (!prs_grow(ps, extra_space))
622 prs_set_offset(ps, old_offset);
624 buffer->string_at_end=prs_data_size(ps);
629 /***************************************************************************
630 receive the notify message
631 ****************************************************************************/
632 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
636 Printer_entry *find_printer;
639 fstrcpy(printer,buf);
642 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
646 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
648 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
650 /* Iterate the printer list. */
651 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
654 * if the entry is the given printer or if it's a printerserver
655 * we send the message
658 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
659 if (strcmp(find_printer->dev.handlename, printer))
662 if (find_printer->notify.client_connected==True)
663 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
668 /***************************************************************************
670 ****************************************************************************/
671 static BOOL srv_spoolss_sendnotify(POLICY_HND *handle)
675 Printer_entry *Printer=find_printer_index_by_hnd(handle);
677 if (!OPEN_HANDLE(Printer)) {
678 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
682 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
683 fstrcpy(printer, Printer->dev.handlename);
685 fstrcpy(printer, "");
687 /*srv_spoolss_receive_message(printer);*/
688 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
690 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
695 /********************************************************************
696 * spoolss_open_printer
698 * called from the spoolss dispatcher
699 ********************************************************************/
700 uint32 _spoolss_open_printer_ex( const UNISTR2 *printername, pipes_struct *p,
701 PRINTER_DEFAULT *printer_default,
702 uint32 user_switch, SPOOL_USER_CTR user_ctr,
706 uint32 result = NT_STATUS_NO_PROBLEMO;
710 struct current_user user;
712 if (printername == NULL)
713 return ERROR_INVALID_PRINTER_NAME;
715 /* some sanity check because you can open a printer or a print server */
716 /* aka: \\server\printer or \\server */
717 unistr2_to_ascii(name, printername, sizeof(name)-1);
719 DEBUGADD(3,("checking name: %s\n",name));
721 if (!open_printer_hnd(handle, name))
722 return ERROR_INVALID_PRINTER_NAME;
725 if (printer_default->datatype_ptr != NULL)
727 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
728 set_printer_hnd_datatype(handle, datatype);
731 set_printer_hnd_datatype(handle, "");
734 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
735 close_printer_handle(handle);
736 return ERROR_ACCESS_DENIED;
740 First case: the user is opening the print server:
742 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
743 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
745 Then both Win2k and WinNT clients try an OpenPrinterEx with
746 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
747 or if the user is listed in the smb.conf printer admin parameter.
749 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
750 client view printer folder, but does not show the MSAPW.
752 Note: this test needs code to check access rights here too. Jeremy
753 could you look at this?
756 Second case: the user is opening a printer:
757 NT doesn't let us connect to a printer if the connecting user
758 doesn't have print permission.
762 get_current_user(&user, p);
764 if (handle_is_printserver(handle)) {
765 if (printer_default->access_required == 0) {
766 return NT_STATUS_NO_PROBLEMO;
768 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
770 if (!lp_ms_add_printer_wizard()) {
771 close_printer_handle(handle);
772 return ERROR_ACCESS_DENIED;
774 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
775 return NT_STATUS_NO_PROBLEMO;
778 close_printer_handle(handle);
779 return ERROR_ACCESS_DENIED;
785 /* NT doesn't let us connect to a printer if the connecting user
786 doesn't have print permission. */
788 if (!get_printer_snum(handle, &snum))
789 return ERROR_INVALID_HANDLE;
791 /* map an empty access mask to the minimum access mask */
792 if (printer_default->access_required == 0x0)
793 printer_default->access_required = PRINTER_ACCESS_USE;
795 if (!print_access_check(&user, snum, printer_default->access_required)) {
796 DEBUG(3, ("access DENIED for printer open\n"));
797 close_printer_handle(handle);
798 return ERROR_ACCESS_DENIED;
802 * If we have a default device pointer in the
803 * printer_default struct, then we need to get
804 * the printer info from the tdb and if there is
805 * no default devicemode there then we do a *SET*
806 * here ! This is insanity.... JRA.
810 * If the openprinterex rpc call contains a devmode,
811 * it's a per-user one. This per-user devmode is derivated
812 * from the global devmode. Openprinterex() contains a per-user
813 * devmode for when you do EMF printing and spooling.
814 * In the EMF case, the NT workstation is only doing half the job
815 * of rendering the page. The other half is done by running the printer
816 * driver on the server.
817 * The EMF file doesn't contain the page description (paper size, orientation, ...).
818 * The EMF file only contains what is to be printed on the page.
819 * So in order for the server to know how to print, the NT client sends
820 * a devicemode attached to the openprinterex call.
821 * But this devicemode is short lived, it's only valid for the current print job.
823 * If Samba would have supported EMF spooling, this devicemode would
824 * have been attached to the handle, to sent it to the driver to correctly
825 * rasterize the EMF file.
827 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
828 * we just act as a pass-thru between windows and the printer.
830 * In order to know that Samba supports only RAW spooling, NT has to call
831 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
832 * and until NT sends a RAW job, we refuse it.
834 * But to call getprinter() or startdoc(), you first need a valid handle,
835 * and to get an handle you have to call openprintex(). Hence why you have
836 * a devicemode in the openprinterex() call.
839 * Differences between NT4 and NT 2000.
842 * On NT4, you only have a global devicemode. This global devicemode can be changed
843 * by the administrator (or by a user with enough privs). Everytime a user
844 * wants to print, the devicemode is resetted to the default. In Word, everytime
845 * you print, the printer's characteristics are always reset to the global devicemode.
849 * In W2K, there is the notion of per-user devicemode. The first time you use
850 * a printer, a per-user devicemode is build from the global devicemode.
851 * If you change your per-user devicemode, it is saved in the registry, under the
852 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
853 * printer preferences available.
855 * To change the per-user devicemode: it's the "Printing Preferences ..." button
856 * on the General Tab of the printer properties windows.
858 * To change the global devicemode: it's the "Printing Defaults..." button
859 * on the Advanced Tab of the printer properties window.
867 if (printer_default->devmode_cont.devmode != NULL) {
868 result = printer_write_default_dev( snum, printer_default);
870 close_printer_handle(handle);
877 return NT_STATUS_NO_PROBLEMO;
880 /****************************************************************************
881 ****************************************************************************/
882 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
883 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
887 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
896 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
897 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
901 printer->info_3=NULL;
902 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
905 printer->info_6=NULL;
906 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
915 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
916 NT_DEVICEMODE **pp_nt_devmode)
918 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
921 * Ensure nt_devmode is a valid pointer
922 * as we will be overwriting it.
925 if (nt_devmode == NULL) {
926 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
927 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
931 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
932 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
934 nt_devmode->specversion=devmode->specversion;
935 nt_devmode->driverversion=devmode->driverversion;
936 nt_devmode->size=devmode->size;
937 nt_devmode->fields=devmode->fields;
938 nt_devmode->orientation=devmode->orientation;
939 nt_devmode->papersize=devmode->papersize;
940 nt_devmode->paperlength=devmode->paperlength;
941 nt_devmode->paperwidth=devmode->paperwidth;
942 nt_devmode->scale=devmode->scale;
943 nt_devmode->copies=devmode->copies;
944 nt_devmode->defaultsource=devmode->defaultsource;
945 nt_devmode->printquality=devmode->printquality;
946 nt_devmode->color=devmode->color;
947 nt_devmode->duplex=devmode->duplex;
948 nt_devmode->yresolution=devmode->yresolution;
949 nt_devmode->ttoption=devmode->ttoption;
950 nt_devmode->collate=devmode->collate;
952 nt_devmode->logpixels=devmode->logpixels;
953 nt_devmode->bitsperpel=devmode->bitsperpel;
954 nt_devmode->pelswidth=devmode->pelswidth;
955 nt_devmode->pelsheight=devmode->pelsheight;
956 nt_devmode->displayflags=devmode->displayflags;
957 nt_devmode->displayfrequency=devmode->displayfrequency;
958 nt_devmode->icmmethod=devmode->icmmethod;
959 nt_devmode->icmintent=devmode->icmintent;
960 nt_devmode->mediatype=devmode->mediatype;
961 nt_devmode->dithertype=devmode->dithertype;
962 nt_devmode->reserved1=devmode->reserved1;
963 nt_devmode->reserved2=devmode->reserved2;
964 nt_devmode->panningwidth=devmode->panningwidth;
965 nt_devmode->panningheight=devmode->panningheight;
968 * Only change private and driverextra if the incoming devmode
969 * has a new one. JRA.
972 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
973 safe_free(nt_devmode->private);
974 nt_devmode->driverextra=devmode->driverextra;
975 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
977 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
980 *pp_nt_devmode = nt_devmode;
985 /********************************************************************
986 * api_spoolss_closeprinter
987 ********************************************************************/
988 uint32 _spoolss_closeprinter(POLICY_HND *handle)
990 Printer_entry *Printer=find_printer_index_by_hnd(handle);
992 if (Printer && Printer->document_started)
993 _spoolss_enddocprinter(handle); /* print job was not closed */
995 if (!close_printer_handle(handle))
996 return ERROR_INVALID_HANDLE;
998 return NT_STATUS_NO_PROBLEMO;
1001 /********************************************************************
1002 * api_spoolss_deleteprinter
1003 ********************************************************************/
1004 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
1006 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1009 if (Printer && Printer->document_started)
1010 _spoolss_enddocprinter(handle); /* print job was not closed */
1012 result = delete_printer_handle(handle);
1014 if (result == ERROR_SUCCESS) {
1015 srv_spoolss_sendnotify(handle);
1021 /********************************************************************
1022 GetPrinterData on a printer server Handle.
1023 ********************************************************************/
1024 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1028 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1030 if (!strcmp(value, "BeepEnabled")) {
1032 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1034 SIVAL(*data, 0, 0x01);
1039 if (!strcmp(value, "EventLog")) {
1041 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1043 SIVAL(*data, 0, 0x1B);
1048 if (!strcmp(value, "NetPopup")) {
1050 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1052 SIVAL(*data, 0, 0x01);
1057 if (!strcmp(value, "MajorVersion")) {
1059 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
1061 SIVAL(*data, 0, 0x02);
1066 if (!strcmp(value, "DefaultSpoolDirectory")) {
1067 pstring string="You are using a Samba server";
1069 *needed = 2*(strlen(string)+1);
1070 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1072 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1074 /* it's done by hand ready to go on the wire */
1075 for (i=0; i<strlen(string); i++) {
1076 (*data)[2*i]=string[i];
1077 (*data)[2*i+1]='\0';
1082 if (!strcmp(value, "Architecture")) {
1083 pstring string="Windows NT x86";
1085 *needed = 2*(strlen(string)+1);
1086 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1088 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1089 for (i=0; i<strlen(string); i++) {
1090 (*data)[2*i]=string[i];
1091 (*data)[2*i+1]='\0';
1099 /********************************************************************
1100 GetPrinterData on a printer Handle.
1101 ********************************************************************/
1102 static BOOL getprinterdata_printer(POLICY_HND *handle,
1103 fstring value, uint32 *type,
1104 uint8 **data, uint32 *needed, uint32 in_size )
1106 NT_PRINTER_INFO_LEVEL *printer = NULL;
1110 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1112 DEBUG(5,("getprinterdata_printer\n"));
1114 if (!OPEN_HANDLE(Printer)) {
1115 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1119 if(!get_printer_snum(handle, &snum))
1122 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1125 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1126 free_a_printer(&printer, 2);
1130 free_a_printer(&printer, 2);
1132 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1135 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
1139 memset(*data, 0, in_size *sizeof(uint8));
1140 /* copy the min(in_size, len) */
1141 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1148 DEBUG(5,("getprinterdata_printer:copy done\n"));
1155 /********************************************************************
1156 * spoolss_getprinterdata
1157 ********************************************************************/
1158 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
1167 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1170 * Reminder: when it's a string, the length is in BYTES
1171 * even if UNICODE is negociated.
1178 /* in case of problem, return some default values */
1182 DEBUG(4,("_spoolss_getprinterdata\n"));
1184 if (!OPEN_HANDLE(Printer)) {
1185 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1186 return ERROR_NOT_ENOUGH_MEMORY;
1187 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1188 return ERROR_INVALID_HANDLE;
1191 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1193 if (handle_is_printserver(handle))
1194 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
1196 found= getprinterdata_printer(handle, value, type, data, needed, *out_size);
1199 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1200 /* reply this param doesn't exist */
1202 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
1203 return ERROR_NOT_ENOUGH_MEMORY;
1204 memset(*data, '\0', *out_size*sizeof(uint8));
1209 return ERROR_INVALID_PARAMETER;
1212 if (*needed > *out_size)
1213 return ERROR_MORE_DATA;
1215 return NT_STATUS_NO_PROBLEMO;
1219 /***************************************************************************
1220 connect to the client
1221 ****************************************************************************/
1222 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1227 * If it's the first connection, contact the client
1228 * and connect to the IPC$ share anonumously
1230 if (smb_connections==0) {
1231 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1233 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1239 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1245 /********************************************************************
1247 * ReplyFindFirstPrinterChangeNotifyEx
1249 * jfmxxxx: before replying OK: status=0
1250 * should do a rpc call to the workstation asking ReplyOpenPrinter
1251 * have to code it, later.
1253 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1254 * called from api_spoolss_rffpcnex
1255 ********************************************************************/
1256 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
1257 const UNISTR2 *localmachine, uint32 printerlocal,
1258 SPOOL_NOTIFY_OPTION *option)
1260 /* store the notify value in the printer struct */
1262 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1264 if (!OPEN_HANDLE(Printer)) {
1265 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1266 return ERROR_INVALID_HANDLE;
1269 Printer->notify.flags=flags;
1270 Printer->notify.options=options;
1271 Printer->notify.printerlocal=printerlocal;
1272 Printer->notify.option=option;
1273 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1275 /* connect to the client machine and send a ReplyOpenPrinter */
1276 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1277 Printer->notify.printerlocal, 1,
1278 &Printer->notify.client_hnd))
1279 Printer->notify.client_connected=True;
1281 return NT_STATUS_NO_PROBLEMO;
1284 /*******************************************************************
1285 * fill a notify_info_data with the servername
1286 ********************************************************************/
1287 static void spoolss_notify_server_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)
1293 pstring temp_name, temp;
1296 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1298 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1300 data->notify_data.data.length = len / 2 - 1;
1301 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1303 if (!data->notify_data.data.string) {
1304 data->notify_data.data.length = 0;
1308 memcpy(data->notify_data.data.string, temp, len);
1311 /*******************************************************************
1312 * fill a notify_info_data with the printername (not including the servername).
1313 ********************************************************************/
1314 static void spoolss_notify_printer_name(int snum,
1315 SPOOL_NOTIFY_INFO_DATA *data,
1316 print_queue_struct *queue,
1317 NT_PRINTER_INFO_LEVEL *printer,
1318 TALLOC_CTX *mem_ctx)
1323 /* the notify name should not contain the \\server\ part */
1324 char *p = strrchr(printer->info_2->printername, '\\');
1327 p = printer->info_2->printername;
1332 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1334 data->notify_data.data.length = len / 2 - 1;
1335 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1337 if (!data->notify_data.data.string) {
1338 data->notify_data.data.length = 0;
1342 memcpy(data->notify_data.data.string, temp, len);
1345 /*******************************************************************
1346 * fill a notify_info_data with the servicename
1347 ********************************************************************/
1348 static void spoolss_notify_share_name(int snum,
1349 SPOOL_NOTIFY_INFO_DATA *data,
1350 print_queue_struct *queue,
1351 NT_PRINTER_INFO_LEVEL *printer,
1352 TALLOC_CTX *mem_ctx)
1357 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1358 sizeof(temp) - 2, True);
1360 data->notify_data.data.length = len / 2 - 1;
1361 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1363 if (!data->notify_data.data.string) {
1364 data->notify_data.data.length = 0;
1368 memcpy(data->notify_data.data.string, temp, len);
1371 /*******************************************************************
1372 * fill a notify_info_data with the port name
1373 ********************************************************************/
1374 static void spoolss_notify_port_name(int snum,
1375 SPOOL_NOTIFY_INFO_DATA *data,
1376 print_queue_struct *queue,
1377 NT_PRINTER_INFO_LEVEL *printer,
1378 TALLOC_CTX *mem_ctx)
1383 /* even if it's strange, that's consistant in all the code */
1385 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1386 sizeof(temp) - 2, True);
1388 data->notify_data.data.length = len / 2 - 1;
1389 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1391 if (!data->notify_data.data.string) {
1392 data->notify_data.data.length = 0;
1396 memcpy(data->notify_data.data.string, temp, len);
1399 /*******************************************************************
1400 * fill a notify_info_data with the printername
1401 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1402 * but it doesn't exist, have to see what to do
1403 ********************************************************************/
1404 static void spoolss_notify_driver_name(int snum,
1405 SPOOL_NOTIFY_INFO_DATA *data,
1406 print_queue_struct *queue,
1407 NT_PRINTER_INFO_LEVEL *printer,
1408 TALLOC_CTX *mem_ctx)
1413 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1414 sizeof(temp) - 2, True);
1416 data->notify_data.data.length = len / 2 - 1;
1417 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1419 if (!data->notify_data.data.string) {
1420 data->notify_data.data.length = 0;
1424 memcpy(data->notify_data.data.string, temp, len);
1427 /*******************************************************************
1428 * fill a notify_info_data with the comment
1429 ********************************************************************/
1430 static void spoolss_notify_comment(int snum,
1431 SPOOL_NOTIFY_INFO_DATA *data,
1432 print_queue_struct *queue,
1433 NT_PRINTER_INFO_LEVEL *printer,
1434 TALLOC_CTX *mem_ctx)
1439 if (*printer->info_2->comment == '\0')
1440 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1441 sizeof(temp) - 2, True);
1443 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1444 sizeof(temp) - 2, True);
1446 data->notify_data.data.length = len / 2 - 1;
1447 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1449 if (!data->notify_data.data.string) {
1450 data->notify_data.data.length = 0;
1454 memcpy(data->notify_data.data.string, temp, len);
1457 /*******************************************************************
1458 * fill a notify_info_data with the comment
1459 * jfm:xxxx incorrect, have to create a new smb.conf option
1460 * location = "Room 1, floor 2, building 3"
1461 ********************************************************************/
1462 static void spoolss_notify_location(int snum,
1463 SPOOL_NOTIFY_INFO_DATA *data,
1464 print_queue_struct *queue,
1465 NT_PRINTER_INFO_LEVEL *printer,
1466 TALLOC_CTX *mem_ctx)
1471 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1472 sizeof(temp) - 2, True);
1474 data->notify_data.data.length = len / 2 - 1;
1475 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1477 if (!data->notify_data.data.string) {
1478 data->notify_data.data.length = 0;
1482 memcpy(data->notify_data.data.string, temp, len);
1485 /*******************************************************************
1486 * fill a notify_info_data with the device mode
1487 * jfm:xxxx don't to it for know but that's a real problem !!!
1488 ********************************************************************/
1489 static void spoolss_notify_devmode(int snum,
1490 SPOOL_NOTIFY_INFO_DATA *data,
1491 print_queue_struct *queue,
1492 NT_PRINTER_INFO_LEVEL *printer,
1493 TALLOC_CTX *mem_ctx)
1497 /*******************************************************************
1498 * fill a notify_info_data with the separator file name
1499 * jfm:xxxx just return no file could add an option to smb.conf
1500 * separator file = "separator.txt"
1501 ********************************************************************/
1502 static void spoolss_notify_sepfile(int snum,
1503 SPOOL_NOTIFY_INFO_DATA *data,
1504 print_queue_struct *queue,
1505 NT_PRINTER_INFO_LEVEL *printer,
1506 TALLOC_CTX *mem_ctx)
1511 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1512 sizeof(temp) - 2, True);
1514 data->notify_data.data.length = len / 2 - 1;
1515 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1517 if (!data->notify_data.data.string) {
1518 data->notify_data.data.length = 0;
1522 memcpy(data->notify_data.data.string, temp, len);
1525 /*******************************************************************
1526 * fill a notify_info_data with the print processor
1527 * jfm:xxxx return always winprint to indicate we don't do anything to it
1528 ********************************************************************/
1529 static void spoolss_notify_print_processor(int snum,
1530 SPOOL_NOTIFY_INFO_DATA *data,
1531 print_queue_struct *queue,
1532 NT_PRINTER_INFO_LEVEL *printer,
1533 TALLOC_CTX *mem_ctx)
1538 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
1539 sizeof(temp) - 2, True);
1541 data->notify_data.data.length = len / 2 - 1;
1542 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1544 if (!data->notify_data.data.string) {
1545 data->notify_data.data.length = 0;
1549 memcpy(data->notify_data.data.string, temp, len);
1552 /*******************************************************************
1553 * fill a notify_info_data with the print processor options
1554 * jfm:xxxx send an empty string
1555 ********************************************************************/
1556 static void spoolss_notify_parameters(int snum,
1557 SPOOL_NOTIFY_INFO_DATA *data,
1558 print_queue_struct *queue,
1559 NT_PRINTER_INFO_LEVEL *printer,
1560 TALLOC_CTX *mem_ctx)
1565 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1566 sizeof(temp) - 2, True);
1568 data->notify_data.data.length = len / 2 - 1;
1569 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1571 if (!data->notify_data.data.string) {
1572 data->notify_data.data.length = 0;
1576 memcpy(data->notify_data.data.string, temp, len);
1579 /*******************************************************************
1580 * fill a notify_info_data with the data type
1581 * jfm:xxxx always send RAW as data type
1582 ********************************************************************/
1583 static void spoolss_notify_datatype(int snum,
1584 SPOOL_NOTIFY_INFO_DATA *data,
1585 print_queue_struct *queue,
1586 NT_PRINTER_INFO_LEVEL *printer,
1587 TALLOC_CTX *mem_ctx)
1592 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1593 sizeof(pstring) - 2, True);
1595 data->notify_data.data.length = len / 2 - 1;
1596 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1598 if (!data->notify_data.data.string) {
1599 data->notify_data.data.length = 0;
1603 memcpy(data->notify_data.data.string, temp, len);
1606 /*******************************************************************
1607 * fill a notify_info_data with the security descriptor
1608 * jfm:xxxx send an null pointer to say no security desc
1609 * have to implement security before !
1610 ********************************************************************/
1611 static void spoolss_notify_security_desc(int snum,
1612 SPOOL_NOTIFY_INFO_DATA *data,
1613 print_queue_struct *queue,
1614 NT_PRINTER_INFO_LEVEL *printer,
1615 TALLOC_CTX *mem_ctx)
1617 data->notify_data.data.length=0;
1618 data->notify_data.data.string = NULL;
1621 /*******************************************************************
1622 * fill a notify_info_data with the attributes
1623 * jfm:xxxx a samba printer is always shared
1624 ********************************************************************/
1625 static void spoolss_notify_attributes(int snum,
1626 SPOOL_NOTIFY_INFO_DATA *data,
1627 print_queue_struct *queue,
1628 NT_PRINTER_INFO_LEVEL *printer,
1629 TALLOC_CTX *mem_ctx)
1631 data->notify_data.value[0] = printer->info_2->attributes;
1634 /*******************************************************************
1635 * fill a notify_info_data with the priority
1636 ********************************************************************/
1637 static void spoolss_notify_priority(int snum,
1638 SPOOL_NOTIFY_INFO_DATA *data,
1639 print_queue_struct *queue,
1640 NT_PRINTER_INFO_LEVEL *printer,
1641 TALLOC_CTX *mem_ctx)
1643 data->notify_data.value[0] = printer->info_2->priority;
1646 /*******************************************************************
1647 * fill a notify_info_data with the default priority
1648 ********************************************************************/
1649 static void spoolss_notify_default_priority(int snum,
1650 SPOOL_NOTIFY_INFO_DATA *data,
1651 print_queue_struct *queue,
1652 NT_PRINTER_INFO_LEVEL *printer,
1653 TALLOC_CTX *mem_ctx)
1655 data->notify_data.value[0] = printer->info_2->default_priority;
1658 /*******************************************************************
1659 * fill a notify_info_data with the start time
1660 ********************************************************************/
1661 static void spoolss_notify_start_time(int snum,
1662 SPOOL_NOTIFY_INFO_DATA *data,
1663 print_queue_struct *queue,
1664 NT_PRINTER_INFO_LEVEL *printer,
1665 TALLOC_CTX *mem_ctx)
1667 data->notify_data.value[0] = printer->info_2->starttime;
1670 /*******************************************************************
1671 * fill a notify_info_data with the until time
1672 ********************************************************************/
1673 static void spoolss_notify_until_time(int snum,
1674 SPOOL_NOTIFY_INFO_DATA *data,
1675 print_queue_struct *queue,
1676 NT_PRINTER_INFO_LEVEL *printer,
1677 TALLOC_CTX *mem_ctx)
1679 data->notify_data.value[0] = printer->info_2->untiltime;
1682 /*******************************************************************
1683 * fill a notify_info_data with the status
1684 ********************************************************************/
1685 static void spoolss_notify_status(int snum,
1686 SPOOL_NOTIFY_INFO_DATA *data,
1687 print_queue_struct *queue,
1688 NT_PRINTER_INFO_LEVEL *printer,
1689 TALLOC_CTX *mem_ctx)
1693 print_queue_struct *q=NULL;
1694 print_status_struct status;
1696 memset(&status, 0, sizeof(status));
1697 count = print_queue_status(snum, &q, &status);
1698 data->notify_data.value[0]=(uint32) status.status;
1702 /*******************************************************************
1703 * fill a notify_info_data with the number of jobs queued
1704 ********************************************************************/
1705 static void spoolss_notify_cjobs(int snum,
1706 SPOOL_NOTIFY_INFO_DATA *data,
1707 print_queue_struct *queue,
1708 NT_PRINTER_INFO_LEVEL *printer,
1709 TALLOC_CTX *mem_ctx)
1711 print_queue_struct *q=NULL;
1712 print_status_struct status;
1714 memset(&status, 0, sizeof(status));
1715 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1719 /*******************************************************************
1720 * fill a notify_info_data with the average ppm
1721 ********************************************************************/
1722 static void spoolss_notify_average_ppm(int snum,
1723 SPOOL_NOTIFY_INFO_DATA *data,
1724 print_queue_struct *queue,
1725 NT_PRINTER_INFO_LEVEL *printer,
1726 TALLOC_CTX *mem_ctx)
1728 /* always respond 8 pages per minutes */
1729 /* a little hard ! */
1730 data->notify_data.value[0] = printer->info_2->averageppm;
1733 /*******************************************************************
1734 * fill a notify_info_data with username
1735 ********************************************************************/
1736 static void spoolss_notify_username(int snum,
1737 SPOOL_NOTIFY_INFO_DATA *data,
1738 print_queue_struct *queue,
1739 NT_PRINTER_INFO_LEVEL *printer,
1740 TALLOC_CTX *mem_ctx)
1745 len = (uint32)dos_PutUniCode(temp, queue->user,
1746 sizeof(temp) - 2, True);
1748 data->notify_data.data.length = len / 2 - 1;
1749 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1751 if (!data->notify_data.data.string) {
1752 data->notify_data.data.length = 0;
1756 memcpy(data->notify_data.data.string, temp, len);
1759 /*******************************************************************
1760 * fill a notify_info_data with job status
1761 ********************************************************************/
1762 static void spoolss_notify_job_status(int snum,
1763 SPOOL_NOTIFY_INFO_DATA *data,
1764 print_queue_struct *queue,
1765 NT_PRINTER_INFO_LEVEL *printer,
1766 TALLOC_CTX *mem_ctx)
1768 data->notify_data.value[0]=nt_printj_status(queue->status);
1771 /*******************************************************************
1772 * fill a notify_info_data with job name
1773 ********************************************************************/
1774 static void spoolss_notify_job_name(int snum,
1775 SPOOL_NOTIFY_INFO_DATA *data,
1776 print_queue_struct *queue,
1777 NT_PRINTER_INFO_LEVEL *printer,
1778 TALLOC_CTX *mem_ctx)
1783 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1786 data->notify_data.data.length = len / 2 - 1;
1787 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1789 if (!data->notify_data.data.string) {
1790 data->notify_data.data.length = 0;
1794 memcpy(data->notify_data.data.string, temp, len);
1797 /*******************************************************************
1798 * fill a notify_info_data with job status
1799 ********************************************************************/
1800 static void spoolss_notify_job_status_string(int snum,
1801 SPOOL_NOTIFY_INFO_DATA *data,
1802 print_queue_struct *queue,
1803 NT_PRINTER_INFO_LEVEL *printer,
1804 TALLOC_CTX *mem_ctx)
1807 * Now we're returning job status codes we just return a "" here. JRA.
1814 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1817 switch (queue->status) {
1822 p = ""; /* NT provides the paused string */
1831 #endif /* NO LONGER NEEDED. */
1833 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1835 data->notify_data.data.length = len / 2 - 1;
1836 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1838 if (!data->notify_data.data.string) {
1839 data->notify_data.data.length = 0;
1843 memcpy(data->notify_data.data.string, temp, len);
1846 /*******************************************************************
1847 * fill a notify_info_data with job time
1848 ********************************************************************/
1849 static void spoolss_notify_job_time(int snum,
1850 SPOOL_NOTIFY_INFO_DATA *data,
1851 print_queue_struct *queue,
1852 NT_PRINTER_INFO_LEVEL *printer,
1853 TALLOC_CTX *mem_ctx)
1855 data->notify_data.value[0]=0x0;
1858 /*******************************************************************
1859 * fill a notify_info_data with job size
1860 ********************************************************************/
1861 static void spoolss_notify_job_size(int snum,
1862 SPOOL_NOTIFY_INFO_DATA *data,
1863 print_queue_struct *queue,
1864 NT_PRINTER_INFO_LEVEL *printer,
1865 TALLOC_CTX *mem_ctx)
1867 data->notify_data.value[0]=queue->size;
1870 /*******************************************************************
1871 * fill a notify_info_data with job position
1872 ********************************************************************/
1873 static void spoolss_notify_job_position(int snum,
1874 SPOOL_NOTIFY_INFO_DATA *data,
1875 print_queue_struct *queue,
1876 NT_PRINTER_INFO_LEVEL *printer,
1877 TALLOC_CTX *mem_ctx)
1879 data->notify_data.value[0]=queue->job;
1882 /*******************************************************************
1883 * fill a notify_info_data with submitted time
1884 ********************************************************************/
1885 static void spoolss_notify_submitted_time(int snum,
1886 SPOOL_NOTIFY_INFO_DATA *data,
1887 print_queue_struct *queue,
1888 NT_PRINTER_INFO_LEVEL *printer,
1889 TALLOC_CTX *mem_ctx)
1894 t=gmtime(&queue->time);
1896 len = sizeof(SYSTEMTIME);
1898 data->notify_data.data.length = len;
1899 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1901 if (!data->notify_data.data.string) {
1902 data->notify_data.data.length = 0;
1906 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
1911 struct s_notify_info_data_table
1917 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1918 print_queue_struct *queue,
1919 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
1922 struct s_notify_info_data_table notify_info_data_table[] =
1924 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1925 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1926 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1927 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1928 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1929 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1930 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1931 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1932 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1933 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1934 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1935 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1936 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1937 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1938 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1939 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1940 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1941 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1942 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1943 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1944 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1945 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1946 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1947 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1948 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1949 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1950 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1951 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1952 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1953 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1954 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1955 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1956 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1957 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1958 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1959 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1960 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1961 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1962 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1963 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1964 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1965 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1966 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
1967 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1968 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1969 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1970 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1971 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1972 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1973 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1974 { END, END, "", END, NULL }
1977 /*******************************************************************
1978 return the size of info_data structure
1979 ********************************************************************/
1980 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1984 while (notify_info_data_table[i].type != END)
1986 if ( (notify_info_data_table[i].type == type ) &&
1987 (notify_info_data_table[i].field == field ) )
1989 return (notify_info_data_table[i].size);
1996 /*******************************************************************
1997 return the type of notify_info_data
1998 ********************************************************************/
1999 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2003 while (notify_info_data_table[i].type != END)
2005 if ( (notify_info_data_table[i].type == type ) &&
2006 (notify_info_data_table[i].field == field ) )
2008 if (notify_info_data_table[i].size == POINTER)
2022 /****************************************************************************
2023 ****************************************************************************/
2024 static int search_notify(uint16 type, uint16 field, int *value)
2029 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2031 if ( (notify_info_data_table[j].type == type ) &&
2032 (notify_info_data_table[j].field == field ) )
2037 if ( found && (notify_info_data_table[j].fn != NULL) )
2043 /****************************************************************************
2044 ****************************************************************************/
2045 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2047 info_data->type = type;
2048 info_data->field = field;
2049 info_data->reserved = 0;
2051 info_data->size = size_of_notify_info_data(type, field);
2052 info_data->enc_type = type_of_notify_info_data(type, field);
2056 /*******************************************************************
2058 * fill a notify_info struct with info asked
2060 ********************************************************************/
2061 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2062 snum, SPOOL_NOTIFY_OPTION_TYPE
2063 *option_type, uint32 id,
2064 TALLOC_CTX *mem_ctx)
2070 SPOOL_NOTIFY_INFO_DATA *current_data;
2071 NT_PRINTER_INFO_LEVEL *printer = NULL;
2072 print_queue_struct *queue=NULL;
2074 type=option_type->type;
2076 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2077 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2078 option_type->count, lp_servicename(snum)));
2080 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2083 for(field_num=0; field_num<option_type->count; field_num++) {
2084 field = option_type->fields[field_num];
2085 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2087 if (!search_notify(type, field, &j) )
2090 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2093 current_data=&info->data[info->count];
2095 construct_info_data(current_data, type, field, id);
2097 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2098 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2100 notify_info_data_table[j].fn(snum, current_data, queue,
2106 free_a_printer(&printer, 2);
2110 /*******************************************************************
2112 * fill a notify_info struct with info asked
2114 ********************************************************************/
2115 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2116 SPOOL_NOTIFY_INFO *info,
2117 NT_PRINTER_INFO_LEVEL *printer,
2118 int snum, SPOOL_NOTIFY_OPTION_TYPE
2119 *option_type, uint32 id,
2120 TALLOC_CTX *mem_ctx)
2126 SPOOL_NOTIFY_INFO_DATA *current_data;
2128 DEBUG(4,("construct_notify_jobs_info\n"));
2130 type = option_type->type;
2132 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2133 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2134 option_type->count));
2136 for(field_num=0; field_num<option_type->count; field_num++) {
2137 field = option_type->fields[field_num];
2139 if (!search_notify(type, field, &j) )
2142 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2146 current_data=&(info->data[info->count]);
2148 construct_info_data(current_data, type, field, id);
2149 notify_info_data_table[j].fn(snum, current_data, queue,
2158 * JFM: The enumeration is not that simple, it's even non obvious.
2160 * let's take an example: I want to monitor the PRINTER SERVER for
2161 * the printer's name and the number of jobs currently queued.
2162 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2163 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2165 * I have 3 printers on the back of my server.
2167 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2170 * 1 printer 1 name 1
2171 * 2 printer 1 cjob 1
2172 * 3 printer 2 name 2
2173 * 4 printer 2 cjob 2
2174 * 5 printer 3 name 3
2175 * 6 printer 3 name 3
2177 * that's the print server case, the printer case is even worse.
2182 /*******************************************************************
2184 * enumerate all printers on the printserver
2185 * fill a notify_info struct with info asked
2187 ********************************************************************/
2188 static uint32 printserver_notify_info(const POLICY_HND *hnd,
2189 SPOOL_NOTIFY_INFO *info,
2190 TALLOC_CTX *mem_ctx)
2193 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2194 int n_services=lp_numservices();
2197 SPOOL_NOTIFY_OPTION *option;
2198 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2200 DEBUG(4,("printserver_notify_info\n"));
2202 option=Printer->notify.option;
2208 for (i=0; i<option->count; i++) {
2209 option_type=&(option->ctr.type[i]);
2211 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2214 for (snum=0; snum<n_services; snum++)
2215 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2216 if (construct_notify_printer_info
2217 (info, snum, option_type, id, mem_ctx))
2222 * Debugging information, don't delete.
2225 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2226 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2227 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2229 for (i=0; i<info->count; i++) {
2230 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2231 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2232 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2236 return NT_STATUS_NO_PROBLEMO;
2239 /*******************************************************************
2241 * fill a notify_info struct with info asked
2243 ********************************************************************/
2244 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2245 TALLOC_CTX *mem_ctx)
2248 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2251 SPOOL_NOTIFY_OPTION *option;
2252 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2254 print_queue_struct *queue=NULL;
2255 print_status_struct status;
2257 DEBUG(4,("printer_notify_info\n"));
2259 option=Printer->notify.option;
2265 get_printer_snum(hnd, &snum);
2267 for (i=0; i<option->count; i++) {
2268 option_type=&option->ctr.type[i];
2270 switch ( option_type->type ) {
2271 case PRINTER_NOTIFY_TYPE:
2272 if(construct_notify_printer_info(info, snum,
2278 case JOB_NOTIFY_TYPE: {
2279 NT_PRINTER_INFO_LEVEL *printer = NULL;
2281 memset(&status, 0, sizeof(status));
2282 count = print_queue_status(snum, &queue, &status);
2284 if (get_a_printer(&printer, 2,
2285 lp_servicename(snum)) != 0)
2288 for (j=0; j<count; j++) {
2289 construct_notify_jobs_info(&queue[j], info,
2296 free_a_printer(&printer, 2);
2306 * Debugging information, don't delete.
2309 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2310 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2311 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2313 for (i=0; i<info->count; i++) {
2314 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2315 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2316 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2319 return NT_STATUS_NO_PROBLEMO;
2322 /********************************************************************
2324 ********************************************************************/
2325 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
2326 SPOOL_NOTIFY_OPTION *option, TALLOC_CTX *mem_ctx,
2327 SPOOL_NOTIFY_INFO *info)
2329 Printer_entry *Printer=find_printer_index_by_hnd(handle);
2330 uint32 result = ERROR_INVALID_HANDLE;
2332 if (!OPEN_HANDLE(Printer)) {
2333 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2334 OUR_HANDLE(handle)));
2338 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2340 /* jfm: the change value isn't used right now.
2341 * we will honour it when
2342 * a) we'll be able to send notification to the client
2343 * b) we'll have a way to communicate between the spoolss process.
2345 * same thing for option->flags
2346 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2347 * I don't have a global notification system, I'm sending back all the
2348 * informations even when _NOTHING_ has changed.
2351 /* just discard the SPOOL_NOTIFY_OPTION */
2353 safe_free(option->ctr.type);
2355 switch (Printer->printer_type) {
2356 case PRINTER_HANDLE_IS_PRINTSERVER:
2357 result = printserver_notify_info(handle, info,
2361 case PRINTER_HANDLE_IS_PRINTER:
2362 result = printer_notify_info(handle, info, mem_ctx);
2370 /********************************************************************
2371 * construct_printer_info_0
2372 * fill a printer_info_0 struct
2373 ********************************************************************/
2374 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2378 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2379 counter_printer_0 *session_counter;
2380 uint32 global_counter;
2384 print_queue_struct *queue=NULL;
2385 print_status_struct status;
2387 memset(&status, 0, sizeof(status));
2389 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2392 count = print_queue_status(snum, &queue, &status);
2394 /* check if we already have a counter for this printer */
2395 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2397 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2398 if (session_counter->snum == snum)
2402 /* it's the first time, add it to the list */
2403 if (session_counter==NULL) {
2404 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2405 free_a_printer(&ntprinter, 2);
2408 ZERO_STRUCTP(session_counter);
2409 session_counter->snum=snum;
2410 session_counter->counter=0;
2411 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2415 session_counter->counter++;
2418 * the global_counter should be stored in a TDB as it's common to all the clients
2419 * and should be zeroed on samba startup
2421 global_counter=session_counter->counter;
2423 pstrcpy(chaine,ntprinter->info_2->printername);
2425 init_unistr(&printer->printername, chaine);
2427 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2428 init_unistr(&printer->servername, chaine);
2430 printer->cjobs = count;
2431 printer->total_jobs = 0;
2432 printer->total_bytes = 0;
2434 setuptime = (time_t)ntprinter->info_2->setuptime;
2435 t=gmtime(&setuptime);
2437 printer->year = t->tm_year+1900;
2438 printer->month = t->tm_mon+1;
2439 printer->dayofweek = t->tm_wday;
2440 printer->day = t->tm_mday;
2441 printer->hour = t->tm_hour;
2442 printer->minute = t->tm_min;
2443 printer->second = t->tm_sec;
2444 printer->milliseconds = 0;
2446 printer->global_counter = global_counter;
2447 printer->total_pages = 0;
2448 printer->major_version = 0x0004; /* NT 4 */
2449 printer->build_version = 0x0565; /* build 1381 */
2450 printer->unknown7 = 0x1;
2451 printer->unknown8 = 0x0;
2452 printer->unknown9 = 0x0;
2453 printer->session_counter = session_counter->counter;
2454 printer->unknown11 = 0x0;
2455 printer->printer_errors = 0x0; /* number of print failure */
2456 printer->unknown13 = 0x0;
2457 printer->unknown14 = 0x1;
2458 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2459 printer->unknown16 = 0x0;
2460 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2461 printer->unknown18 = 0x0;
2462 printer->status = nt_printq_status(status.status);
2463 printer->unknown20 = 0x0;
2464 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2465 printer->unknown22 = 0x0;
2466 printer->unknown23 = 0x6; /* 6 ???*/
2467 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2468 printer->unknown25 = 0;
2469 printer->unknown26 = 0;
2470 printer->unknown27 = 0;
2471 printer->unknown28 = 0;
2472 printer->unknown29 = 0;
2475 free_a_printer(&ntprinter,2);
2479 /********************************************************************
2480 * construct_printer_info_1
2481 * fill a printer_info_1 struct
2482 ********************************************************************/
2483 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2487 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2489 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2492 printer->flags=flags;
2494 if (*ntprinter->info_2->comment == '\0') {
2495 init_unistr(&printer->comment, lp_comment(snum));
2496 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2497 ntprinter->info_2->drivername, lp_comment(snum));
2500 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2501 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2502 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2505 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2507 init_unistr(&printer->description, chaine);
2508 init_unistr(&printer->name, chaine2);
2510 free_a_printer(&ntprinter,2);
2515 /****************************************************************************
2516 Free a DEVMODE struct.
2517 ****************************************************************************/
2519 static void free_dev_mode(DEVICEMODE *dev)
2525 safe_free(dev->private);
2530 /****************************************************************************
2531 Create a DEVMODE struct. Returns malloced memory.
2532 ****************************************************************************/
2534 static DEVICEMODE *construct_dev_mode(int snum)
2538 NT_PRINTER_INFO_LEVEL *printer = NULL;
2539 NT_DEVICEMODE *ntdevmode = NULL;
2540 DEVICEMODE *devmode = NULL;
2542 DEBUG(7,("construct_dev_mode\n"));
2544 DEBUGADD(8,("getting printer characteristics\n"));
2546 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2547 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2551 ZERO_STRUCTP(devmode);
2553 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2556 if (printer->info_2->devmode)
2557 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2559 if (ntdevmode == NULL)
2562 DEBUGADD(8,("loading DEVICEMODE\n"));
2564 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2565 init_unistr(&devmode->devicename, adevice);
2567 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2568 init_unistr(&devmode->formname, aform);
2570 devmode->specversion = ntdevmode->specversion;
2571 devmode->driverversion = ntdevmode->driverversion;
2572 devmode->size = ntdevmode->size;
2573 devmode->driverextra = ntdevmode->driverextra;
2574 devmode->fields = ntdevmode->fields;
2576 devmode->orientation = ntdevmode->orientation;
2577 devmode->papersize = ntdevmode->papersize;
2578 devmode->paperlength = ntdevmode->paperlength;
2579 devmode->paperwidth = ntdevmode->paperwidth;
2580 devmode->scale = ntdevmode->scale;
2581 devmode->copies = ntdevmode->copies;
2582 devmode->defaultsource = ntdevmode->defaultsource;
2583 devmode->printquality = ntdevmode->printquality;
2584 devmode->color = ntdevmode->color;
2585 devmode->duplex = ntdevmode->duplex;
2586 devmode->yresolution = ntdevmode->yresolution;
2587 devmode->ttoption = ntdevmode->ttoption;
2588 devmode->collate = ntdevmode->collate;
2589 devmode->icmmethod = ntdevmode->icmmethod;
2590 devmode->icmintent = ntdevmode->icmintent;
2591 devmode->mediatype = ntdevmode->mediatype;
2592 devmode->dithertype = ntdevmode->dithertype;
2594 if (ntdevmode->private != NULL) {
2595 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2599 free_nt_devicemode(&ntdevmode);
2600 free_a_printer(&printer,2);
2607 free_nt_devicemode(&ntdevmode);
2609 free_a_printer(&printer,2);
2610 free_dev_mode(devmode);
2615 /********************************************************************
2616 * construct_printer_info_2
2617 * fill a printer_info_2 struct
2618 ********************************************************************/
2620 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2623 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2625 print_queue_struct *queue=NULL;
2626 print_status_struct status;
2627 memset(&status, 0, sizeof(status));
2629 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2632 memset(&status, 0, sizeof(status));
2633 count = print_queue_status(snum, &queue, &status);
2635 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2636 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2637 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2638 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2639 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2641 if (*ntprinter->info_2->comment == '\0')
2642 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2644 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2646 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2647 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2648 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2649 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2650 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2652 printer->attributes = ntprinter->info_2->attributes;
2654 printer->priority = ntprinter->info_2->priority; /* priority */
2655 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2656 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2657 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2658 printer->status = nt_printq_status(status.status); /* status */
2659 printer->cjobs = count; /* jobs */
2660 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2662 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2663 DEBUG(8, ("Returning NULL Devicemode!\n"));
2666 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2667 /* steal the printer info sec_desc structure. [badly done]. */
2668 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2669 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2670 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2671 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2674 printer->secdesc = NULL;
2677 free_a_printer(&ntprinter, 2);
2682 /********************************************************************
2683 * construct_printer_info_3
2684 * fill a printer_info_3 struct
2685 ********************************************************************/
2686 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2688 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2689 PRINTER_INFO_3 *printer = NULL;
2691 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2695 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2696 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2700 ZERO_STRUCTP(printer);
2702 printer->flags = 4; /* These are the components of the SD we are returning. */
2703 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2704 /* steal the printer info sec_desc structure. [badly done]. */
2705 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2709 * Set the flags for the components we are returning.
2712 if (printer->secdesc->owner_sid)
2713 printer->flags |= OWNER_SECURITY_INFORMATION;
2715 if (printer->secdesc->grp_sid)
2716 printer->flags |= GROUP_SECURITY_INFORMATION;
2718 if (printer->secdesc->dacl)
2719 printer->flags |= DACL_SECURITY_INFORMATION;
2721 if (printer->secdesc->sacl)
2722 printer->flags |= SACL_SECURITY_INFORMATION;
2725 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2726 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2727 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2730 free_a_printer(&ntprinter, 2);
2732 *pp_printer = printer;
2736 /********************************************************************
2737 Spoolss_enumprinters.
2738 ********************************************************************/
2739 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2743 int n_services=lp_numservices();
2744 PRINTER_INFO_1 *printers=NULL;
2745 PRINTER_INFO_1 current_prt;
2747 DEBUG(4,("enum_all_printers_info_1\n"));
2749 for (snum=0; snum<n_services; snum++) {
2750 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2751 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2753 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2754 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2756 return ERROR_NOT_ENOUGH_MEMORY;
2758 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2759 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2765 /* check the required size. */
2766 for (i=0; i<*returned; i++)
2767 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2769 if (!alloc_buffer_size(buffer, *needed))
2770 return ERROR_INSUFFICIENT_BUFFER;
2772 /* fill the buffer with the structures */
2773 for (i=0; i<*returned; i++)
2774 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2777 safe_free(printers);
2779 if (*needed > offered) {
2781 return ERROR_INSUFFICIENT_BUFFER;
2784 return NT_STATUS_NO_PROBLEMO;
2787 /********************************************************************
2788 enum_all_printers_info_1_local.
2789 *********************************************************************/
2790 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2792 DEBUG(4,("enum_all_printers_info_1_local\n"));
2794 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2797 /********************************************************************
2798 enum_all_printers_info_1_name.
2799 *********************************************************************/
2800 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2803 DEBUG(4,("enum_all_printers_info_1_name\n"));
2805 fstrcpy(temp, "\\\\");
2806 fstrcat(temp, global_myname);
2808 if (strequal(name, temp)) {
2809 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2812 return ERROR_INVALID_NAME;
2815 /********************************************************************
2816 enum_all_printers_info_1_remote.
2817 *********************************************************************/
2818 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2820 PRINTER_INFO_1 *printer;
2821 fstring printername;
2824 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2826 /* JFM: currently it's more a place holder than anything else.
2827 * In the spooler world there is a notion of server registration.
2828 * the print servers are registring (sp ?) on the PDC (in the same domain)
2830 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2833 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2834 return ERROR_NOT_ENOUGH_MEMORY;
2838 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2839 slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2840 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2842 init_unistr(&printer->description, desc);
2843 init_unistr(&printer->name, printername);
2844 init_unistr(&printer->comment, comment);
2845 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2847 /* check the required size. */
2848 *needed += spoolss_size_printer_info_1(printer);
2850 if (!alloc_buffer_size(buffer, *needed)) {
2852 return ERROR_INSUFFICIENT_BUFFER;
2855 /* fill the buffer with the structures */
2856 new_smb_io_printer_info_1("", buffer, printer, 0);
2861 if (*needed > offered) {
2863 return ERROR_INSUFFICIENT_BUFFER;
2866 return NT_STATUS_NO_PROBLEMO;
2869 /********************************************************************
2870 enum_all_printers_info_1_network.
2871 *********************************************************************/
2872 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2874 DEBUG(4,("enum_all_printers_info_1_network\n"));
2876 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2879 /********************************************************************
2880 * api_spoolss_enumprinters
2882 * called from api_spoolss_enumprinters (see this to understand)
2883 ********************************************************************/
2884 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2888 int n_services=lp_numservices();
2889 PRINTER_INFO_2 *printers=NULL;
2890 PRINTER_INFO_2 current_prt;
2892 for (snum=0; snum<n_services; snum++) {
2893 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2894 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2896 if (construct_printer_info_2(¤t_prt, snum)) {
2897 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2898 return ERROR_NOT_ENOUGH_MEMORY;
2899 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2900 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2906 /* check the required size. */
2907 for (i=0; i<*returned; i++)
2908 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2910 if (!alloc_buffer_size(buffer, *needed)) {
2911 for (i=0; i<*returned; i++) {
2912 free_devmode(printers[i].devmode);
2913 free_sec_desc(&printers[i].secdesc);
2915 safe_free(printers);
2916 return ERROR_INSUFFICIENT_BUFFER;
2919 /* fill the buffer with the structures */
2920 for (i=0; i<*returned; i++)
2921 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2924 for (i=0; i<*returned; i++) {
2925 free_devmode(printers[i].devmode);
2926 free_sec_desc(&printers[i].secdesc);
2928 safe_free(printers);
2930 if (*needed > offered) {
2932 return ERROR_INSUFFICIENT_BUFFER;
2935 return NT_STATUS_NO_PROBLEMO;
2938 /********************************************************************
2939 * handle enumeration of printers at level 1
2940 ********************************************************************/
2941 static uint32 enumprinters_level1( uint32 flags, fstring name,
2942 NEW_BUFFER *buffer, uint32 offered,
2943 uint32 *needed, uint32 *returned)
2945 /* Not all the flags are equals */
2947 if (flags & PRINTER_ENUM_LOCAL)
2948 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
2950 if (flags & PRINTER_ENUM_NAME)
2951 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2953 if (flags & PRINTER_ENUM_REMOTE)
2954 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2956 if (flags & PRINTER_ENUM_NETWORK)
2957 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
2959 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2962 /********************************************************************
2963 * handle enumeration of printers at level 2
2964 ********************************************************************/
2965 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2966 NEW_BUFFER *buffer, uint32 offered,
2967 uint32 *needed, uint32 *returned)
2971 fstrcpy(temp, "\\\\");
2972 fstrcat(temp, global_myname);
2974 if (flags & PRINTER_ENUM_LOCAL) {
2975 if (strequal(servername, temp))
2976 return enum_all_printers_info_2(buffer, offered, needed, returned);
2978 return enum_all_printers_info_2(buffer, offered, needed, returned);
2981 if (flags & PRINTER_ENUM_NAME) {
2982 if (strequal(servername, temp))
2983 return enum_all_printers_info_2(buffer, offered, needed, returned);
2985 return ERROR_INVALID_NAME;
2988 if (flags & PRINTER_ENUM_REMOTE)
2989 return ERROR_INVALID_LEVEL;
2991 return NT_STATUS_NO_PROBLEMO;
2994 /********************************************************************
2995 * handle enumeration of printers at level 5
2996 ********************************************************************/
2997 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2998 NEW_BUFFER *buffer, uint32 offered,
2999 uint32 *needed, uint32 *returned)
3001 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3002 return NT_STATUS_NO_PROBLEMO;
3005 /********************************************************************
3006 * api_spoolss_enumprinters
3008 * called from api_spoolss_enumprinters (see this to understand)
3009 ********************************************************************/
3010 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
3011 NEW_BUFFER *buffer, uint32 offered,
3012 uint32 *needed, uint32 *returned)
3016 DEBUG(4,("_spoolss_enumprinters\n"));
3023 * flags==PRINTER_ENUM_NAME
3024 * if name=="" then enumerates all printers
3025 * if name!="" then enumerate the printer
3026 * flags==PRINTER_ENUM_REMOTE
3027 * name is NULL, enumerate printers
3028 * Level 2: name!="" enumerates printers, name can't be NULL
3029 * Level 3: doesn't exist
3030 * Level 4: does a local registry lookup
3031 * Level 5: same as Level 2
3034 unistr2_to_ascii(name, servername, sizeof(name)-1);
3039 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3041 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3043 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3047 return ERROR_INVALID_LEVEL;
3051 /****************************************************************************
3052 ****************************************************************************/
3053 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3055 PRINTER_INFO_0 *printer=NULL;
3057 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3058 return ERROR_NOT_ENOUGH_MEMORY;
3060 construct_printer_info_0(printer, snum);
3062 /* check the required size. */
3063 *needed += spoolss_size_printer_info_0(printer);
3065 if (!alloc_buffer_size(buffer, *needed)) {
3067 return ERROR_INSUFFICIENT_BUFFER;
3070 /* fill the buffer with the structures */
3071 new_smb_io_printer_info_0("", buffer, printer, 0);
3076 if (*needed > offered) {
3077 return ERROR_INSUFFICIENT_BUFFER;
3080 return NT_STATUS_NO_PROBLEMO;
3083 /****************************************************************************
3084 ****************************************************************************/
3085 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3087 PRINTER_INFO_1 *printer=NULL;
3089 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3090 return ERROR_NOT_ENOUGH_MEMORY;
3092 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3094 /* check the required size. */
3095 *needed += spoolss_size_printer_info_1(printer);
3097 if (!alloc_buffer_size(buffer, *needed)) {
3099 return ERROR_INSUFFICIENT_BUFFER;
3102 /* fill the buffer with the structures */
3103 new_smb_io_printer_info_1("", buffer, printer, 0);
3108 if (*needed > offered) {
3109 return ERROR_INSUFFICIENT_BUFFER;
3112 return NT_STATUS_NO_PROBLEMO;
3115 /****************************************************************************
3116 ****************************************************************************/
3117 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3119 PRINTER_INFO_2 *printer=NULL;
3121 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3122 return ERROR_NOT_ENOUGH_MEMORY;
3124 construct_printer_info_2(printer, snum);
3126 /* check the required size. */
3127 *needed += spoolss_size_printer_info_2(printer);
3129 if (!alloc_buffer_size(buffer, *needed)) {
3130 free_printer_info_2(printer);
3131 return ERROR_INSUFFICIENT_BUFFER;
3134 /* fill the buffer with the structures */
3135 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
3136 free_printer_info_2(printer);
3137 return ERROR_NOT_ENOUGH_MEMORY;
3141 free_printer_info_2(printer);
3143 if (*needed > offered) {
3144 return ERROR_INSUFFICIENT_BUFFER;
3147 return NT_STATUS_NO_PROBLEMO;
3150 /****************************************************************************
3151 ****************************************************************************/
3152 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3154 PRINTER_INFO_3 *printer=NULL;
3156 if (!construct_printer_info_3(&printer, snum))
3157 return ERROR_NOT_ENOUGH_MEMORY;
3159 /* check the required size. */
3160 *needed += spoolss_size_printer_info_3(printer);
3162 if (!alloc_buffer_size(buffer, *needed)) {
3163 free_printer_info_3(printer);
3164 return ERROR_INSUFFICIENT_BUFFER;
3167 /* fill the buffer with the structures */
3168 new_smb_io_printer_info_3("", buffer, printer, 0);
3171 free_printer_info_3(printer);
3173 if (*needed > offered) {
3174 return ERROR_INSUFFICIENT_BUFFER;
3177 return NT_STATUS_NO_PROBLEMO;
3180 /****************************************************************************
3181 ****************************************************************************/
3182 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
3183 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3189 if (!get_printer_snum(handle, &snum))
3190 return ERROR_INVALID_HANDLE;
3194 return getprinter_level_0(snum, buffer, offered, needed);
3196 return getprinter_level_1(snum, buffer, offered, needed);
3198 return getprinter_level_2(snum, buffer, offered, needed);
3200 return getprinter_level_3(snum, buffer, offered, needed);
3202 return ERROR_INVALID_LEVEL;
3206 /********************************************************************
3207 * fill a DRIVER_INFO_1 struct
3208 ********************************************************************/
3209 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3211 init_unistr( &info->name, driver.info_3->name);
3214 /********************************************************************
3215 * construct_printer_driver_info_1
3216 ********************************************************************/
3217 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3219 NT_PRINTER_INFO_LEVEL *printer = NULL;
3220 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3222 ZERO_STRUCT(driver);
3224 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3225 return ERROR_INVALID_PRINTER_NAME;
3227 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3228 return ERROR_UNKNOWN_PRINTER_DRIVER;
3230 fill_printer_driver_info_1(info, driver, servername, architecture);
3232 free_a_printer(&printer,2);
3234 return NT_STATUS_NO_PROBLEMO;
3237 /********************************************************************
3238 * construct_printer_driver_info_2
3239 * fill a printer_info_2 struct
3240 ********************************************************************/
3241 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3245 info->version=driver.info_3->cversion;
3247 init_unistr( &info->name, driver.info_3->name );
3248 init_unistr( &info->architecture, driver.info_3->environment );
3251 if (strlen(driver.info_3->driverpath)) {
3252 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3253 init_unistr( &info->driverpath, temp );
3255 init_unistr( &info->driverpath, "" );
3257 if (strlen(driver.info_3->datafile)) {
3258 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3259 init_unistr( &info->datafile, temp );
3261 init_unistr( &info->datafile, "" );
3263 if (strlen(driver.info_3->configfile)) {
3264 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3265 init_unistr( &info->configfile, temp );
3267 init_unistr( &info->configfile, "" );
3270 /********************************************************************
3271 * construct_printer_driver_info_2
3272 * fill a printer_info_2 struct
3273 ********************************************************************/
3274 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3276 NT_PRINTER_INFO_LEVEL *printer = NULL;
3277 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3279 ZERO_STRUCT(printer);
3280 ZERO_STRUCT(driver);
3282 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3283 return ERROR_INVALID_PRINTER_NAME;
3285 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3286 return ERROR_UNKNOWN_PRINTER_DRIVER;
3288 fill_printer_driver_info_2(info, driver, servername);
3290 free_a_printer(&printer,2);
3292 return NT_STATUS_NO_PROBLEMO;
3295 /********************************************************************
3296 * copy a strings array and convert to UNICODE
3298 * convert an array of ascii string to a UNICODE string
3299 ********************************************************************/
3300 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3307 DEBUG(6,("init_unistr_array\n"));
3311 if (char_array == NULL)
3315 if (!v) v = ""; /* hack to handle null lists */
3317 if (strlen(v) == 0) break;
3318 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3319 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3320 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3321 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3324 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3329 (*uni_array)[j]=0x0000;
3332 DEBUGADD(6,("last one:done\n"));
3335 /********************************************************************
3336 * construct_printer_info_3
3337 * fill a printer_info_3 struct
3338 ********************************************************************/
3339 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3345 info->version=driver.info_3->cversion;
3347 init_unistr( &info->name, driver.info_3->name );
3348 init_unistr( &info->architecture, driver.info_3->environment );
3350 if (strlen(driver.info_3->driverpath)) {
3351 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3352 init_unistr( &info->driverpath, temp );
3354 init_unistr( &info->driverpath, "" );
3356 if (strlen(driver.info_3->datafile)) {
3357 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3358 init_unistr( &info->datafile, temp );
3360 init_unistr( &info->datafile, "" );
3362 if (strlen(driver.info_3->configfile)) {
3363 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3364 init_unistr( &info->configfile, temp );
3366 init_unistr( &info->configfile, "" );
3368 if (strlen(driver.info_3->helpfile)) {
3369 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3370 init_unistr( &info->helpfile, temp );
3372 init_unistr( &info->helpfile, "" );
3374 init_unistr( &info->monitorname, driver.info_3->monitorname );
3375 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3377 info->dependentfiles=NULL;
3378 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3381 /********************************************************************
3382 * construct_printer_info_3
3383 * fill a printer_info_3 struct
3384 ********************************************************************/
3385 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3387 NT_PRINTER_INFO_LEVEL *printer = NULL;
3388 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3390 ZERO_STRUCT(driver);
3392 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3393 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3395 return ERROR_INVALID_PRINTER_NAME;
3397 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3398 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3400 free_a_printer(&printer,2);
3401 return ERROR_UNKNOWN_PRINTER_DRIVER;
3404 fill_printer_driver_info_3(info, driver, servername);
3406 free_a_printer(&printer,2);
3408 return NT_STATUS_NO_PROBLEMO;
3411 /********************************************************************
3412 * construct_printer_info_6
3413 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3414 ********************************************************************/
3416 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3422 memset(&nullstr, '\0', sizeof(fstring));
3424 info->version=driver.info_3->cversion;
3426 init_unistr( &info->name, driver.info_3->name );
3427 init_unistr( &info->architecture, driver.info_3->environment );
3429 if (strlen(driver.info_3->driverpath)) {
3430 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3431 init_unistr( &info->driverpath, temp );
3433 init_unistr( &info->driverpath, "" );
3435 if (strlen(driver.info_3->datafile)) {
3436 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3437 init_unistr( &info->datafile, temp );
3439 init_unistr( &info->datafile, "" );
3441 if (strlen(driver.info_3->configfile)) {
3442 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3443 init_unistr( &info->configfile, temp );
3445 init_unistr( &info->configfile, "" );
3447 if (strlen(driver.info_3->helpfile)) {
3448 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3449 init_unistr( &info->helpfile, temp );
3451 init_unistr( &info->helpfile, "" );
3453 init_unistr( &info->monitorname, driver.info_3->monitorname );
3454 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3456 info->dependentfiles=NULL;
3457 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3459 info->previousdrivernames=NULL;
3460 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3462 info->driver_date.low=0;
3463 info->driver_date.high=0;
3466 info->driver_version_low=0;
3467 info->driver_version_high=0;
3469 init_unistr( &info->mfgname, "");
3470 init_unistr( &info->oem_url, "");
3471 init_unistr( &info->hardware_id, "");
3472 init_unistr( &info->provider, "");
3475 /********************************************************************
3476 * construct_printer_info_6
3477 * fill a printer_info_6 struct
3478 ********************************************************************/
3479 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3481 NT_PRINTER_INFO_LEVEL *printer = NULL;
3482 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3484 ZERO_STRUCT(driver);
3486 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3487 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3489 return ERROR_INVALID_PRINTER_NAME;
3491 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3492 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3495 * Is this a W2k client ?
3499 free_a_printer(&printer,2);
3500 return ERROR_UNKNOWN_PRINTER_DRIVER;
3503 /* Yes - try again with a WinNT driver. */
3505 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3506 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3508 free_a_printer(&printer,2);
3509 return ERROR_UNKNOWN_PRINTER_DRIVER;
3513 fill_printer_driver_info_6(info, driver, servername);
3515 free_a_printer(&printer,2);
3517 return NT_STATUS_NO_PROBLEMO;
3520 /****************************************************************************
3521 ****************************************************************************/
3523 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3525 safe_free(info->dependentfiles);
3528 /****************************************************************************
3529 ****************************************************************************/
3531 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3533 safe_free(info->dependentfiles);
3537 /****************************************************************************
3538 ****************************************************************************/
3539 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3541 DRIVER_INFO_1 *info=NULL;
3544 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3545 return ERROR_NOT_ENOUGH_MEMORY;
3547 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3548 if (status != NT_STATUS_NO_PROBLEMO) {
3553 /* check the required size. */
3554 *needed += spoolss_size_printer_driver_info_1(info);
3556 if (!alloc_buffer_size(buffer, *needed)) {
3558 return ERROR_INSUFFICIENT_BUFFER;
3561 /* fill the buffer with the structures */
3562 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3567 if (*needed > offered)
3568 return ERROR_INSUFFICIENT_BUFFER;
3570 return NT_STATUS_NO_PROBLEMO;
3573 /****************************************************************************
3574 ****************************************************************************/
3575 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3577 DRIVER_INFO_2 *info=NULL;
3580 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3581 return ERROR_NOT_ENOUGH_MEMORY;
3583 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3584 if (status != NT_STATUS_NO_PROBLEMO) {
3589 /* check the required size. */
3590 *needed += spoolss_size_printer_driver_info_2(info);
3592 if (!alloc_buffer_size(buffer, *needed)) {
3594 return ERROR_INSUFFICIENT_BUFFER;
3597 /* fill the buffer with the structures */
3598 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3603 if (*needed > offered)
3604 return ERROR_INSUFFICIENT_BUFFER;
3606 return NT_STATUS_NO_PROBLEMO;
3609 /****************************************************************************
3610 ****************************************************************************/
3611 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3618 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3619 if (status != NT_STATUS_NO_PROBLEMO) {
3623 /* check the required size. */
3624 *needed += spoolss_size_printer_driver_info_3(&info);
3626 if (!alloc_buffer_size(buffer, *needed)) {
3627 free_printer_driver_info_3(&info);
3628 return ERROR_INSUFFICIENT_BUFFER;
3631 /* fill the buffer with the structures */
3632 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3634 free_printer_driver_info_3(&info);
3636 if (*needed > offered)
3637 return ERROR_INSUFFICIENT_BUFFER;
3639 return NT_STATUS_NO_PROBLEMO;
3642 /****************************************************************************
3643 ****************************************************************************/
3644 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3651 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3652 if (status != NT_STATUS_NO_PROBLEMO) {
3656 /* check the required size. */
3657 *needed += spoolss_size_printer_driver_info_6(&info);
3659 if (!alloc_buffer_size(buffer, *needed)) {
3660 free_printer_driver_info_6(&info);
3661 return ERROR_INSUFFICIENT_BUFFER;
3664 /* fill the buffer with the structures */
3665 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3667 free_printer_driver_info_6(&info);
3669 if (*needed > offered)
3670 return ERROR_INSUFFICIENT_BUFFER;
3672 return NT_STATUS_NO_PROBLEMO;
3675 /****************************************************************************
3676 ****************************************************************************/
3677 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
3678 uint32 clientmajorversion, uint32 clientminorversion,
3679 NEW_BUFFER *buffer, uint32 offered,
3680 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
3683 fstring architecture;
3686 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3689 *servermajorversion=0;
3690 *serverminorversion=0;
3692 pstrcpy(servername, global_myname);
3693 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3695 if (!get_printer_snum(handle, &snum))
3696 return ERROR_INVALID_HANDLE;
3700 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3702 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3704 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3706 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3708 return ERROR_INVALID_LEVEL;
3712 /****************************************************************************
3713 ****************************************************************************/
3714 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
3716 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3718 if (OPEN_HANDLE(Printer)) {
3719 Printer->page_started=True;
3723 DEBUG(3,("Error in startpageprinter printer handle\n"));
3724 return ERROR_INVALID_HANDLE;
3727 /****************************************************************************
3728 ****************************************************************************/
3729 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
3731 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3733 if (!OPEN_HANDLE(Printer)) {
3734 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3735 return ERROR_INVALID_HANDLE;
3738 Printer->page_started=False;
3740 return NT_STATUS_NO_PROBLEMO;
3744 /********************************************************************
3745 * api_spoolss_getprinter
3746 * called from the spoolss dispatcher
3748 ********************************************************************/
3749 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
3750 pipes_struct *p, DOC_INFO *docinfo,
3753 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3757 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3758 struct current_user user;
3760 if (!OPEN_HANDLE(Printer)) {
3761 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3762 return ERROR_INVALID_HANDLE;
3765 get_current_user(&user, p);
3768 * a nice thing with NT is it doesn't listen to what you tell it.
3769 * when asked to send _only_ RAW datas, it tries to send datas
3772 * So I add checks like in NT Server ...
3774 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3775 * there's a bug in NT client-side code, so we'll fix it in the
3776 * server-side code. *nnnnnggggh!*
3779 if (info_1->p_datatype != 0) {
3780 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3781 if (strcmp(datatype, "RAW") != 0) {
3783 return ERROR_INVALID_DATATYPE;
3787 /* get the share number of the printer */
3788 if (!get_printer_snum(handle, &snum)) {
3789 return ERROR_INVALID_HANDLE;
3792 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3794 Printer->jobid = print_job_start(&user, snum, jobname);
3796 /* An error occured in print_job_start() so return an appropriate
3799 if (Printer->jobid == -1) {
3800 return map_nt_error_from_unix(errno);
3803 Printer->document_started=True;
3804 (*jobid) = Printer->jobid;
3809 /********************************************************************
3810 * api_spoolss_getprinter
3811 * called from the spoolss dispatcher
3813 ********************************************************************/
3814 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
3816 Printer_entry *Printer=find_printer_index_by_hnd(handle);
3818 if (!OPEN_HANDLE(Printer)) {
3819 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3820 return ERROR_INVALID_HANDLE;
3823 Printer->document_started=False;
3824 print_job_end(Printer->jobid,True);
3825 /* error codes unhandled so far ... */
3830 /****************************************************************************
3831 ****************************************************************************/
3832 uint32 _spoolss_writeprinter( POLICY_HND *handle,
3835 uint32 *buffer_written)
3837 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3839 if (!OPEN_HANDLE(Printer)) {
3840 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3841 return ERROR_INVALID_HANDLE;
3844 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
3850 /********************************************************************
3851 * api_spoolss_getprinter
3852 * called from the spoolss dispatcher
3854 ********************************************************************/
3855 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3858 struct current_user user;
3859 int snum, errcode = ERROR_INVALID_FUNCTION;
3860 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3862 get_current_user(&user, p);
3864 if (!OPEN_HANDLE(Printer)) {
3865 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3866 return ERROR_INVALID_HANDLE;
3869 if (!get_printer_snum(handle, &snum))
3870 return ERROR_INVALID_HANDLE;
3873 case PRINTER_CONTROL_PAUSE:
3874 if (print_queue_pause(&user, snum, &errcode)) {
3878 case PRINTER_CONTROL_RESUME:
3879 case PRINTER_CONTROL_UNPAUSE:
3880 if (print_queue_resume(&user, snum, &errcode)) {
3884 case PRINTER_CONTROL_PURGE:
3885 if (print_queue_purge(&user, snum, &errcode)) {
3890 return ERROR_INVALID_LEVEL;
3896 /********************************************************************
3897 * api_spoolss_abortprinter
3898 ********************************************************************/
3900 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3902 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3905 /********************************************************************
3906 * called by spoolss_api_setprinter
3907 * when updating a printer description
3908 ********************************************************************/
3909 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3910 const SPOOL_PRINTER_INFO_LEVEL *info,
3911 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3913 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
3914 struct current_user user;
3918 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3920 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3921 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3922 OUR_HANDLE(handle)));
3924 result = ERROR_INVALID_HANDLE;
3928 /* NT seems to like setting the security descriptor even though
3929 nothing may have actually changed. This causes annoying
3930 dialog boxes when the user doesn't have permission to change
3931 the security descriptor. */
3933 nt_printing_getsec(Printer->dev.handlename, &old_secdesc_ctr);
3935 if (DEBUGLEVEL >= 10) {
3939 acl = old_secdesc_ctr->sec->dacl;
3940 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3941 PRINTERNAME(snum), acl->num_aces));
3943 for (i = 0; i < acl->num_aces; i++) {
3946 sid_to_string(sid_str, &acl->ace[i].sid);
3948 DEBUG(10, ("%s 0x%08x\n", sid_str,
3949 acl->ace[i].info.mask));
3952 acl = secdesc_ctr->sec->dacl;
3955 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3956 PRINTERNAME(snum), acl->num_aces));
3958 for (i = 0; i < acl->num_aces; i++) {
3961 sid_to_string(sid_str, &acl->ace[i].sid);
3963 DEBUG(10, ("%s 0x%08x\n", sid_str,
3964 acl->ace[i].info.mask));
3967 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3971 new_secdesc_ctr = sec_desc_merge(secdesc_ctr, old_secdesc_ctr);
3973 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
3974 result = NT_STATUS_NO_PROBLEMO;
3978 /* Work out which user is performing the operation */
3980 get_current_user(&user, p);
3982 /* Check the user has permissions to change the security
3983 descriptor. By experimentation with two NT machines, the user
3984 requires Full Access to the printer to change security
3987 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
3988 result = ERROR_ACCESS_DENIED;
3992 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
3995 free_sec_desc_buf(&new_secdesc_ctr);
3996 free_sec_desc_buf(&old_secdesc_ctr);
4001 /********************************************************************
4002 Do Samba sanity checks on a printer info struct.
4003 this has changed purpose: it now "canonicalises" printer
4004 info from a client rather than just checking it is correct
4005 ********************************************************************/
4007 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4009 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4010 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4012 /* we force some elements to "correct" values */
4013 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4014 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4015 global_myname, lp_servicename(snum));
4016 fstrcpy(info->sharename, lp_servicename(snum));
4017 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4018 | PRINTER_ATTRIBUTE_LOCAL \
4019 | PRINTER_ATTRIBUTE_RAW_ONLY \
4020 | PRINTER_ATTRIBUTE_QUEUED ;
4025 /****************************************************************************
4026 ****************************************************************************/
4027 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4029 pid_t local_pid = sys_getpid();
4030 char *cmd = lp_addprinter_cmd();
4035 pstring driverlocation;
4039 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4040 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4044 /* build driver path... only 9X architecture is needed for legacy reasons */
4045 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4047 /* change \ to \\ for the shell */
4048 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4050 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
4051 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4052 cmd, printer->info_2->printername, printer->info_2->sharename,
4053 printer->info_2->portname, printer->info_2->drivername,
4054 printer->info_2->location, driverlocation);
4058 /* Convert script args to unix-codepage */
4059 dos_to_unix(command, True);
4060 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4061 ret = smbrun(command, tmp_file, False);
4062 DEBUGADD(10,("returned [%d]\n", ret));
4070 /* Get lines and convert them back to dos-codepage */
4071 qlines = file_lines_load(tmp_file, &numlines, True);
4072 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4073 DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
4077 /* Set the portname to what the script says the portname should be. */
4078 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4079 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4081 /* Send SIGHUP to process group... is there a better way? */
4086 file_lines_free(qlines);
4090 /* Return true if two devicemodes are equal */
4092 #define DEVMODE_CHECK_INT(field) \
4093 if (d1->field != d2->field) { \
4094 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4095 d1->field, d2->field)); \
4099 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4101 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4104 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4105 return False; /* if either is exclusively NULL are not equal */
4108 if (!strequal(d1->devicename, d2->devicename)) {
4109 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4113 if (!strequal(d1->formname, d2->formname)) {
4114 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4118 DEVMODE_CHECK_INT(specversion);
4119 DEVMODE_CHECK_INT(driverversion);
4120 DEVMODE_CHECK_INT(driverextra);
4121 DEVMODE_CHECK_INT(orientation);
4122 DEVMODE_CHECK_INT(papersize);
4123 DEVMODE_CHECK_INT(paperlength);
4124 DEVMODE_CHECK_INT(paperwidth);
4125 DEVMODE_CHECK_INT(scale);
4126 DEVMODE_CHECK_INT(copies);
4127 DEVMODE_CHECK_INT(defaultsource);
4128 DEVMODE_CHECK_INT(printquality);
4129 DEVMODE_CHECK_INT(color);
4130 DEVMODE_CHECK_INT(duplex);
4131 DEVMODE_CHECK_INT(yresolution);
4132 DEVMODE_CHECK_INT(ttoption);
4133 DEVMODE_CHECK_INT(collate);
4134 DEVMODE_CHECK_INT(logpixels);
4136 DEVMODE_CHECK_INT(fields);
4137 DEVMODE_CHECK_INT(bitsperpel);
4138 DEVMODE_CHECK_INT(pelswidth);
4139 DEVMODE_CHECK_INT(pelsheight);
4140 DEVMODE_CHECK_INT(displayflags);
4141 DEVMODE_CHECK_INT(displayfrequency);
4142 DEVMODE_CHECK_INT(icmmethod);
4143 DEVMODE_CHECK_INT(icmintent);
4144 DEVMODE_CHECK_INT(mediatype);
4145 DEVMODE_CHECK_INT(dithertype);
4146 DEVMODE_CHECK_INT(reserved1);
4147 DEVMODE_CHECK_INT(reserved2);
4148 DEVMODE_CHECK_INT(panningwidth);
4149 DEVMODE_CHECK_INT(panningheight);
4151 /* compare the private data if it exists */
4152 if (!d1->driverextra && !d2->driverextra) goto equal;
4155 DEVMODE_CHECK_INT(driverextra);
4157 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4158 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4163 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4167 /* Return true if two NT_PRINTER_PARAM structures are equal */
4169 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4170 NT_PRINTER_PARAM *p2)
4172 if (!p1 && !p2) goto equal;
4174 if ((!p1 && p2) || (p1 && !p2)) {
4175 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4179 /* Compare lists of printer parameters */
4183 NT_PRINTER_PARAM *q = p1;
4185 /* Find the parameter in the second structure */
4189 if (strequal(p1->value, q->value)) {
4191 if (p1->type != q->type) {
4192 DEBUG(10, ("nt_printer_param_equal():"
4193 "types for %s differ (%d != %d)\n",
4194 p1->value, p1->type,
4199 if (p1->data_len != q->data_len) {
4200 DEBUG(10, ("nt_printer_param_equal():"
4201 "len for %s differs (%d != %d)\n",
4202 p1->value, p1->data_len,
4207 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4210 DEBUG(10, ("nt_printer_param_equal():"
4211 "data for %s differs\n", p1->value));
4221 DEBUG(10, ("nt_printer_param_equal(): param %s "
4222 "does not exist\n", p1->value));
4231 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4235 /********************************************************************
4236 * Called by update_printer when trying to work out whether to
4237 * actually update printer info.
4238 ********************************************************************/
4240 #define PI_CHECK_INT(field) \
4241 if (pi1->field != pi2->field) { \
4242 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4243 pi1->field, pi2->field)); \
4247 #define PI_CHECK_STR(field) \
4248 if (!strequal(pi1->field, pi2->field)) { \
4249 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4250 pi1->field, pi2->field)); \
4254 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4255 NT_PRINTER_INFO_LEVEL *p2)
4257 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4259 /* Trivial conditions */
4261 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4265 if ((!p1 && p2) || (p1 && !p2) ||
4266 (!p1->info_2 && p2->info_2) ||
4267 (p1->info_2 && !p2->info_2)) {
4268 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4273 /* Compare two nt_printer_info_level structures. Don't compare
4274 status or cjobs as they seem to have something to do with the
4280 /* Don't check the attributes as we stomp on the value in
4281 check_printer_ok() anyway. */
4284 PI_CHECK_INT(attributes);
4287 PI_CHECK_INT(priority);
4288 PI_CHECK_INT(default_priority);
4289 PI_CHECK_INT(starttime);
4290 PI_CHECK_INT(untiltime);
4291 PI_CHECK_INT(averageppm);
4293 /* Yuck - don't check the printername or servername as the
4294 add_a_printer() code plays games with them. You can't
4295 change the printername or the sharename through this interface
4298 PI_CHECK_STR(sharename);
4299 PI_CHECK_STR(portname);
4300 PI_CHECK_STR(drivername);
4301 PI_CHECK_STR(comment);
4302 PI_CHECK_STR(location);
4304 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4308 PI_CHECK_STR(sepfile);
4309 PI_CHECK_STR(printprocessor);
4310 PI_CHECK_STR(datatype);
4311 PI_CHECK_STR(parameters);
4313 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4317 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4321 PI_CHECK_INT(changeid);
4322 PI_CHECK_INT(c_setprinter);
4323 PI_CHECK_INT(setuptime);
4326 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4330 /********************************************************************
4331 * called by spoolss_api_setprinter
4332 * when updating a printer description
4333 ********************************************************************/
4335 static uint32 update_printer(POLICY_HND *handle, uint32 level,
4336 const SPOOL_PRINTER_INFO_LEVEL *info,
4337 DEVICEMODE *devmode)
4340 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4341 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4344 DEBUG(8,("update_printer\n"));
4346 result = NT_STATUS_NO_PROBLEMO;
4349 DEBUG(0,("Send a mail to samba@samba.org\n"));
4350 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4351 result = ERROR_INVALID_LEVEL;
4355 if (!OPEN_HANDLE(Printer)) {
4356 result = ERROR_INVALID_HANDLE;
4360 if (!get_printer_snum(handle, &snum)) {
4361 result = ERROR_INVALID_HANDLE;
4365 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4366 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4367 result = ERROR_INVALID_HANDLE;
4371 DEBUGADD(8,("Converting info_2 struct\n"));
4374 * convert_printer_info converts the incoming
4375 * info from the client and overwrites the info
4376 * just read from the tdb in the pointer 'printer'.
4379 convert_printer_info(info, printer, level);
4381 if (info->info_2->devmode_ptr != 0) {
4382 /* we have a valid devmode
4383 convert it and link it*/
4385 DEBUGADD(8,("Converting the devicemode struct\n"));
4386 if (!convert_devicemode(printer->info_2->printername, devmode,
4387 &printer->info_2->devmode)) {
4388 result = ERROR_NOT_ENOUGH_MEMORY;
4393 /* Do sanity check on the requested changes for Samba */
4395 if (!check_printer_ok(printer->info_2, snum)) {
4396 result = ERROR_INVALID_PARAMETER;
4400 /* NT likes to call this function even though nothing has actually
4401 changed. Check this so the user doesn't end up with an
4402 annoying permission denied dialog box. */
4404 if (nt_printer_info_level_equal(printer, old_printer)) {
4405 DEBUG(3, ("printer info has not changed\n"));
4406 result = NT_STATUS_NO_PROBLEMO;
4410 /* Check calling user has permission to update printer description */
4412 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4413 DEBUG(3, ("printer property change denied by security "
4415 result = ERROR_ACCESS_DENIED;
4419 /* Call addprinter hook */
4421 if (*lp_addprinter_cmd() )
4422 if ( !add_printer_hook(printer) ) {
4423 result = ERROR_ACCESS_DENIED;
4427 /* Update printer info */
4429 if (add_a_printer(*printer, 2)!=0) {
4430 /* I don't really know what to return here !!! */
4431 result = ERROR_ACCESS_DENIED;
4436 free_a_printer(&printer, 2);
4437 free_a_printer(&old_printer, 2);
4439 srv_spoolss_sendnotify(handle);
4444 /****************************************************************************
4445 ****************************************************************************/
4446 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
4447 const SPOOL_PRINTER_INFO_LEVEL *info,
4448 DEVMODE_CTR devmode_ctr,
4449 SEC_DESC_BUF *secdesc_ctr,
4450 uint32 command, pipes_struct *p)
4452 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4454 if (!OPEN_HANDLE(Printer)) {
4455 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4456 return ERROR_INVALID_HANDLE;
4459 /* check the level */
4462 return control_printer(handle, command, p);
4464 return update_printer(handle, level, info, devmode_ctr.devmode);
4466 return update_printer_sec(handle, level, info, p,
4469 return ERROR_INVALID_LEVEL;
4473 /****************************************************************************
4474 ****************************************************************************/
4475 uint32 _spoolss_fcpn(POLICY_HND *handle)
4477 Printer_entry *Printer= find_printer_index_by_hnd(handle);
4479 if (!OPEN_HANDLE(Printer)) {
4480 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4481 return ERROR_INVALID_HANDLE;
4484 if (Printer->notify.client_connected==True)
4485 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4486 return ERROR_INVALID_HANDLE;
4488 Printer->notify.flags=0;
4489 Printer->notify.options=0;
4490 Printer->notify.localmachine[0]='\0';
4491 Printer->notify.printerlocal=0;
4492 if (Printer->notify.option)
4493 safe_free(Printer->notify.option->ctr.type);
4494 safe_free(Printer->notify.option);
4495 Printer->notify.option=NULL;
4496 Printer->notify.client_connected=False;
4498 return NT_STATUS_NO_PROBLEMO;
4501 /****************************************************************************
4502 ****************************************************************************/
4503 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
4504 NEW_BUFFER *buffer, uint32 offered,
4508 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4509 returns for AddJob. AddJob
4510 must fail on non-local
4514 /****************************************************************************
4515 ****************************************************************************/
4516 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4517 int position, int snum)
4523 t=gmtime(&queue->time);
4524 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4526 job_info->jobid=queue->job;
4527 init_unistr(&job_info->printername, lp_servicename(snum));
4528 init_unistr(&job_info->machinename, temp_name);
4529 init_unistr(&job_info->username, queue->user);
4530 init_unistr(&job_info->document, queue->file);
4531 init_unistr(&job_info->datatype, "RAW");
4532 init_unistr(&job_info->text_status, "");
4533 job_info->status=nt_printj_status(queue->status);
4534 job_info->priority=queue->priority;
4535 job_info->position=position;
4536 job_info->totalpages=0;
4537 job_info->pagesprinted=0;
4539 make_systemtime(&job_info->submitted, t);
4542 /****************************************************************************
4543 ****************************************************************************/
4544 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4545 int position, int snum,
4546 NT_PRINTER_INFO_LEVEL *ntprinter)
4552 t=gmtime(&queue->time);
4553 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4555 job_info->jobid=queue->job;
4557 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4559 init_unistr(&job_info->printername, chaine);
4561 init_unistr(&job_info->machinename, temp_name);
4562 init_unistr(&job_info->username, queue->user);
4563 init_unistr(&job_info->document, queue->file);
4564 init_unistr(&job_info->notifyname, queue->user);
4565 init_unistr(&job_info->datatype, "RAW");
4566 init_unistr(&job_info->printprocessor, "winprint");
4567 init_unistr(&job_info->parameters, "");
4568 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4569 init_unistr(&job_info->text_status, "");
4571 /* and here the security descriptor */
4573 job_info->status=nt_printj_status(queue->status);
4574 job_info->priority=queue->priority;
4575 job_info->position=position;
4576 job_info->starttime=0;
4577 job_info->untiltime=0;
4578 job_info->totalpages=0;
4579 job_info->size=queue->size;
4580 make_systemtime(&(job_info->submitted), t);
4581 job_info->timeelapsed=0;
4582 job_info->pagesprinted=0;
4584 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4591 /****************************************************************************
4592 Enumjobs at level 1.
4593 ****************************************************************************/
4594 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4595 NEW_BUFFER *buffer, uint32 offered,
4596 uint32 *needed, uint32 *returned)
4601 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4605 return ERROR_NOT_ENOUGH_MEMORY;
4608 for (i=0; i<*returned; i++)
4609 fill_job_info_1(&info[i], &queue[i], i, snum);
4613 /* check the required size. */
4614 for (i=0; i<*returned; i++)
4615 (*needed) += spoolss_size_job_info_1(&info[i]);
4617 if (!alloc_buffer_size(buffer, *needed)) {
4619 return ERROR_INSUFFICIENT_BUFFER;
4622 /* fill the buffer with the structures */
4623 for (i=0; i<*returned; i++)
4624 new_smb_io_job_info_1("", buffer, &info[i], 0);
4629 if (*needed > offered) {
4631 return ERROR_INSUFFICIENT_BUFFER;
4634 return NT_STATUS_NO_PROBLEMO;
4637 /****************************************************************************
4638 Enumjobs at level 2.
4639 ****************************************************************************/
4640 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4641 NEW_BUFFER *buffer, uint32 offered,
4642 uint32 *needed, uint32 *returned)
4644 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4648 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4651 return ERROR_NOT_ENOUGH_MEMORY;
4654 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4656 return ERROR_NOT_ENOUGH_MEMORY;
4659 for (i=0; i<*returned; i++)
4660 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4662 free_a_printer(&ntprinter, 2);
4665 /* check the required size. */
4666 for (i=0; i<*returned; i++)
4667 (*needed) += spoolss_size_job_info_2(&info[i]);
4669 if (!alloc_buffer_size(buffer, *needed)) {
4671 return ERROR_INSUFFICIENT_BUFFER;
4674 /* fill the buffer with the structures */
4675 for (i=0; i<*returned; i++)
4676 new_smb_io_job_info_2("", buffer, &info[i], 0);
4679 for (i = 0; i < *returned; i++)
4680 free_job_info_2(&info[i]);
4684 if (*needed > offered) {
4686 return ERROR_INSUFFICIENT_BUFFER;
4689 return NT_STATUS_NO_PROBLEMO;
4692 /****************************************************************************
4694 ****************************************************************************/
4695 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
4696 NEW_BUFFER *buffer, uint32 offered,
4697 uint32 *needed, uint32 *returned)
4700 print_queue_struct *queue=NULL;
4701 print_status_struct prt_status;
4703 DEBUG(4,("_spoolss_enumjobs\n"));
4705 ZERO_STRUCT(prt_status);
4710 if (!get_printer_snum(handle, &snum))
4711 return ERROR_INVALID_HANDLE;
4713 *returned = print_queue_status(snum, &queue, &prt_status);
4714 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4716 if (*returned == 0) {
4718 return NT_STATUS_NO_PROBLEMO;
4723 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4725 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4729 return ERROR_INVALID_LEVEL;
4734 /****************************************************************************
4735 ****************************************************************************/
4736 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
4741 /****************************************************************************
4742 ****************************************************************************/
4743 uint32 _spoolss_setjob(POLICY_HND *handle, uint32 jobid, uint32 level,
4744 pipes_struct *p, JOB_INFO *ctr, uint32 command)
4746 struct current_user user;
4747 print_status_struct prt_status;
4748 int snum, errcode = ERROR_INVALID_FUNCTION;
4750 memset(&prt_status, 0, sizeof(prt_status));
4752 if (!get_printer_snum(handle, &snum)) {
4753 return ERROR_INVALID_HANDLE;
4756 if (!print_job_exists(jobid)) {
4757 return ERROR_INVALID_PRINTER_NAME;
4760 get_current_user(&user, p);
4763 case JOB_CONTROL_CANCEL:
4764 case JOB_CONTROL_DELETE:
4765 if (print_job_delete(&user, jobid, &errcode)) {
4769 case JOB_CONTROL_PAUSE:
4770 if (print_job_pause(&user, jobid, &errcode)) {
4774 case JOB_CONTROL_RESTART:
4775 case JOB_CONTROL_RESUME:
4776 if (print_job_resume(&user, jobid, &errcode)) {
4781 return ERROR_INVALID_LEVEL;
4787 /****************************************************************************
4788 Enumerates all printer drivers at level 1.
4789 ****************************************************************************/
4790 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4795 fstring *list = NULL;
4797 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4798 DRIVER_INFO_1 *driver_info_1=NULL;
4802 #define MAX_VERSION 4
4804 for (version=0; version<MAX_VERSION; version++) {
4806 ndrivers=get_ntdrivers(&list, architecture, version);
4807 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4810 return ERROR_NOT_ENOUGH_MEMORY;
4813 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4815 return ERROR_NOT_ENOUGH_MEMORY;
4819 for (i=0; i<ndrivers; i++) {
4821 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4822 ZERO_STRUCT(driver);
4823 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4827 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4828 free_a_printer_driver(driver, 3);
4831 *returned+=ndrivers;
4835 /* check the required size. */
4836 for (i=0; i<*returned; i++) {
4837 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4838 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4841 if (!alloc_buffer_size(buffer, *needed)) {
4842 safe_free(driver_info_1);
4843 return ERROR_INSUFFICIENT_BUFFER;
4846 /* fill the buffer with the form structures */
4847 for (i=0; i<*returned; i++) {
4848 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4849 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4852 safe_free(driver_info_1);
4854 if (*needed > offered) {
4856 return ERROR_INSUFFICIENT_BUFFER;
4859 return NT_STATUS_NO_PROBLEMO;
4862 /****************************************************************************
4863 Enumerates all printer drivers at level 2.
4864 ****************************************************************************/
4865 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4870 fstring *list = NULL;
4872 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4873 DRIVER_INFO_2 *driver_info_2=NULL;
4877 #define MAX_VERSION 4
4879 for (version=0; version<MAX_VERSION; version++) {
4881 ndrivers=get_ntdrivers(&list, architecture, version);
4882 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4885 return ERROR_NOT_ENOUGH_MEMORY;
4888 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
4890 return ERROR_NOT_ENOUGH_MEMORY;
4894 for (i=0; i<ndrivers; i++) {
4897 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4898 ZERO_STRUCT(driver);
4899 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4903 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
4904 free_a_printer_driver(driver, 3);
4907 *returned+=ndrivers;
4911 /* check the required size. */
4912 for (i=0; i<*returned; i++) {
4913 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4914 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
4917 if (!alloc_buffer_size(buffer, *needed)) {
4918 safe_free(driver_info_2);
4919 return ERROR_INSUFFICIENT_BUFFER;
4922 /* fill the buffer with the form structures */
4923 for (i=0; i<*returned; i++) {
4924 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4925 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
4928 safe_free(driver_info_2);
4930 if (*needed > offered) {
4932 return ERROR_INSUFFICIENT_BUFFER;
4935 return NT_STATUS_NO_PROBLEMO;
4938 /****************************************************************************
4939 Enumerates all printer drivers at level 3.
4940 ****************************************************************************/
4941 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4946 fstring *list = NULL;
4948 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4949 DRIVER_INFO_3 *driver_info_3=NULL;
4953 #define MAX_VERSION 4
4955 for (version=0; version<MAX_VERSION; version++) {
4957 ndrivers=get_ntdrivers(&list, architecture, version);
4958 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4961 return ERROR_NOT_ENOUGH_MEMORY;
4964 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
4966 return ERROR_NOT_ENOUGH_MEMORY;
4970 for (i=0; i<ndrivers; i++) {
4973 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4974 ZERO_STRUCT(driver);
4975 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4979 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
4980 free_a_printer_driver(driver, 3);
4983 *returned+=ndrivers;
4987 /* check the required size. */
4988 for (i=0; i<*returned; i++) {
4989 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4990 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
4993 if (!alloc_buffer_size(buffer, *needed)) {
4994 safe_free(driver_info_3);
4995 return ERROR_INSUFFICIENT_BUFFER;
4998 /* fill the buffer with the driver structures */
4999 for (i=0; i<*returned; i++) {
5000 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5001 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5004 for (i=0; i<*returned; i++)
5005 safe_free(driver_info_3[i].dependentfiles);
5007 safe_free(driver_info_3);
5009 if (*needed > offered) {
5011 return ERROR_INSUFFICIENT_BUFFER;
5014 return NT_STATUS_NO_PROBLEMO;
5017 /****************************************************************************
5018 Enumerates all printer drivers.
5019 ****************************************************************************/
5020 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
5021 NEW_BUFFER *buffer, uint32 offered,
5022 uint32 *needed, uint32 *returned)
5024 fstring *list = NULL;
5026 fstring architecture;
5028 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5029 fstrcpy(servername, global_myname);
5033 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5037 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5039 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5041 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5045 return ERROR_INVALID_LEVEL;
5049 /****************************************************************************
5050 ****************************************************************************/
5051 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5053 form->flag=list->flag;
5054 init_unistr(&form->name, list->name);
5055 form->width=list->width;
5056 form->length=list->length;
5057 form->left=list->left;
5058 form->top=list->top;
5059 form->right=list->right;
5060 form->bottom=list->bottom;
5063 /****************************************************************************
5064 ****************************************************************************/
5065 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
5066 NEW_BUFFER *buffer, uint32 offered,
5067 uint32 *needed, uint32 *numofforms)
5069 nt_forms_struct *list=NULL;
5074 DEBUG(4,("_new_spoolss_enumforms\n"));
5075 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5076 DEBUGADD(5,("Info level [%d]\n", level));
5078 *numofforms = get_ntforms(&list);
5079 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
5081 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
5085 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5087 return ERROR_NOT_ENOUGH_MEMORY;
5090 /* construct the list of form structures */
5091 for (i=0; i<*numofforms; i++) {
5092 DEBUGADD(6,("Filling form number [%d]\n",i));
5093 fill_form_1(&forms_1[i], &list[i]);
5098 /* check the required size. */
5099 for (i=0; i<*numofforms; i++) {
5100 DEBUGADD(6,("adding form [%d]'s size\n",i));
5101 buffer_size += spoolss_size_form_1(&forms_1[i]);
5104 *needed=buffer_size;
5106 if (!alloc_buffer_size(buffer, buffer_size)){
5108 return ERROR_INSUFFICIENT_BUFFER;
5111 /* fill the buffer with the form structures */
5112 for (i=0; i<*numofforms; i++) {
5113 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5114 new_smb_io_form_1("", buffer, &forms_1[i], 0);
5119 if (*needed > offered) {
5121 return ERROR_INSUFFICIENT_BUFFER;
5124 return NT_STATUS_NO_PROBLEMO;
5128 return ERROR_INVALID_LEVEL;
5133 /****************************************************************************
5134 ****************************************************************************/
5135 uint32 _spoolss_getform( POLICY_HND *handle, uint32 level, UNISTR2 *uni_formname, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5137 nt_forms_struct *list=NULL;
5143 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5145 DEBUG(4,("_spoolss_getform\n"));
5146 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5147 DEBUGADD(5,("Info level [%d]\n", level));
5149 numofforms = get_ntforms(&list);
5150 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5152 if (numofforms == 0)
5153 return ERROR_NO_MORE_ITEMS;
5158 /* Check if the requested name is in the list of form structures */
5159 for (i=0; i<numofforms; i++) {
5161 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5163 if (strequal(form_name, list[i].name)) {
5164 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5165 fill_form_1(&form_1, &list[i]);
5172 /* check the required size. */
5174 *needed=spoolss_size_form_1(&form_1);
5176 if (!alloc_buffer_size(buffer, buffer_size)){
5177 return ERROR_INSUFFICIENT_BUFFER;
5180 if (*needed > offered) {
5181 return ERROR_INSUFFICIENT_BUFFER;
5184 /* fill the buffer with the form structures */
5185 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5186 new_smb_io_form_1("", buffer, &form_1, 0);
5188 return NT_STATUS_NO_PROBLEMO;
5192 return ERROR_INVALID_LEVEL;
5196 /****************************************************************************
5197 ****************************************************************************/
5198 static void fill_port_1(PORT_INFO_1 *port, char *name)
5200 init_unistr(&port->port_name, name);
5203 /****************************************************************************
5204 ****************************************************************************/
5205 static void fill_port_2(PORT_INFO_2 *port, char *name)
5207 init_unistr(&port->port_name, name);
5208 init_unistr(&port->monitor_name, "Local Monitor");
5209 init_unistr(&port->description, "Local Port");
5210 #define PORT_TYPE_WRITE 1
5211 port->port_type=PORT_TYPE_WRITE;
5215 /****************************************************************************
5217 ****************************************************************************/
5218 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5220 PORT_INFO_1 *ports=NULL;
5223 if (*lp_enumports_cmd()) {
5224 pid_t local_pid = sys_getpid();
5225 char *cmd = lp_enumports_cmd();
5233 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5234 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5238 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5239 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5242 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5243 ret = smbrun(command, tmp_file, False);
5244 DEBUG(10,("Returned [%d]\n", ret));
5247 /* Is this the best error to return here? */
5248 return ERROR_ACCESS_DENIED;
5252 qlines = file_lines_load(tmp_file, &numlines,True);
5253 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5254 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5258 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5259 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5260 file_lines_free(qlines);
5261 return ERROR_NOT_ENOUGH_MEMORY;
5264 for (i=0; i<numlines; i++) {
5265 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5266 fill_port_1(&ports[i], qlines[i]);
5269 file_lines_free(qlines);
5272 *returned = numlines;
5275 *returned = 1; /* Sole Samba port returned. */
5277 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5278 return ERROR_NOT_ENOUGH_MEMORY;
5280 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5282 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5285 /* check the required size. */
5286 for (i=0; i<*returned; i++) {
5287 DEBUGADD(6,("adding port [%d]'s size\n", i));
5288 *needed += spoolss_size_port_info_1(&ports[i]);
5291 if (!alloc_buffer_size(buffer, *needed)) {
5293 return ERROR_INSUFFICIENT_BUFFER;
5296 /* fill the buffer with the ports structures */
5297 for (i=0; i<*returned; i++) {
5298 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5299 new_smb_io_port_1("", buffer, &ports[i], 0);
5304 if (*needed > offered) {
5306 return ERROR_INSUFFICIENT_BUFFER;
5309 return NT_STATUS_NO_PROBLEMO;
5312 /****************************************************************************
5314 ****************************************************************************/
5316 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5318 PORT_INFO_2 *ports=NULL;
5321 if (*lp_enumports_cmd()) {
5322 pid_t local_pid = sys_getpid();
5323 char *cmd = lp_enumports_cmd();
5331 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5332 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5336 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5337 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5340 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5341 ret = smbrun(command, tmp_file, False);
5342 DEBUGADD(10,("returned [%d]\n", ret));
5345 /* Is this the best error to return here? */
5346 return ERROR_ACCESS_DENIED;
5350 qlines = file_lines_load(tmp_file, &numlines,True);
5351 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5352 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5356 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5357 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5358 file_lines_free(qlines);
5359 return ERROR_NOT_ENOUGH_MEMORY;
5362 for (i=0; i<numlines; i++) {
5363 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5364 fill_port_2(&(ports[i]), qlines[i]);
5367 file_lines_free(qlines);
5370 *returned = numlines;
5376 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5377 return ERROR_NOT_ENOUGH_MEMORY;
5379 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5381 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5384 /* check the required size. */
5385 for (i=0; i<*returned; i++) {
5386 DEBUGADD(6,("adding port [%d]'s size\n", i));
5387 *needed += spoolss_size_port_info_2(&ports[i]);
5390 if (!alloc_buffer_size(buffer, *needed)) {
5392 return ERROR_INSUFFICIENT_BUFFER;
5395 /* fill the buffer with the ports structures */
5396 for (i=0; i<*returned; i++) {
5397 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5398 new_smb_io_port_2("", buffer, &ports[i], 0);
5403 if (*needed > offered) {
5405 return ERROR_INSUFFICIENT_BUFFER;
5408 return NT_STATUS_NO_PROBLEMO;
5411 /****************************************************************************
5413 ****************************************************************************/
5414 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
5415 NEW_BUFFER *buffer, uint32 offered,
5416 uint32 *needed, uint32 *returned)
5418 DEBUG(4,("_spoolss_enumports\n"));
5425 return enumports_level_1(buffer, offered, needed, returned);
5427 return enumports_level_2(buffer, offered, needed, returned);
5429 return ERROR_INVALID_LEVEL;
5433 /****************************************************************************
5434 ****************************************************************************/
5435 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5436 const SPOOL_PRINTER_INFO_LEVEL *info,
5437 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5438 uint32 user_switch, const SPOOL_USER_CTR *user,
5441 NT_PRINTER_INFO_LEVEL *printer = NULL;
5445 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5446 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5447 return ERROR_NOT_ENOUGH_MEMORY;
5450 ZERO_STRUCTP(printer);
5452 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5453 convert_printer_info(info, printer, 2);
5455 if (*lp_addprinter_cmd() )
5456 if ( !add_printer_hook(printer) ) {
5457 free_a_printer(&printer,2);
5458 return ERROR_ACCESS_DENIED;
5461 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5462 printer->info_2->sharename);
5464 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5465 free_a_printer(&printer,2);
5466 return ERROR_ACCESS_DENIED;
5469 /* you must be a printer admin to add a new printer */
5470 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5471 free_a_printer(&printer,2);
5472 return ERROR_ACCESS_DENIED;
5476 * Do sanity check on the requested changes for Samba.
5479 if (!check_printer_ok(printer->info_2, snum)) {
5480 free_a_printer(&printer,2);
5481 return ERROR_INVALID_PARAMETER;
5484 /* write the ASCII on disk */
5485 if (add_a_printer(*printer, 2) != 0) {
5486 free_a_printer(&printer,2);
5487 return ERROR_ACCESS_DENIED;
5490 if (!open_printer_hnd(handle, name)) {
5491 /* Handle open failed - remove addition. */
5492 del_a_printer(printer->info_2->sharename);
5493 free_a_printer(&printer,2);
5494 return ERROR_ACCESS_DENIED;
5497 free_a_printer(&printer,2);
5499 srv_spoolss_sendnotify(handle);
5501 return NT_STATUS_NO_PROBLEMO;
5504 /****************************************************************************
5505 ****************************************************************************/
5506 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
5507 const SPOOL_PRINTER_INFO_LEVEL *info,
5508 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5509 uint32 user_switch, const SPOOL_USER_CTR *user,
5514 /* we don't handle yet */
5515 /* but I know what to do ... */
5516 return ERROR_INVALID_LEVEL;
5518 return spoolss_addprinterex_level_2(uni_srv_name, info,
5519 unk0, unk1, unk2, unk3,
5520 user_switch, user, handle);
5522 return ERROR_INVALID_LEVEL;
5526 /****************************************************************************
5527 ****************************************************************************/
5528 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
5529 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
5531 uint32 err = NT_STATUS_NO_PROBLEMO;
5532 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5533 struct current_user user;
5535 ZERO_STRUCT(driver);
5537 get_current_user(&user, p);
5539 convert_printer_driver_info(info, &driver, level);
5541 DEBUG(5,("Cleaning driver's information\n"));
5542 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5545 DEBUG(5,("Moving driver to final destination\n"));
5546 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5548 err = ERROR_ACCESS_DENIED;
5552 if (add_a_printer_driver(driver, level)!=0) {
5553 err = ERROR_ACCESS_DENIED;
5558 free_a_printer_driver(driver, level);
5562 /****************************************************************************
5563 ****************************************************************************/
5564 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5566 init_unistr(&info->name, name);
5569 /****************************************************************************
5570 ****************************************************************************/
5571 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5575 pstring short_archi;
5576 DRIVER_DIRECTORY_1 *info=NULL;
5578 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5580 if (get_short_archi(short_archi, long_archi)==FALSE)
5581 return ERROR_INVALID_ENVIRONMENT;
5583 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5584 return ERROR_NOT_ENOUGH_MEMORY;
5586 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5588 DEBUG(4,("printer driver directory: [%s]\n", path));
5590 fill_driverdir_1(info, path);
5592 *needed += spoolss_size_driverdir_info_1(info);
5594 if (!alloc_buffer_size(buffer, *needed)) {
5596 return ERROR_INSUFFICIENT_BUFFER;
5599 new_smb_io_driverdir_1("", buffer, info, 0);
5603 if (*needed > offered)
5604 return ERROR_INSUFFICIENT_BUFFER;
5606 return NT_STATUS_NO_PROBLEMO;
5609 /****************************************************************************
5610 ****************************************************************************/
5611 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
5612 NEW_BUFFER *buffer, uint32 offered,
5615 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5621 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5623 return ERROR_INVALID_LEVEL;
5627 /****************************************************************************
5628 ****************************************************************************/
5629 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
5630 uint32 in_value_len, uint32 in_data_len,
5631 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
5633 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
5635 NT_PRINTER_INFO_LEVEL *printer = NULL;
5640 uint32 biggest_valuesize;
5641 uint32 biggest_datasize;
5643 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5648 ZERO_STRUCT(printer);
5650 *out_max_value_len=0;
5656 *out_max_data_len=0;
5660 DEBUG(5,("spoolss_enumprinterdata\n"));
5662 if (!OPEN_HANDLE(Printer)) {
5663 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5664 return ERROR_INVALID_HANDLE;
5667 if (!get_printer_snum(handle, &snum))
5668 return ERROR_INVALID_HANDLE;
5670 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5671 return ERROR_INVALID_HANDLE;
5674 * The NT machine wants to know the biggest size of value and data
5676 * cf: MSDN EnumPrinterData remark section
5678 if ( (in_value_len==0) && (in_data_len==0) ) {
5679 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5683 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5684 * if this parameter size doesn't exist.
5685 * Ok - my opinion here is that the client is not asking for the greatest
5686 * possible size of all the parameters, but is asking specifically for the size needed
5687 * for this specific parameter. In that case we can remove the loop below and
5688 * simplify this lookup code considerably. JF - comments welcome. JRA.
5691 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5693 free_a_printer(&printer, 2);
5694 return ERROR_NO_MORE_ITEMS;
5702 biggest_valuesize=0;
5705 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5706 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5707 if (data_len > biggest_datasize) biggest_datasize=data_len;
5709 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5717 * I think this is correct, it doesn't break APW and
5718 * allows Gerald's Win32 test programs to work correctly,
5719 * but may need altering.... JRA.
5722 if (param_index == 0) {
5723 /* No parameters found. */
5724 free_a_printer(&printer, 2);
5725 return ERROR_NO_MORE_ITEMS;
5728 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5729 *out_value_len=2*(1+biggest_valuesize);
5730 *out_data_len=biggest_datasize;
5732 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5734 free_a_printer(&printer, 2);
5735 return NT_STATUS_NO_PROBLEMO;
5739 * the value len is wrong in NT sp3
5740 * that's the number of bytes not the number of unicode chars
5743 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5745 free_a_printer(&printer, 2);
5746 return ERROR_NO_MORE_ITEMS;
5749 free_a_printer(&printer, 2);
5753 * - counted in bytes in the request
5754 * - counted in UNICODE chars in the max reply
5755 * - counted in bytes in the real size
5757 * take a pause *before* coding not *during* coding
5760 *out_max_value_len=(in_value_len/sizeof(uint16));
5761 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
5763 return ERROR_NOT_ENOUGH_MEMORY;
5766 ZERO_STRUCTP(*out_value);
5767 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
5771 /* the data is counted in bytes */
5772 *out_max_data_len=in_data_len;
5773 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
5775 return ERROR_NOT_ENOUGH_MEMORY;
5778 memset(*data_out,'\0',in_data_len);
5779 memcpy(*data_out, data, (size_t)data_len);
5780 *out_data_len=data_len;
5784 return NT_STATUS_NO_PROBLEMO;
5787 /****************************************************************************
5788 ****************************************************************************/
5789 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
5790 const UNISTR2 *value,
5795 uint32 numeric_data)
5797 NT_PRINTER_INFO_LEVEL *printer = NULL;
5798 NT_PRINTER_PARAM *param = NULL, old_param;
5800 uint32 status = 0x0;
5801 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5803 DEBUG(5,("spoolss_setprinterdata\n"));
5805 if (!OPEN_HANDLE(Printer)) {
5806 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5807 return ERROR_INVALID_HANDLE;
5810 if (!get_printer_snum(handle, &snum))
5811 return ERROR_INVALID_HANDLE;
5813 status = get_a_printer(&printer, 2, lp_servicename(snum));
5815 return ERROR_INVALID_NAME;
5817 convert_specific_param(¶m, value , type, data, real_len);
5819 /* Check if we are making any changes or not. Return true if
5820 nothing is actually changing. */
5822 ZERO_STRUCT(old_param);
5824 if (get_specific_param(*printer, 2, param->value, &old_param.data,
5825 &old_param.type, (unsigned int *)&old_param.data_len)) {
5827 if (param->type == old_param.type &&
5828 param->data_len == old_param.data_len &&
5829 memcmp(param->data, old_param.data,
5830 old_param.data_len) == 0) {
5832 DEBUG(3, ("setprinterdata hasn't changed\n"));
5833 status = NT_STATUS_NO_PROBLEMO;
5840 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5841 DEBUG(3, ("security descriptor change denied by existing "
5842 "security descriptor\n"));
5843 status = ERROR_ACCESS_DENIED;
5847 unlink_specific_param_if_exist(printer->info_2, param);
5849 add_a_specific_param(printer->info_2, ¶m);
5850 status = mod_a_printer(*printer, 2);
5853 free_a_printer(&printer, 2);
5855 free_nt_printer_param(¶m);
5856 safe_free(old_param.data);
5861 /****************************************************************************
5862 ****************************************************************************/
5863 uint32 _spoolss_deleteprinterdata( POLICY_HND *handle, const UNISTR2 *value)
5865 NT_PRINTER_INFO_LEVEL *printer = NULL;
5866 NT_PRINTER_PARAM param;
5868 uint32 status = 0x0;
5869 Printer_entry *Printer=find_printer_index_by_hnd(handle);
5871 DEBUG(5,("spoolss_deleteprinterdata\n"));
5873 if (!OPEN_HANDLE(Printer)) {
5874 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5875 return ERROR_INVALID_HANDLE;
5878 if (!get_printer_snum(handle, &snum))
5879 return ERROR_INVALID_HANDLE;
5881 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5882 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
5883 "change denied by existing security descriptor\n"));
5884 return ERROR_ACCESS_DENIED;
5887 status = get_a_printer(&printer, 2, lp_servicename(snum));
5889 return ERROR_INVALID_NAME;
5891 ZERO_STRUCTP(¶m);
5892 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
5894 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
5895 status = ERROR_INVALID_PARAMETER;
5897 status = mod_a_printer(*printer, 2);
5899 free_a_printer(&printer, 2);
5903 /****************************************************************************
5904 ****************************************************************************/
5905 uint32 _spoolss_addform( POLICY_HND *handle,
5910 nt_forms_struct *list=NULL;
5911 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5913 DEBUG(5,("spoolss_addform\n"));
5915 if (!OPEN_HANDLE(Printer)) {
5916 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5917 return ERROR_INVALID_HANDLE;
5920 count=get_ntforms(&list);
5921 if(!add_a_form(&list, form, &count))
5922 return ERROR_NOT_ENOUGH_MEMORY;
5923 write_ntforms(&list, count);
5930 /****************************************************************************
5931 ****************************************************************************/
5932 uint32 _spoolss_deleteform( POLICY_HND *handle, UNISTR2 *form_name)
5936 nt_forms_struct *list=NULL;
5937 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5939 DEBUG(5,("spoolss_deleteform\n"));
5941 if (!OPEN_HANDLE(Printer)) {
5942 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5943 return ERROR_INVALID_HANDLE;
5946 count = get_ntforms(&list);
5947 if(!delete_a_form(&list, form_name, &count, &ret))
5948 return ERROR_INVALID_PARAMETER;
5955 /****************************************************************************
5956 ****************************************************************************/
5957 uint32 _spoolss_setform( POLICY_HND *handle,
5958 const UNISTR2 *uni_name,
5963 nt_forms_struct *list=NULL;
5964 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5966 DEBUG(5,("spoolss_setform\n"));
5968 if (!OPEN_HANDLE(Printer)) {
5969 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5970 return ERROR_INVALID_HANDLE;
5972 count=get_ntforms(&list);
5973 update_a_form(&list, form, count);
5974 write_ntforms(&list, count);
5981 /****************************************************************************
5982 enumprintprocessors level 1.
5983 ****************************************************************************/
5984 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5986 PRINTPROCESSOR_1 *info_1=NULL;
5988 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
5989 return ERROR_NOT_ENOUGH_MEMORY;
5993 init_unistr(&info_1->name, "winprint");
5995 *needed += spoolss_size_printprocessor_info_1(info_1);
5997 if (!alloc_buffer_size(buffer, *needed))
5998 return ERROR_INSUFFICIENT_BUFFER;
6000 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6004 if (*needed > offered) {
6006 return ERROR_INSUFFICIENT_BUFFER;
6009 return NT_STATUS_NO_PROBLEMO;
6012 /****************************************************************************
6013 ****************************************************************************/
6014 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
6015 NEW_BUFFER *buffer, uint32 offered,
6016 uint32 *needed, uint32 *returned)
6018 DEBUG(5,("spoolss_enumprintprocessors\n"));
6021 * Enumerate the print processors ...
6023 * Just reply with "winprint", to keep NT happy
6024 * and I can use my nice printer checker.
6032 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6034 return ERROR_INVALID_LEVEL;
6038 /****************************************************************************
6039 enumprintprocdatatypes level 1.
6040 ****************************************************************************/
6041 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6043 PRINTPROCDATATYPE_1 *info_1=NULL;
6045 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6046 return ERROR_NOT_ENOUGH_MEMORY;
6050 init_unistr(&info_1->name, "RAW");
6052 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6054 if (!alloc_buffer_size(buffer, *needed))
6055 return ERROR_INSUFFICIENT_BUFFER;
6057 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6061 if (*needed > offered) {
6063 return ERROR_INSUFFICIENT_BUFFER;
6066 return NT_STATUS_NO_PROBLEMO;
6069 /****************************************************************************
6070 ****************************************************************************/
6071 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
6072 NEW_BUFFER *buffer, uint32 offered,
6073 uint32 *needed, uint32 *returned)
6075 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6082 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6084 return ERROR_INVALID_LEVEL;
6088 /****************************************************************************
6089 enumprintmonitors level 1.
6090 ****************************************************************************/
6091 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6093 PRINTMONITOR_1 *info_1=NULL;
6095 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6096 return ERROR_NOT_ENOUGH_MEMORY;
6100 init_unistr(&info_1->name, "Local Port");
6102 *needed += spoolss_size_printmonitor_info_1(info_1);
6104 if (!alloc_buffer_size(buffer, *needed))
6105 return ERROR_INSUFFICIENT_BUFFER;
6107 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6111 if (*needed > offered) {
6113 return ERROR_INSUFFICIENT_BUFFER;
6116 return NT_STATUS_NO_PROBLEMO;
6119 /****************************************************************************
6120 enumprintmonitors level 2.
6121 ****************************************************************************/
6122 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6124 PRINTMONITOR_2 *info_2=NULL;
6126 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6127 return ERROR_NOT_ENOUGH_MEMORY;
6131 init_unistr(&info_2->name, "Local Port");
6132 init_unistr(&info_2->environment, "Windows NT X86");
6133 init_unistr(&info_2->dll_name, "localmon.dll");
6135 *needed += spoolss_size_printmonitor_info_2(info_2);
6137 if (!alloc_buffer_size(buffer, *needed))
6138 return ERROR_INSUFFICIENT_BUFFER;
6140 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6144 if (*needed > offered) {
6146 return ERROR_INSUFFICIENT_BUFFER;
6149 return NT_STATUS_NO_PROBLEMO;
6152 /****************************************************************************
6153 ****************************************************************************/
6154 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
6155 NEW_BUFFER *buffer, uint32 offered,
6156 uint32 *needed, uint32 *returned)
6158 DEBUG(5,("spoolss_enumprintmonitors\n"));
6161 * Enumerate the print monitors ...
6163 * Just reply with "Local Port", to keep NT happy
6164 * and I can use my nice printer checker.
6172 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6174 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6176 return ERROR_INVALID_LEVEL;
6180 /****************************************************************************
6181 ****************************************************************************/
6182 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6186 JOB_INFO_1 *info_1=NULL;
6188 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6190 if (info_1 == NULL) {
6192 return ERROR_NOT_ENOUGH_MEMORY;
6195 for (i=0; i<count && found==False; i++) {
6196 if (queue[i].job==(int)jobid)
6203 /* I shoud reply something else ... I can't find the good one */
6204 return NT_STATUS_NO_PROBLEMO;
6207 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6211 *needed += spoolss_size_job_info_1(info_1);
6213 if (!alloc_buffer_size(buffer, *needed)) {
6215 return ERROR_INSUFFICIENT_BUFFER;
6218 new_smb_io_job_info_1("", buffer, info_1, 0);
6222 if (*needed > offered)
6223 return ERROR_INSUFFICIENT_BUFFER;
6225 return NT_STATUS_NO_PROBLEMO;
6229 /****************************************************************************
6230 ****************************************************************************/
6231 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6236 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6238 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6240 ZERO_STRUCTP(info_2);
6242 if (info_2 == NULL) {
6244 return ERROR_NOT_ENOUGH_MEMORY;
6247 for (i=0; i<count && found==False; i++) {
6248 if (queue[i].job==(int)jobid)
6255 /* I shoud reply something else ... I can't find the good one */
6256 return NT_STATUS_NO_PROBLEMO;
6259 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6261 return ERROR_NOT_ENOUGH_MEMORY;
6264 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6266 free_a_printer(&ntprinter, 2);
6269 *needed += spoolss_size_job_info_2(info_2);
6271 if (!alloc_buffer_size(buffer, *needed)) {
6273 return ERROR_INSUFFICIENT_BUFFER;
6276 new_smb_io_job_info_2("", buffer, info_2, 0);
6278 free_job_info_2(info_2);
6281 if (*needed > offered)
6282 return ERROR_INSUFFICIENT_BUFFER;
6284 return NT_STATUS_NO_PROBLEMO;
6287 /****************************************************************************
6288 ****************************************************************************/
6289 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
6290 NEW_BUFFER *buffer, uint32 offered,
6295 print_queue_struct *queue=NULL;
6296 print_status_struct prt_status;
6298 DEBUG(5,("spoolss_getjob\n"));
6300 memset(&prt_status, 0, sizeof(prt_status));
6304 if (!get_printer_snum(handle, &snum))
6305 return ERROR_INVALID_HANDLE;
6307 count = print_queue_status(snum, &queue, &prt_status);
6309 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6310 count, prt_status.status, prt_status.message));
6314 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6316 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6319 return ERROR_INVALID_LEVEL;