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.
9 * Copyright (C) Jeremy Allison 2001.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 extern int DEBUGLEVEL;
29 extern pstring global_myname;
31 #ifndef MAX_OPEN_PRINTER_EXS
32 #define MAX_OPEN_PRINTER_EXS 50
35 #define PRINTER_HANDLE_IS_PRINTER 0
36 #define PRINTER_HANDLE_IS_PRINTSERVER 1
38 /* structure to store the printer handles */
39 /* and a reference to what it's pointing to */
40 /* and the notify info asked about */
41 /* that's the central struct */
42 typedef struct _Printer{
47 BOOL document_started;
49 int jobid; /* jobid in printing backend */
50 POLICY_HND printer_hnd;
54 fstring printerservername;
63 SPOOL_NOTIFY_OPTION *option;
64 POLICY_HND client_hnd;
65 uint32 client_connected;
73 typedef struct _counter_printer_0 {
81 static ubi_dlList Printer_list;
82 static ubi_dlList counter_list;
84 static struct cli_state cli;
85 static uint32 smb_connections=0;
87 #define OPEN_HANDLE(pnum) ((pnum!=NULL) && (pnum->open!=False) && (IVAL(pnum->printer_hnd.data,16)==(uint32)sys_getpid()))
88 #define OUR_HANDLE(pnum) ((pnum==NULL)?"NULL":(IVAL(pnum->data,16)==sys_getpid()?"OURS":"OTHER"))
90 /* translate between internal status numbers and NT status numbers */
91 static int nt_printj_status(int v)
97 return JOB_STATUS_PAUSED;
99 return JOB_STATUS_SPOOLING;
101 return JOB_STATUS_PRINTING;
103 return JOB_STATUS_ERROR;
105 return JOB_STATUS_DELETING;
107 return JOB_STATUS_OFFLINE;
109 return JOB_STATUS_PAPEROUT;
111 return JOB_STATUS_PRINTED;
113 return JOB_STATUS_DELETED;
115 return JOB_STATUS_BLOCKED;
116 case LPQ_USER_INTERVENTION:
117 return JOB_STATUS_USER_INTERVENTION;
122 static int nt_printq_status(int v)
126 return PRINTER_STATUS_PAUSED;
135 /****************************************************************************
136 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
137 ****************************************************************************/
139 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
141 SPOOL_NOTIFY_OPTION *sp = *pp;
149 safe_free(sp->ctr.type);
155 /****************************************************************************
156 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
157 ****************************************************************************/
159 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
161 SPOOL_NOTIFY_OPTION *new_sp = NULL;
166 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
173 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
175 if (!new_sp->ctr.type) {
184 /****************************************************************************
185 initialise printer handle states...
186 ****************************************************************************/
187 void init_printer_hnd(void)
189 ubi_dlInitList(&Printer_list);
190 ubi_dlInitList(&counter_list);
193 /****************************************************************************
194 Return a user struct for a pipe user.
195 ****************************************************************************/
197 static struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
199 if (p->ntlmssp_auth_validated) {
200 memcpy(user, &p->pipe_user, sizeof(struct current_user));
202 extern struct current_user current_user;
203 memcpy(user, ¤t_user, sizeof(struct current_user));
209 /****************************************************************************
210 create a unique printer handle
211 ****************************************************************************/
212 static void create_printer_hnd(POLICY_HND *hnd)
214 static uint32 prt_hnd_low = 0;
215 static uint32 prt_hnd_high = 0;
217 if (hnd == NULL) return;
219 /* i severely doubt that prt_hnd_high will ever be non-zero... */
221 if (prt_hnd_low == 0) prt_hnd_high++;
223 SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */
224 SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */
225 SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */
226 SIVAL(hnd->data, 12, time(NULL)); /* something random */
227 SIVAL(hnd->data, 16, sys_getpid()); /* something more random */
230 /****************************************************************************
231 find printer index by handle
232 ****************************************************************************/
233 static Printer_entry *find_printer_index_by_hnd(const POLICY_HND *hnd)
235 Printer_entry *find_printer;
237 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
239 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
241 if (memcmp(&(find_printer->printer_hnd), hnd, sizeof(*hnd)) == 0) {
242 DEBUG(4,("Found printer handle \n"));
243 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
248 DEBUG(3,("Whoops, Printer handle not found: "));
249 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
253 /****************************************************************************
255 ****************************************************************************/
256 static void clear_handle(POLICY_HND *hnd)
261 /***************************************************************************
262 Disconnect from the client
263 ****************************************************************************/
264 static BOOL srv_spoolss_replycloseprinter(POLICY_HND *handle)
268 /* weird if the test succeds !!! */
269 if (smb_connections==0) {
270 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
274 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
277 /* if it's the last connection, deconnect the IPC$ share */
278 if (smb_connections==1) {
279 if(!spoolss_disconnect_from_client(&cli))
282 message_deregister(MSG_PRINTER_NOTIFY);
290 /****************************************************************************
291 close printer index by handle
292 ****************************************************************************/
294 static BOOL close_printer_handle(POLICY_HND *hnd)
296 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
298 if (!OPEN_HANDLE(Printer)) {
299 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
303 if (Printer->notify.client_connected==True)
304 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
305 return ERROR_INVALID_HANDLE;
308 Printer->notify.flags=0;
309 Printer->notify.options=0;
310 Printer->notify.localmachine[0]='\0';
311 Printer->notify.printerlocal=0;
312 free_spool_notify_option(&Printer->notify.option);
313 Printer->notify.client_connected=False;
317 ubi_dlRemThis(&Printer_list, Printer);
324 /****************************************************************************
325 delete a printer given a handle
326 ****************************************************************************/
327 static uint32 delete_printer_handle(POLICY_HND *hnd)
329 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
331 if (!OPEN_HANDLE(Printer)) {
332 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
333 return ERROR_INVALID_HANDLE;
336 if (del_a_printer(Printer->dev.handlename) != 0) {
337 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
338 return ERROR_INVALID_HANDLE;
341 /* Check calling user has permission to delete printer. Note that
342 since we set the snum parameter to -1 only administrators can
343 delete the printer. This stops people with the Full Control
344 permission from deleting the printer. */
346 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
347 DEBUG(3, ("printer delete denied by security descriptor\n"));
348 return ERROR_ACCESS_DENIED;
351 if (*lp_deleteprinter_cmd()) {
353 pid_t local_pid = sys_getpid();
354 char *cmd = lp_deleteprinter_cmd();
361 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
362 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
366 /* Printer->dev.handlename equals portname equals sharename */
367 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
368 Printer->dev.handlename);
369 dos_to_unix(command, True); /* Convert printername to unix-codepage */
370 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
373 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
374 ret = smbrun(command, tmp_file, False);
377 return ERROR_INVALID_HANDLE; /* What to return here? */
379 DEBUGADD(10,("returned [%d]\n", ret));
380 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
383 /* Send SIGHUP to process group... is there a better way? */
386 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
388 return ERROR_SUCCESS;
390 return ERROR_ACCESS_DENIED;
393 return ERROR_SUCCESS;
396 /****************************************************************************
397 return the snum of a printer corresponding to an handle
398 ****************************************************************************/
399 static BOOL get_printer_snum(POLICY_HND *hnd, int *number)
401 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
403 if (!OPEN_HANDLE(Printer)) {
404 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
408 switch (Printer->printer_type) {
409 case PRINTER_HANDLE_IS_PRINTER:
410 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
411 *number = print_queue_snum(Printer->dev.handlename);
412 return (*number != -1);
413 case PRINTER_HANDLE_IS_PRINTSERVER:
420 /****************************************************************************
421 set printer handle type.
422 ****************************************************************************/
423 static BOOL set_printer_hnd_accesstype(POLICY_HND *hnd, uint32 access_required)
425 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
427 if (!OPEN_HANDLE(Printer)) {
428 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
432 DEBUG(4,("Setting printer access=%x\n", access_required));
433 Printer->access = access_required;
437 /****************************************************************************
438 Set printer handle type.
439 Check if it's \\server or \\server\printer
440 ****************************************************************************/
442 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
444 DEBUG(3,("Setting printer type=%s\n", handlename));
446 if ( strlen(handlename) < 3 ) {
447 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
451 /* it's a print server */
452 if (!strchr(handlename+2, '\\')) {
453 DEBUGADD(4,("Printer is a print server\n"));
454 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
458 DEBUGADD(4,("Printer is a printer\n"));
459 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
465 /****************************************************************************
466 Set printer handle name.
467 ****************************************************************************/
469 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
471 NT_PRINTER_INFO_LEVEL *printer = NULL;
473 int n_services=lp_numservices();
477 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
479 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
480 ZERO_STRUCT(Printer->dev.printerservername);
481 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
485 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
488 aprinter=strchr(handlename+2, '\\');
491 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
494 * store the Samba share name in it
495 * in back we have the long printer name
496 * need to iterate all the snum and do a
497 * get_a_printer each time to find the printer
498 * faster to do it here than later.
501 for (snum=0;snum<n_services && found==False;snum++) {
504 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
507 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
509 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
512 printername=strchr(printer->info_2->printername+2, '\\');
515 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
516 printer->info_2->printername, aprinter ));
518 if ( strlen(printername) != strlen(aprinter) ) {
519 free_a_printer(&printer, 2);
523 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
524 free_a_printer(&printer, 2);
532 * if we haven't found a printer with the given handlename
533 * then it can be a share name as you can open both \\server\printer and
538 * we still check if the printer description file exists as NT won't be happy
539 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
543 DEBUGADD(5,("Printer not found, checking for share now\n"));
545 for (snum=0;snum<n_services && found==False;snum++) {
547 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
550 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
552 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
555 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
556 printer->info_2->printername, aprinter ));
558 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
559 free_a_printer(&printer, 2);
563 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
564 free_a_printer(&printer, 2);
573 DEBUGADD(4,("Printer not found\n"));
578 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
579 printer->info_2->printername, lp_servicename(snum),snum));
581 ZERO_STRUCT(Printer->dev.handlename);
582 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
584 free_a_printer(&printer, 2);
589 /****************************************************************************
590 find first available printer slot. creates a printer handle for you.
591 ****************************************************************************/
593 static BOOL open_printer_hnd(POLICY_HND *hnd, char *name)
595 Printer_entry *new_printer;
597 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
599 create_printer_hnd(hnd);
601 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
604 ZERO_STRUCTP(new_printer);
606 new_printer->open = True;
607 new_printer->notify.option=NULL;
609 memcpy(&new_printer->printer_hnd, hnd, sizeof(*hnd));
611 ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
613 if (!set_printer_hnd_printertype(new_printer, name)) {
614 close_printer_handle(hnd);
618 if (!set_printer_hnd_name(new_printer, name)) {
619 close_printer_handle(hnd);
623 DEBUG(5, ("%d printer handles active\n",
624 (int)ubi_dlCount(&Printer_list)));
629 /********************************************************************
630 Return True is the handle is a print server.
631 ********************************************************************/
632 static BOOL handle_is_printserver(const POLICY_HND *handle)
634 Printer_entry *Printer=find_printer_index_by_hnd(handle);
636 if (!OPEN_HANDLE(Printer))
639 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
645 /****************************************************************************
646 allocate more memory for a BUFFER.
647 ****************************************************************************/
648 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
656 /* damn, I'm doing the reverse operation of prs_grow() :) */
657 if (buffer_size < prs_data_size(ps))
660 extra_space = buffer_size - prs_data_size(ps);
663 * save the offset and move to the end of the buffer
664 * prs_grow() checks the extra_space against the offset
666 old_offset=prs_offset(ps);
667 prs_set_offset(ps, prs_data_size(ps));
669 if (!prs_grow(ps, extra_space))
672 prs_set_offset(ps, old_offset);
674 buffer->string_at_end=prs_data_size(ps);
679 /***************************************************************************
680 receive the notify message
681 ****************************************************************************/
682 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
686 Printer_entry *find_printer;
689 fstrcpy(printer,buf);
692 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
696 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
698 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
700 /* Iterate the printer list. */
701 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
704 * if the entry is the given printer or if it's a printerserver
705 * we send the message
708 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
709 if (strcmp(find_printer->dev.handlename, printer))
712 if (find_printer->notify.client_connected==True)
713 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
718 /***************************************************************************
720 ****************************************************************************/
721 static BOOL srv_spoolss_sendnotify(POLICY_HND *handle)
725 Printer_entry *Printer=find_printer_index_by_hnd(handle);
727 if (!OPEN_HANDLE(Printer)) {
728 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
732 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
733 fstrcpy(printer, Printer->dev.handlename);
735 fstrcpy(printer, "");
737 /*srv_spoolss_receive_message(printer);*/
738 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
740 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
745 /********************************************************************
746 * spoolss_open_printer
748 * called from the spoolss dispatcher
749 ********************************************************************/
751 uint32 _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
754 uint32 result = NT_STATUS_NO_PROBLEMO;
757 UNISTR2 *printername = NULL;
758 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
759 /* uint32 user_switch = q_u->user_switch; - notused */
760 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
761 POLICY_HND *handle = &r_u->handle;
765 struct current_user user;
767 if (q_u->printername_ptr != 0)
768 printername = &q_u->printername;
770 if (printername == NULL)
771 return ERROR_INVALID_PRINTER_NAME;
773 /* some sanity check because you can open a printer or a print server */
774 /* aka: \\server\printer or \\server */
775 unistr2_to_ascii(name, printername, sizeof(name)-1);
777 DEBUGADD(3,("checking name: %s\n",name));
779 if (!open_printer_hnd(handle, name))
780 return ERROR_INVALID_PRINTER_NAME;
783 if (printer_default->datatype_ptr != NULL)
785 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
786 set_printer_hnd_datatype(handle, datatype);
789 set_printer_hnd_datatype(handle, "");
792 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
793 close_printer_handle(handle);
794 return ERROR_ACCESS_DENIED;
798 First case: the user is opening the print server:
800 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
801 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
803 Then both Win2k and WinNT clients try an OpenPrinterEx with
804 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
805 or if the user is listed in the smb.conf printer admin parameter.
807 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
808 client view printer folder, but does not show the MSAPW.
810 Note: this test needs code to check access rights here too. Jeremy
811 could you look at this?
814 Second case: the user is opening a printer:
815 NT doesn't let us connect to a printer if the connecting user
816 doesn't have print permission.
820 get_current_user(&user, p);
822 if (handle_is_printserver(handle)) {
823 if (printer_default->access_required == 0) {
824 return NT_STATUS_NO_PROBLEMO;
826 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
828 /* Printserver handles use global struct... */
831 if (!lp_ms_add_printer_wizard()) {
832 close_printer_handle(handle);
833 return ERROR_ACCESS_DENIED;
835 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
836 return NT_STATUS_NO_PROBLEMO;
839 close_printer_handle(handle);
840 return ERROR_ACCESS_DENIED;
846 /* NT doesn't let us connect to a printer if the connecting user
847 doesn't have print permission. */
849 /* map an empty access mask to the minimum access mask */
850 if (printer_default->access_required == 0x0)
851 printer_default->access_required = PRINTER_ACCESS_USE;
853 if (!get_printer_snum(handle, &snum))
854 return ERROR_INVALID_HANDLE;
856 if (!print_access_check(&user, snum, printer_default->access_required)) {
857 DEBUG(3, ("access DENIED for printer open\n"));
858 close_printer_handle(handle);
859 return ERROR_ACCESS_DENIED;
863 * If we have a default device pointer in the
864 * printer_default struct, then we need to get
865 * the printer info from the tdb and if there is
866 * no default devicemode there then we do a *SET*
867 * here ! This is insanity.... JRA.
871 * If the openprinterex rpc call contains a devmode,
872 * it's a per-user one. This per-user devmode is derivated
873 * from the global devmode. Openprinterex() contains a per-user
874 * devmode for when you do EMF printing and spooling.
875 * In the EMF case, the NT workstation is only doing half the job
876 * of rendering the page. The other half is done by running the printer
877 * driver on the server.
878 * The EMF file doesn't contain the page description (paper size, orientation, ...).
879 * The EMF file only contains what is to be printed on the page.
880 * So in order for the server to know how to print, the NT client sends
881 * a devicemode attached to the openprinterex call.
882 * But this devicemode is short lived, it's only valid for the current print job.
884 * If Samba would have supported EMF spooling, this devicemode would
885 * have been attached to the handle, to sent it to the driver to correctly
886 * rasterize the EMF file.
888 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
889 * we just act as a pass-thru between windows and the printer.
891 * In order to know that Samba supports only RAW spooling, NT has to call
892 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
893 * and until NT sends a RAW job, we refuse it.
895 * But to call getprinter() or startdoc(), you first need a valid handle,
896 * and to get an handle you have to call openprintex(). Hence why you have
897 * a devicemode in the openprinterex() call.
900 * Differences between NT4 and NT 2000.
903 * On NT4, you only have a global devicemode. This global devicemode can be changed
904 * by the administrator (or by a user with enough privs). Everytime a user
905 * wants to print, the devicemode is resetted to the default. In Word, everytime
906 * you print, the printer's characteristics are always reset to the global devicemode.
910 * In W2K, there is the notion of per-user devicemode. The first time you use
911 * a printer, a per-user devicemode is build from the global devicemode.
912 * If you change your per-user devicemode, it is saved in the registry, under the
913 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
914 * printer preferences available.
916 * To change the per-user devicemode: it's the "Printing Preferences ..." button
917 * on the General Tab of the printer properties windows.
919 * To change the global devicemode: it's the "Printing Defaults..." button
920 * on the Advanced Tab of the printer properties window.
928 if (printer_default->devmode_cont.devmode != NULL) {
929 result = printer_write_default_dev( snum, printer_default);
931 close_printer_handle(handle);
938 return NT_STATUS_NO_PROBLEMO;
941 /****************************************************************************
942 ****************************************************************************/
943 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
944 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
948 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
957 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
958 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
962 printer->info_3=NULL;
963 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
966 printer->info_6=NULL;
967 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
976 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
977 NT_DEVICEMODE **pp_nt_devmode)
979 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
982 * Ensure nt_devmode is a valid pointer
983 * as we will be overwriting it.
986 if (nt_devmode == NULL) {
987 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
988 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
992 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
993 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
995 nt_devmode->specversion=devmode->specversion;
996 nt_devmode->driverversion=devmode->driverversion;
997 nt_devmode->size=devmode->size;
998 nt_devmode->fields=devmode->fields;
999 nt_devmode->orientation=devmode->orientation;
1000 nt_devmode->papersize=devmode->papersize;
1001 nt_devmode->paperlength=devmode->paperlength;
1002 nt_devmode->paperwidth=devmode->paperwidth;
1003 nt_devmode->scale=devmode->scale;
1004 nt_devmode->copies=devmode->copies;
1005 nt_devmode->defaultsource=devmode->defaultsource;
1006 nt_devmode->printquality=devmode->printquality;
1007 nt_devmode->color=devmode->color;
1008 nt_devmode->duplex=devmode->duplex;
1009 nt_devmode->yresolution=devmode->yresolution;
1010 nt_devmode->ttoption=devmode->ttoption;
1011 nt_devmode->collate=devmode->collate;
1013 nt_devmode->logpixels=devmode->logpixels;
1014 nt_devmode->bitsperpel=devmode->bitsperpel;
1015 nt_devmode->pelswidth=devmode->pelswidth;
1016 nt_devmode->pelsheight=devmode->pelsheight;
1017 nt_devmode->displayflags=devmode->displayflags;
1018 nt_devmode->displayfrequency=devmode->displayfrequency;
1019 nt_devmode->icmmethod=devmode->icmmethod;
1020 nt_devmode->icmintent=devmode->icmintent;
1021 nt_devmode->mediatype=devmode->mediatype;
1022 nt_devmode->dithertype=devmode->dithertype;
1023 nt_devmode->reserved1=devmode->reserved1;
1024 nt_devmode->reserved2=devmode->reserved2;
1025 nt_devmode->panningwidth=devmode->panningwidth;
1026 nt_devmode->panningheight=devmode->panningheight;
1029 * Only change private and driverextra if the incoming devmode
1030 * has a new one. JRA.
1033 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1034 safe_free(nt_devmode->private);
1035 nt_devmode->driverextra=devmode->driverextra;
1036 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1038 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1041 *pp_nt_devmode = nt_devmode;
1046 /********************************************************************
1047 * _spoolss_enddocprinter_internal.
1048 ********************************************************************/
1050 static uint32 _spoolss_enddocprinter_internal(POLICY_HND *handle)
1052 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1054 if (!OPEN_HANDLE(Printer)) {
1055 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1056 return ERROR_INVALID_HANDLE;
1059 Printer->document_started=False;
1060 print_job_end(Printer->jobid,True);
1061 /* error codes unhandled so far ... */
1066 /********************************************************************
1067 * api_spoolss_closeprinter
1068 ********************************************************************/
1070 uint32 _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1072 POLICY_HND *handle = &q_u->handle;
1074 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1076 if (Printer && Printer->document_started)
1077 _spoolss_enddocprinter_internal(handle); /* print job was not closed */
1079 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1081 if (!close_printer_handle(handle))
1082 return ERROR_INVALID_HANDLE;
1084 return NT_STATUS_NO_PROBLEMO;
1087 /********************************************************************
1088 * api_spoolss_deleteprinter
1090 ********************************************************************/
1092 uint32 _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1094 POLICY_HND *handle = &q_u->handle;
1096 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1099 if (Printer && Printer->document_started)
1100 _spoolss_enddocprinter_internal(handle); /* print job was not closed */
1102 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1104 result = delete_printer_handle(handle);
1106 if (result == ERROR_SUCCESS) {
1107 srv_spoolss_sendnotify(handle);
1113 /********************************************************************
1114 GetPrinterData on a printer server Handle.
1115 ********************************************************************/
1117 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1121 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1123 if (!strcmp(value, "BeepEnabled")) {
1125 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1127 SIVAL(*data, 0, 0x01);
1132 if (!strcmp(value, "EventLog")) {
1134 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1136 SIVAL(*data, 0, 0x1B);
1141 if (!strcmp(value, "NetPopup")) {
1143 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1145 SIVAL(*data, 0, 0x01);
1150 if (!strcmp(value, "MajorVersion")) {
1152 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1154 SIVAL(*data, 0, 0x02);
1159 if (!strcmp(value, "DefaultSpoolDirectory")) {
1160 pstring string="You are using a Samba server";
1162 *needed = 2*(strlen(string)+1);
1163 if((*data = (uint8 *)talloc_zero( ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1166 /* it's done by hand ready to go on the wire */
1167 for (i=0; i<strlen(string); i++) {
1168 (*data)[2*i]=string[i];
1169 (*data)[2*i+1]='\0';
1174 if (!strcmp(value, "Architecture")) {
1175 pstring string="Windows NT x86";
1177 *needed = 2*(strlen(string)+1);
1178 if((*data = (uint8 *)talloc_zero( ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1180 for (i=0; i<strlen(string); i++) {
1181 (*data)[2*i]=string[i];
1182 (*data)[2*i+1]='\0';
1190 /********************************************************************
1191 GetPrinterData on a printer Handle.
1192 ********************************************************************/
1193 static BOOL getprinterdata_printer(TALLOC_CTX *ctx, POLICY_HND *handle,
1194 fstring value, uint32 *type,
1195 uint8 **data, uint32 *needed, uint32 in_size )
1197 NT_PRINTER_INFO_LEVEL *printer = NULL;
1201 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1203 DEBUG(5,("getprinterdata_printer\n"));
1205 if (!OPEN_HANDLE(Printer)) {
1206 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1210 if(!get_printer_snum(handle, &snum))
1213 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1216 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1217 free_a_printer(&printer, 2);
1221 free_a_printer(&printer, 2);
1223 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1226 if((*data = (uint8 *)talloc_zero(ctx, in_size *sizeof(uint8) )) == NULL) {
1230 /* copy the min(in_size, len) */
1231 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1238 DEBUG(5,("getprinterdata_printer:copy done\n"));
1245 /********************************************************************
1246 * spoolss_getprinterdata
1247 ********************************************************************/
1249 uint32 _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1251 POLICY_HND *handle = &q_u->handle;
1252 UNISTR2 *valuename = &q_u->valuename;
1253 uint32 in_size = q_u->size;
1254 uint32 *type = &r_u->type;
1255 uint32 *out_size = &r_u->size;
1256 uint8 **data = &r_u->data;
1257 uint32 *needed = &r_u->needed;
1261 Printer_entry *Printer = find_printer_index_by_hnd(handle);
1264 * Reminder: when it's a string, the length is in BYTES
1265 * even if UNICODE is negociated.
1272 /* in case of problem, return some default values */
1276 DEBUG(4,("_spoolss_getprinterdata\n"));
1278 if (!OPEN_HANDLE(Printer)) {
1279 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1280 return ERROR_NOT_ENOUGH_MEMORY;
1281 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1282 return ERROR_INVALID_HANDLE;
1285 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1287 if (handle_is_printserver(handle))
1288 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1290 found= getprinterdata_printer(p->mem_ctx, handle, value, type, data, needed, *out_size);
1293 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1294 /* reply this param doesn't exist */
1296 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1297 return ERROR_NOT_ENOUGH_MEMORY;
1302 return ERROR_INVALID_PARAMETER;
1305 if (*needed > *out_size)
1306 return ERROR_MORE_DATA;
1308 return NT_STATUS_NO_PROBLEMO;
1312 /***************************************************************************
1313 connect to the client
1314 ****************************************************************************/
1315 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1320 * If it's the first connection, contact the client
1321 * and connect to the IPC$ share anonumously
1323 if (smb_connections==0) {
1324 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1326 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1332 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1338 /********************************************************************
1340 * ReplyFindFirstPrinterChangeNotifyEx
1342 * jfmxxxx: before replying OK: status=0
1343 * should do a rpc call to the workstation asking ReplyOpenPrinter
1344 * have to code it, later.
1346 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1347 * called from api_spoolss_rffpcnex
1348 ********************************************************************/
1350 uint32 _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1352 POLICY_HND *handle = &q_u->handle;
1353 uint32 flags = q_u->flags;
1354 uint32 options = q_u->options;
1355 UNISTR2 *localmachine = &q_u->localmachine;
1356 uint32 printerlocal = q_u->printerlocal;
1357 SPOOL_NOTIFY_OPTION *option = q_u->option;
1359 /* store the notify value in the printer struct */
1361 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1363 if (!OPEN_HANDLE(Printer)) {
1364 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1365 return ERROR_INVALID_HANDLE;
1368 Printer->notify.flags=flags;
1369 Printer->notify.printerlocal=printerlocal;
1371 if (Printer->notify.option)
1372 free_spool_notify_option(&Printer->notify.option);
1374 Printer->notify.options=options;
1375 Printer->notify.option=dup_spool_notify_option(option);
1377 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1379 /* connect to the client machine and send a ReplyOpenPrinter */
1380 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1381 Printer->notify.printerlocal, 1,
1382 &Printer->notify.client_hnd))
1383 Printer->notify.client_connected=True;
1385 return NT_STATUS_NO_PROBLEMO;
1388 /*******************************************************************
1389 * fill a notify_info_data with the servername
1390 ********************************************************************/
1392 static void spoolss_notify_server_name(int snum,
1393 SPOOL_NOTIFY_INFO_DATA *data,
1394 print_queue_struct *queue,
1395 NT_PRINTER_INFO_LEVEL *printer,
1396 TALLOC_CTX *mem_ctx)
1398 pstring temp_name, temp;
1401 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1403 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1405 data->notify_data.data.length = len / 2 - 1;
1406 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1408 if (!data->notify_data.data.string) {
1409 data->notify_data.data.length = 0;
1413 memcpy(data->notify_data.data.string, temp, len);
1416 /*******************************************************************
1417 * fill a notify_info_data with the printername (not including the servername).
1418 ********************************************************************/
1419 static void spoolss_notify_printer_name(int snum,
1420 SPOOL_NOTIFY_INFO_DATA *data,
1421 print_queue_struct *queue,
1422 NT_PRINTER_INFO_LEVEL *printer,
1423 TALLOC_CTX *mem_ctx)
1428 /* the notify name should not contain the \\server\ part */
1429 char *p = strrchr(printer->info_2->printername, '\\');
1432 p = printer->info_2->printername;
1437 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1439 data->notify_data.data.length = len / 2 - 1;
1440 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1442 if (!data->notify_data.data.string) {
1443 data->notify_data.data.length = 0;
1447 memcpy(data->notify_data.data.string, temp, len);
1450 /*******************************************************************
1451 * fill a notify_info_data with the servicename
1452 ********************************************************************/
1453 static void spoolss_notify_share_name(int snum,
1454 SPOOL_NOTIFY_INFO_DATA *data,
1455 print_queue_struct *queue,
1456 NT_PRINTER_INFO_LEVEL *printer,
1457 TALLOC_CTX *mem_ctx)
1462 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1463 sizeof(temp) - 2, True);
1465 data->notify_data.data.length = len / 2 - 1;
1466 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1468 if (!data->notify_data.data.string) {
1469 data->notify_data.data.length = 0;
1473 memcpy(data->notify_data.data.string, temp, len);
1476 /*******************************************************************
1477 * fill a notify_info_data with the port name
1478 ********************************************************************/
1479 static void spoolss_notify_port_name(int snum,
1480 SPOOL_NOTIFY_INFO_DATA *data,
1481 print_queue_struct *queue,
1482 NT_PRINTER_INFO_LEVEL *printer,
1483 TALLOC_CTX *mem_ctx)
1488 /* even if it's strange, that's consistant in all the code */
1490 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1491 sizeof(temp) - 2, True);
1493 data->notify_data.data.length = len / 2 - 1;
1494 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1496 if (!data->notify_data.data.string) {
1497 data->notify_data.data.length = 0;
1501 memcpy(data->notify_data.data.string, temp, len);
1504 /*******************************************************************
1505 * fill a notify_info_data with the printername
1506 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1507 * but it doesn't exist, have to see what to do
1508 ********************************************************************/
1509 static void spoolss_notify_driver_name(int snum,
1510 SPOOL_NOTIFY_INFO_DATA *data,
1511 print_queue_struct *queue,
1512 NT_PRINTER_INFO_LEVEL *printer,
1513 TALLOC_CTX *mem_ctx)
1518 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1519 sizeof(temp) - 2, True);
1521 data->notify_data.data.length = len / 2 - 1;
1522 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1524 if (!data->notify_data.data.string) {
1525 data->notify_data.data.length = 0;
1529 memcpy(data->notify_data.data.string, temp, len);
1532 /*******************************************************************
1533 * fill a notify_info_data with the comment
1534 ********************************************************************/
1535 static void spoolss_notify_comment(int snum,
1536 SPOOL_NOTIFY_INFO_DATA *data,
1537 print_queue_struct *queue,
1538 NT_PRINTER_INFO_LEVEL *printer,
1539 TALLOC_CTX *mem_ctx)
1544 if (*printer->info_2->comment == '\0')
1545 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1546 sizeof(temp) - 2, True);
1548 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1549 sizeof(temp) - 2, True);
1551 data->notify_data.data.length = len / 2 - 1;
1552 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1554 if (!data->notify_data.data.string) {
1555 data->notify_data.data.length = 0;
1559 memcpy(data->notify_data.data.string, temp, len);
1562 /*******************************************************************
1563 * fill a notify_info_data with the comment
1564 * jfm:xxxx incorrect, have to create a new smb.conf option
1565 * location = "Room 1, floor 2, building 3"
1566 ********************************************************************/
1567 static void spoolss_notify_location(int snum,
1568 SPOOL_NOTIFY_INFO_DATA *data,
1569 print_queue_struct *queue,
1570 NT_PRINTER_INFO_LEVEL *printer,
1571 TALLOC_CTX *mem_ctx)
1576 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1577 sizeof(temp) - 2, True);
1579 data->notify_data.data.length = len / 2 - 1;
1580 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1582 if (!data->notify_data.data.string) {
1583 data->notify_data.data.length = 0;
1587 memcpy(data->notify_data.data.string, temp, len);
1590 /*******************************************************************
1591 * fill a notify_info_data with the device mode
1592 * jfm:xxxx don't to it for know but that's a real problem !!!
1593 ********************************************************************/
1594 static void spoolss_notify_devmode(int snum,
1595 SPOOL_NOTIFY_INFO_DATA *data,
1596 print_queue_struct *queue,
1597 NT_PRINTER_INFO_LEVEL *printer,
1598 TALLOC_CTX *mem_ctx)
1602 /*******************************************************************
1603 * fill a notify_info_data with the separator file name
1604 * jfm:xxxx just return no file could add an option to smb.conf
1605 * separator file = "separator.txt"
1606 ********************************************************************/
1607 static void spoolss_notify_sepfile(int snum,
1608 SPOOL_NOTIFY_INFO_DATA *data,
1609 print_queue_struct *queue,
1610 NT_PRINTER_INFO_LEVEL *printer,
1611 TALLOC_CTX *mem_ctx)
1616 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1617 sizeof(temp) - 2, True);
1619 data->notify_data.data.length = len / 2 - 1;
1620 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1622 if (!data->notify_data.data.string) {
1623 data->notify_data.data.length = 0;
1627 memcpy(data->notify_data.data.string, temp, len);
1630 /*******************************************************************
1631 * fill a notify_info_data with the print processor
1632 * jfm:xxxx return always winprint to indicate we don't do anything to it
1633 ********************************************************************/
1634 static void spoolss_notify_print_processor(int snum,
1635 SPOOL_NOTIFY_INFO_DATA *data,
1636 print_queue_struct *queue,
1637 NT_PRINTER_INFO_LEVEL *printer,
1638 TALLOC_CTX *mem_ctx)
1643 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
1644 sizeof(temp) - 2, True);
1646 data->notify_data.data.length = len / 2 - 1;
1647 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1649 if (!data->notify_data.data.string) {
1650 data->notify_data.data.length = 0;
1654 memcpy(data->notify_data.data.string, temp, len);
1657 /*******************************************************************
1658 * fill a notify_info_data with the print processor options
1659 * jfm:xxxx send an empty string
1660 ********************************************************************/
1661 static void spoolss_notify_parameters(int snum,
1662 SPOOL_NOTIFY_INFO_DATA *data,
1663 print_queue_struct *queue,
1664 NT_PRINTER_INFO_LEVEL *printer,
1665 TALLOC_CTX *mem_ctx)
1670 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1671 sizeof(temp) - 2, True);
1673 data->notify_data.data.length = len / 2 - 1;
1674 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1676 if (!data->notify_data.data.string) {
1677 data->notify_data.data.length = 0;
1681 memcpy(data->notify_data.data.string, temp, len);
1684 /*******************************************************************
1685 * fill a notify_info_data with the data type
1686 * jfm:xxxx always send RAW as data type
1687 ********************************************************************/
1688 static void spoolss_notify_datatype(int snum,
1689 SPOOL_NOTIFY_INFO_DATA *data,
1690 print_queue_struct *queue,
1691 NT_PRINTER_INFO_LEVEL *printer,
1692 TALLOC_CTX *mem_ctx)
1697 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1698 sizeof(pstring) - 2, True);
1700 data->notify_data.data.length = len / 2 - 1;
1701 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1703 if (!data->notify_data.data.string) {
1704 data->notify_data.data.length = 0;
1708 memcpy(data->notify_data.data.string, temp, len);
1711 /*******************************************************************
1712 * fill a notify_info_data with the security descriptor
1713 * jfm:xxxx send an null pointer to say no security desc
1714 * have to implement security before !
1715 ********************************************************************/
1716 static void spoolss_notify_security_desc(int snum,
1717 SPOOL_NOTIFY_INFO_DATA *data,
1718 print_queue_struct *queue,
1719 NT_PRINTER_INFO_LEVEL *printer,
1720 TALLOC_CTX *mem_ctx)
1722 data->notify_data.data.length=0;
1723 data->notify_data.data.string = NULL;
1726 /*******************************************************************
1727 * fill a notify_info_data with the attributes
1728 * jfm:xxxx a samba printer is always shared
1729 ********************************************************************/
1730 static void spoolss_notify_attributes(int snum,
1731 SPOOL_NOTIFY_INFO_DATA *data,
1732 print_queue_struct *queue,
1733 NT_PRINTER_INFO_LEVEL *printer,
1734 TALLOC_CTX *mem_ctx)
1736 data->notify_data.value[0] = printer->info_2->attributes;
1739 /*******************************************************************
1740 * fill a notify_info_data with the priority
1741 ********************************************************************/
1742 static void spoolss_notify_priority(int snum,
1743 SPOOL_NOTIFY_INFO_DATA *data,
1744 print_queue_struct *queue,
1745 NT_PRINTER_INFO_LEVEL *printer,
1746 TALLOC_CTX *mem_ctx)
1748 data->notify_data.value[0] = printer->info_2->priority;
1751 /*******************************************************************
1752 * fill a notify_info_data with the default priority
1753 ********************************************************************/
1754 static void spoolss_notify_default_priority(int snum,
1755 SPOOL_NOTIFY_INFO_DATA *data,
1756 print_queue_struct *queue,
1757 NT_PRINTER_INFO_LEVEL *printer,
1758 TALLOC_CTX *mem_ctx)
1760 data->notify_data.value[0] = printer->info_2->default_priority;
1763 /*******************************************************************
1764 * fill a notify_info_data with the start time
1765 ********************************************************************/
1766 static void spoolss_notify_start_time(int snum,
1767 SPOOL_NOTIFY_INFO_DATA *data,
1768 print_queue_struct *queue,
1769 NT_PRINTER_INFO_LEVEL *printer,
1770 TALLOC_CTX *mem_ctx)
1772 data->notify_data.value[0] = printer->info_2->starttime;
1775 /*******************************************************************
1776 * fill a notify_info_data with the until time
1777 ********************************************************************/
1778 static void spoolss_notify_until_time(int snum,
1779 SPOOL_NOTIFY_INFO_DATA *data,
1780 print_queue_struct *queue,
1781 NT_PRINTER_INFO_LEVEL *printer,
1782 TALLOC_CTX *mem_ctx)
1784 data->notify_data.value[0] = printer->info_2->untiltime;
1787 /*******************************************************************
1788 * fill a notify_info_data with the status
1789 ********************************************************************/
1790 static void spoolss_notify_status(int snum,
1791 SPOOL_NOTIFY_INFO_DATA *data,
1792 print_queue_struct *queue,
1793 NT_PRINTER_INFO_LEVEL *printer,
1794 TALLOC_CTX *mem_ctx)
1798 print_queue_struct *q=NULL;
1799 print_status_struct status;
1801 memset(&status, 0, sizeof(status));
1802 count = print_queue_status(snum, &q, &status);
1803 data->notify_data.value[0]=(uint32) status.status;
1807 /*******************************************************************
1808 * fill a notify_info_data with the number of jobs queued
1809 ********************************************************************/
1810 static void spoolss_notify_cjobs(int snum,
1811 SPOOL_NOTIFY_INFO_DATA *data,
1812 print_queue_struct *queue,
1813 NT_PRINTER_INFO_LEVEL *printer,
1814 TALLOC_CTX *mem_ctx)
1816 print_queue_struct *q=NULL;
1817 print_status_struct status;
1819 memset(&status, 0, sizeof(status));
1820 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1824 /*******************************************************************
1825 * fill a notify_info_data with the average ppm
1826 ********************************************************************/
1827 static void spoolss_notify_average_ppm(int snum,
1828 SPOOL_NOTIFY_INFO_DATA *data,
1829 print_queue_struct *queue,
1830 NT_PRINTER_INFO_LEVEL *printer,
1831 TALLOC_CTX *mem_ctx)
1833 /* always respond 8 pages per minutes */
1834 /* a little hard ! */
1835 data->notify_data.value[0] = printer->info_2->averageppm;
1838 /*******************************************************************
1839 * fill a notify_info_data with username
1840 ********************************************************************/
1841 static void spoolss_notify_username(int snum,
1842 SPOOL_NOTIFY_INFO_DATA *data,
1843 print_queue_struct *queue,
1844 NT_PRINTER_INFO_LEVEL *printer,
1845 TALLOC_CTX *mem_ctx)
1850 len = (uint32)dos_PutUniCode(temp, queue->user,
1851 sizeof(temp) - 2, True);
1853 data->notify_data.data.length = len / 2 - 1;
1854 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1856 if (!data->notify_data.data.string) {
1857 data->notify_data.data.length = 0;
1861 memcpy(data->notify_data.data.string, temp, len);
1864 /*******************************************************************
1865 * fill a notify_info_data with job status
1866 ********************************************************************/
1867 static void spoolss_notify_job_status(int snum,
1868 SPOOL_NOTIFY_INFO_DATA *data,
1869 print_queue_struct *queue,
1870 NT_PRINTER_INFO_LEVEL *printer,
1871 TALLOC_CTX *mem_ctx)
1873 data->notify_data.value[0]=nt_printj_status(queue->status);
1876 /*******************************************************************
1877 * fill a notify_info_data with job name
1878 ********************************************************************/
1879 static void spoolss_notify_job_name(int snum,
1880 SPOOL_NOTIFY_INFO_DATA *data,
1881 print_queue_struct *queue,
1882 NT_PRINTER_INFO_LEVEL *printer,
1883 TALLOC_CTX *mem_ctx)
1888 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1891 data->notify_data.data.length = len / 2 - 1;
1892 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1894 if (!data->notify_data.data.string) {
1895 data->notify_data.data.length = 0;
1899 memcpy(data->notify_data.data.string, temp, len);
1902 /*******************************************************************
1903 * fill a notify_info_data with job status
1904 ********************************************************************/
1905 static void spoolss_notify_job_status_string(int snum,
1906 SPOOL_NOTIFY_INFO_DATA *data,
1907 print_queue_struct *queue,
1908 NT_PRINTER_INFO_LEVEL *printer,
1909 TALLOC_CTX *mem_ctx)
1912 * Now we're returning job status codes we just return a "" here. JRA.
1919 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1922 switch (queue->status) {
1927 p = ""; /* NT provides the paused string */
1936 #endif /* NO LONGER NEEDED. */
1938 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1940 data->notify_data.data.length = len / 2 - 1;
1941 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1943 if (!data->notify_data.data.string) {
1944 data->notify_data.data.length = 0;
1948 memcpy(data->notify_data.data.string, temp, len);
1951 /*******************************************************************
1952 * fill a notify_info_data with job time
1953 ********************************************************************/
1954 static void spoolss_notify_job_time(int snum,
1955 SPOOL_NOTIFY_INFO_DATA *data,
1956 print_queue_struct *queue,
1957 NT_PRINTER_INFO_LEVEL *printer,
1958 TALLOC_CTX *mem_ctx)
1960 data->notify_data.value[0]=0x0;
1963 /*******************************************************************
1964 * fill a notify_info_data with job size
1965 ********************************************************************/
1966 static void spoolss_notify_job_size(int snum,
1967 SPOOL_NOTIFY_INFO_DATA *data,
1968 print_queue_struct *queue,
1969 NT_PRINTER_INFO_LEVEL *printer,
1970 TALLOC_CTX *mem_ctx)
1972 data->notify_data.value[0]=queue->size;
1975 /*******************************************************************
1976 * fill a notify_info_data with job position
1977 ********************************************************************/
1978 static void spoolss_notify_job_position(int snum,
1979 SPOOL_NOTIFY_INFO_DATA *data,
1980 print_queue_struct *queue,
1981 NT_PRINTER_INFO_LEVEL *printer,
1982 TALLOC_CTX *mem_ctx)
1984 data->notify_data.value[0]=queue->job;
1987 /*******************************************************************
1988 * fill a notify_info_data with submitted time
1989 ********************************************************************/
1990 static void spoolss_notify_submitted_time(int snum,
1991 SPOOL_NOTIFY_INFO_DATA *data,
1992 print_queue_struct *queue,
1993 NT_PRINTER_INFO_LEVEL *printer,
1994 TALLOC_CTX *mem_ctx)
1999 t=gmtime(&queue->time);
2001 len = sizeof(SYSTEMTIME);
2003 data->notify_data.data.length = len;
2004 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2006 if (!data->notify_data.data.string) {
2007 data->notify_data.data.length = 0;
2011 make_systemtime((SYSTEMTIME*)(data->notify_data.data.string), t);
2016 struct s_notify_info_data_table
2022 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2023 print_queue_struct *queue,
2024 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2027 struct s_notify_info_data_table notify_info_data_table[] =
2029 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2030 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2031 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2032 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2033 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2034 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2035 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2036 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2037 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2038 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2039 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2040 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2041 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2042 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2043 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2044 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2045 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2046 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2047 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2048 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2049 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2050 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2051 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2052 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2053 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2054 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2055 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2056 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2057 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2058 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2059 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2060 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2061 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2062 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2063 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2064 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2065 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2066 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2067 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2068 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2069 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2070 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2071 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2072 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2073 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2074 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2075 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2076 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2077 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2078 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2079 { END, END, "", END, NULL }
2082 /*******************************************************************
2083 return the size of info_data structure
2084 ********************************************************************/
2085 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2089 while (notify_info_data_table[i].type != END)
2091 if ( (notify_info_data_table[i].type == type ) &&
2092 (notify_info_data_table[i].field == field ) )
2094 return (notify_info_data_table[i].size);
2101 /*******************************************************************
2102 return the type of notify_info_data
2103 ********************************************************************/
2104 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2108 while (notify_info_data_table[i].type != END)
2110 if ( (notify_info_data_table[i].type == type ) &&
2111 (notify_info_data_table[i].field == field ) )
2113 if (notify_info_data_table[i].size == POINTER)
2127 /****************************************************************************
2128 ****************************************************************************/
2129 static int search_notify(uint16 type, uint16 field, int *value)
2134 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2136 if ( (notify_info_data_table[j].type == type ) &&
2137 (notify_info_data_table[j].field == field ) )
2142 if ( found && (notify_info_data_table[j].fn != NULL) )
2148 /****************************************************************************
2149 ****************************************************************************/
2150 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2152 info_data->type = type;
2153 info_data->field = field;
2154 info_data->reserved = 0;
2156 info_data->size = size_of_notify_info_data(type, field);
2157 info_data->enc_type = type_of_notify_info_data(type, field);
2161 /*******************************************************************
2163 * fill a notify_info struct with info asked
2165 ********************************************************************/
2166 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2167 snum, SPOOL_NOTIFY_OPTION_TYPE
2168 *option_type, uint32 id,
2169 TALLOC_CTX *mem_ctx)
2175 SPOOL_NOTIFY_INFO_DATA *current_data;
2176 NT_PRINTER_INFO_LEVEL *printer = NULL;
2177 print_queue_struct *queue=NULL;
2178 size_t realloc_size = 0;
2179 SPOOL_NOTIFY_INFO_DATA *info_data_ptr = NULL;
2181 type=option_type->type;
2183 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2184 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2185 option_type->count, lp_servicename(snum)));
2187 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2190 for(field_num=0; field_num<option_type->count; field_num++) {
2191 field = option_type->fields[field_num];
2192 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2194 if (!search_notify(type, field, &j) )
2197 realloc_size = (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA);
2198 if((info_data_ptr=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info_data_ptr, realloc_size)) == NULL) {
2201 current_data=&info_data_ptr[info->count];
2203 construct_info_data(current_data, type, field, id);
2205 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2206 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2208 notify_info_data_table[j].fn(snum, current_data, queue,
2215 info->data = talloc_memdup(mem_ctx, info_data_ptr, realloc_size);
2219 safe_free(info_data_ptr);
2220 free_a_printer(&printer, 2);
2224 /*******************************************************************
2226 * fill a notify_info struct with info asked
2228 ********************************************************************/
2229 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2230 SPOOL_NOTIFY_INFO *info,
2231 NT_PRINTER_INFO_LEVEL *printer,
2232 int snum, SPOOL_NOTIFY_OPTION_TYPE
2233 *option_type, uint32 id,
2234 TALLOC_CTX *mem_ctx)
2240 SPOOL_NOTIFY_INFO_DATA *current_data;
2242 DEBUG(4,("construct_notify_jobs_info\n"));
2244 type = option_type->type;
2246 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2247 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2248 option_type->count));
2250 for(field_num=0; field_num<option_type->count; field_num++) {
2251 field = option_type->fields[field_num];
2253 if (!search_notify(type, field, &j) )
2256 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2260 current_data=&(info->data[info->count]);
2262 construct_info_data(current_data, type, field, id);
2263 notify_info_data_table[j].fn(snum, current_data, queue,
2272 * JFM: The enumeration is not that simple, it's even non obvious.
2274 * let's take an example: I want to monitor the PRINTER SERVER for
2275 * the printer's name and the number of jobs currently queued.
2276 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2277 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2279 * I have 3 printers on the back of my server.
2281 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2284 * 1 printer 1 name 1
2285 * 2 printer 1 cjob 1
2286 * 3 printer 2 name 2
2287 * 4 printer 2 cjob 2
2288 * 5 printer 3 name 3
2289 * 6 printer 3 name 3
2291 * that's the print server case, the printer case is even worse.
2296 /*******************************************************************
2298 * enumerate all printers on the printserver
2299 * fill a notify_info struct with info asked
2301 ********************************************************************/
2302 static uint32 printserver_notify_info(const POLICY_HND *hnd,
2303 SPOOL_NOTIFY_INFO *info,
2304 TALLOC_CTX *mem_ctx)
2307 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2308 int n_services=lp_numservices();
2311 SPOOL_NOTIFY_OPTION *option;
2312 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2314 DEBUG(4,("printserver_notify_info\n"));
2316 option=Printer->notify.option;
2322 for (i=0; i<option->count; i++) {
2323 option_type=&(option->ctr.type[i]);
2325 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2328 for (snum=0; snum<n_services; snum++)
2329 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2330 if (construct_notify_printer_info(info, snum, option_type, id, mem_ctx))
2335 * Debugging information, don't delete.
2338 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2339 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2340 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2342 for (i=0; i<info->count; i++) {
2343 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2344 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2345 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2349 return NT_STATUS_NO_PROBLEMO;
2352 /*******************************************************************
2354 * fill a notify_info struct with info asked
2356 ********************************************************************/
2357 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2358 TALLOC_CTX *mem_ctx)
2361 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
2364 SPOOL_NOTIFY_OPTION *option;
2365 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2367 print_queue_struct *queue=NULL;
2368 print_status_struct status;
2370 DEBUG(4,("printer_notify_info\n"));
2372 option=Printer->notify.option;
2378 get_printer_snum(hnd, &snum);
2380 for (i=0; i<option->count; i++) {
2381 option_type=&option->ctr.type[i];
2383 switch ( option_type->type ) {
2384 case PRINTER_NOTIFY_TYPE:
2385 if(construct_notify_printer_info(info, snum, option_type, id, mem_ctx))
2389 case JOB_NOTIFY_TYPE: {
2390 NT_PRINTER_INFO_LEVEL *printer = NULL;
2392 memset(&status, 0, sizeof(status));
2393 count = print_queue_status(snum, &queue, &status);
2395 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2398 for (j=0; j<count; j++) {
2399 construct_notify_jobs_info(&queue[j], info,
2406 free_a_printer(&printer, 2);
2416 * Debugging information, don't delete.
2419 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2420 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2421 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2423 for (i=0; i<info->count; i++) {
2424 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2425 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2426 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2429 return NT_STATUS_NO_PROBLEMO;
2432 /********************************************************************
2434 ********************************************************************/
2436 uint32 _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2438 POLICY_HND *handle = &q_u->handle;
2439 /* uint32 change = q_u->change; - notused. */
2440 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2441 SPOOL_NOTIFY_INFO *info = &r_u->info;
2443 Printer_entry *Printer=find_printer_index_by_hnd(handle);
2444 uint32 result = ERROR_INVALID_HANDLE;
2446 /* we always have a NOTIFY_INFO struct */
2449 if (!OPEN_HANDLE(Printer)) {
2450 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2451 OUR_HANDLE(handle)));
2455 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2457 /* jfm: the change value isn't used right now.
2458 * we will honour it when
2459 * a) we'll be able to send notification to the client
2460 * b) we'll have a way to communicate between the spoolss process.
2462 * same thing for option->flags
2463 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2464 * I don't have a global notification system, I'm sending back all the
2465 * informations even when _NOTHING_ has changed.
2468 /* just ignore the SPOOL_NOTIFY_OPTION */
2470 switch (Printer->printer_type) {
2471 case PRINTER_HANDLE_IS_PRINTSERVER:
2472 result = printserver_notify_info(handle, info,
2476 case PRINTER_HANDLE_IS_PRINTER:
2477 result = printer_notify_info(handle, info, p->mem_ctx);
2485 /********************************************************************
2486 * construct_printer_info_0
2487 * fill a printer_info_0 struct
2488 ********************************************************************/
2489 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2493 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2494 counter_printer_0 *session_counter;
2495 uint32 global_counter;
2499 print_queue_struct *queue=NULL;
2500 print_status_struct status;
2502 memset(&status, 0, sizeof(status));
2504 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2507 count = print_queue_status(snum, &queue, &status);
2509 /* check if we already have a counter for this printer */
2510 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2512 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2513 if (session_counter->snum == snum)
2517 /* it's the first time, add it to the list */
2518 if (session_counter==NULL) {
2519 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2520 free_a_printer(&ntprinter, 2);
2523 ZERO_STRUCTP(session_counter);
2524 session_counter->snum=snum;
2525 session_counter->counter=0;
2526 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2530 session_counter->counter++;
2533 * the global_counter should be stored in a TDB as it's common to all the clients
2534 * and should be zeroed on samba startup
2536 global_counter=session_counter->counter;
2538 pstrcpy(chaine,ntprinter->info_2->printername);
2540 init_unistr(&printer->printername, chaine);
2542 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2543 init_unistr(&printer->servername, chaine);
2545 printer->cjobs = count;
2546 printer->total_jobs = 0;
2547 printer->total_bytes = 0;
2549 setuptime = (time_t)ntprinter->info_2->setuptime;
2550 t=gmtime(&setuptime);
2552 printer->year = t->tm_year+1900;
2553 printer->month = t->tm_mon+1;
2554 printer->dayofweek = t->tm_wday;
2555 printer->day = t->tm_mday;
2556 printer->hour = t->tm_hour;
2557 printer->minute = t->tm_min;
2558 printer->second = t->tm_sec;
2559 printer->milliseconds = 0;
2561 printer->global_counter = global_counter;
2562 printer->total_pages = 0;
2563 printer->major_version = 0x0004; /* NT 4 */
2564 printer->build_version = 0x0565; /* build 1381 */
2565 printer->unknown7 = 0x1;
2566 printer->unknown8 = 0x0;
2567 printer->unknown9 = 0x0;
2568 printer->session_counter = session_counter->counter;
2569 printer->unknown11 = 0x0;
2570 printer->printer_errors = 0x0; /* number of print failure */
2571 printer->unknown13 = 0x0;
2572 printer->unknown14 = 0x1;
2573 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2574 printer->unknown16 = 0x0;
2575 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2576 printer->unknown18 = 0x0;
2577 printer->status = nt_printq_status(status.status);
2578 printer->unknown20 = 0x0;
2579 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2580 printer->unknown22 = 0x0;
2581 printer->unknown23 = 0x6; /* 6 ???*/
2582 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2583 printer->unknown25 = 0;
2584 printer->unknown26 = 0;
2585 printer->unknown27 = 0;
2586 printer->unknown28 = 0;
2587 printer->unknown29 = 0;
2590 free_a_printer(&ntprinter,2);
2594 /********************************************************************
2595 * construct_printer_info_1
2596 * fill a printer_info_1 struct
2597 ********************************************************************/
2598 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2602 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2604 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2607 printer->flags=flags;
2609 if (*ntprinter->info_2->comment == '\0') {
2610 init_unistr(&printer->comment, lp_comment(snum));
2611 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2612 ntprinter->info_2->drivername, lp_comment(snum));
2615 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2616 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2617 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2620 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2622 init_unistr(&printer->description, chaine);
2623 init_unistr(&printer->name, chaine2);
2625 free_a_printer(&ntprinter,2);
2630 /****************************************************************************
2631 Free a DEVMODE struct.
2632 ****************************************************************************/
2634 static void free_dev_mode(DEVICEMODE *dev)
2640 safe_free(dev->private);
2645 /****************************************************************************
2646 Create a DEVMODE struct. Returns malloced memory.
2647 ****************************************************************************/
2649 static DEVICEMODE *construct_dev_mode(int snum)
2653 NT_PRINTER_INFO_LEVEL *printer = NULL;
2654 NT_DEVICEMODE *ntdevmode = NULL;
2655 DEVICEMODE *devmode = NULL;
2657 DEBUG(7,("construct_dev_mode\n"));
2659 DEBUGADD(8,("getting printer characteristics\n"));
2661 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2662 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2666 ZERO_STRUCTP(devmode);
2668 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2671 if (printer->info_2->devmode)
2672 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2674 if (ntdevmode == NULL)
2677 DEBUGADD(8,("loading DEVICEMODE\n"));
2679 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2680 init_unistr(&devmode->devicename, adevice);
2682 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2683 init_unistr(&devmode->formname, aform);
2685 devmode->specversion = ntdevmode->specversion;
2686 devmode->driverversion = ntdevmode->driverversion;
2687 devmode->size = ntdevmode->size;
2688 devmode->driverextra = ntdevmode->driverextra;
2689 devmode->fields = ntdevmode->fields;
2691 devmode->orientation = ntdevmode->orientation;
2692 devmode->papersize = ntdevmode->papersize;
2693 devmode->paperlength = ntdevmode->paperlength;
2694 devmode->paperwidth = ntdevmode->paperwidth;
2695 devmode->scale = ntdevmode->scale;
2696 devmode->copies = ntdevmode->copies;
2697 devmode->defaultsource = ntdevmode->defaultsource;
2698 devmode->printquality = ntdevmode->printquality;
2699 devmode->color = ntdevmode->color;
2700 devmode->duplex = ntdevmode->duplex;
2701 devmode->yresolution = ntdevmode->yresolution;
2702 devmode->ttoption = ntdevmode->ttoption;
2703 devmode->collate = ntdevmode->collate;
2704 devmode->icmmethod = ntdevmode->icmmethod;
2705 devmode->icmintent = ntdevmode->icmintent;
2706 devmode->mediatype = ntdevmode->mediatype;
2707 devmode->dithertype = ntdevmode->dithertype;
2709 if (ntdevmode->private != NULL) {
2710 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2714 free_nt_devicemode(&ntdevmode);
2715 free_a_printer(&printer,2);
2722 free_nt_devicemode(&ntdevmode);
2724 free_a_printer(&printer,2);
2725 free_dev_mode(devmode);
2730 /********************************************************************
2731 * construct_printer_info_2
2732 * fill a printer_info_2 struct
2733 ********************************************************************/
2735 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2738 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2740 print_queue_struct *queue=NULL;
2741 print_status_struct status;
2742 memset(&status, 0, sizeof(status));
2744 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2747 memset(&status, 0, sizeof(status));
2748 count = print_queue_status(snum, &queue, &status);
2750 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2751 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2752 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2753 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2754 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2756 if (*ntprinter->info_2->comment == '\0')
2757 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2759 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2761 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2762 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2763 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2764 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2765 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2767 printer->attributes = ntprinter->info_2->attributes;
2769 printer->priority = ntprinter->info_2->priority; /* priority */
2770 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2771 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2772 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2773 printer->status = nt_printq_status(status.status); /* status */
2774 printer->cjobs = count; /* jobs */
2775 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2777 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2778 DEBUG(8, ("Returning NULL Devicemode!\n"));
2781 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2782 /* steal the printer info sec_desc structure. [badly done]. */
2783 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2784 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2785 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2786 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2789 printer->secdesc = NULL;
2792 free_a_printer(&ntprinter, 2);
2797 /********************************************************************
2798 * construct_printer_info_3
2799 * fill a printer_info_3 struct
2800 ********************************************************************/
2801 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2803 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2804 PRINTER_INFO_3 *printer = NULL;
2806 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2810 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2811 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2815 ZERO_STRUCTP(printer);
2817 printer->flags = 4; /* These are the components of the SD we are returning. */
2818 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2819 /* steal the printer info sec_desc structure. [badly done]. */
2820 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2824 * Set the flags for the components we are returning.
2827 if (printer->secdesc->owner_sid)
2828 printer->flags |= OWNER_SECURITY_INFORMATION;
2830 if (printer->secdesc->grp_sid)
2831 printer->flags |= GROUP_SECURITY_INFORMATION;
2833 if (printer->secdesc->dacl)
2834 printer->flags |= DACL_SECURITY_INFORMATION;
2836 if (printer->secdesc->sacl)
2837 printer->flags |= SACL_SECURITY_INFORMATION;
2840 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2841 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2842 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2845 free_a_printer(&ntprinter, 2);
2847 *pp_printer = printer;
2851 /********************************************************************
2852 Spoolss_enumprinters.
2853 ********************************************************************/
2854 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2858 int n_services=lp_numservices();
2859 PRINTER_INFO_1 *printers=NULL;
2860 PRINTER_INFO_1 current_prt;
2862 DEBUG(4,("enum_all_printers_info_1\n"));
2864 for (snum=0; snum<n_services; snum++) {
2865 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2866 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2868 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2869 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2871 return ERROR_NOT_ENOUGH_MEMORY;
2873 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2874 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
2880 /* check the required size. */
2881 for (i=0; i<*returned; i++)
2882 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2884 if (!alloc_buffer_size(buffer, *needed))
2885 return ERROR_INSUFFICIENT_BUFFER;
2887 /* fill the buffer with the structures */
2888 for (i=0; i<*returned; i++)
2889 new_smb_io_printer_info_1("", buffer, &printers[i], 0);
2892 safe_free(printers);
2894 if (*needed > offered) {
2896 return ERROR_INSUFFICIENT_BUFFER;
2899 return NT_STATUS_NO_PROBLEMO;
2902 /********************************************************************
2903 enum_all_printers_info_1_local.
2904 *********************************************************************/
2905 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2907 DEBUG(4,("enum_all_printers_info_1_local\n"));
2909 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2912 /********************************************************************
2913 enum_all_printers_info_1_name.
2914 *********************************************************************/
2915 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2918 DEBUG(4,("enum_all_printers_info_1_name\n"));
2920 fstrcpy(temp, "\\\\");
2921 fstrcat(temp, global_myname);
2923 if (strequal(name, temp)) {
2924 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2927 return ERROR_INVALID_NAME;
2930 /********************************************************************
2931 enum_all_printers_info_1_remote.
2932 *********************************************************************/
2933 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2935 PRINTER_INFO_1 *printer;
2936 fstring printername;
2939 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2941 /* JFM: currently it's more a place holder than anything else.
2942 * In the spooler world there is a notion of server registration.
2943 * the print servers are registring (sp ?) on the PDC (in the same domain)
2945 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2948 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2949 return ERROR_NOT_ENOUGH_MEMORY;
2953 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2954 slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2955 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2957 init_unistr(&printer->description, desc);
2958 init_unistr(&printer->name, printername);
2959 init_unistr(&printer->comment, comment);
2960 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2962 /* check the required size. */
2963 *needed += spoolss_size_printer_info_1(printer);
2965 if (!alloc_buffer_size(buffer, *needed)) {
2967 return ERROR_INSUFFICIENT_BUFFER;
2970 /* fill the buffer with the structures */
2971 new_smb_io_printer_info_1("", buffer, printer, 0);
2976 if (*needed > offered) {
2978 return ERROR_INSUFFICIENT_BUFFER;
2981 return NT_STATUS_NO_PROBLEMO;
2984 /********************************************************************
2985 enum_all_printers_info_1_network.
2986 *********************************************************************/
2988 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2990 DEBUG(4,("enum_all_printers_info_1_network\n"));
2992 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2995 /********************************************************************
2996 * api_spoolss_enumprinters
2998 * called from api_spoolss_enumprinters (see this to understand)
2999 ********************************************************************/
3001 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3005 int n_services=lp_numservices();
3006 PRINTER_INFO_2 *printers=NULL;
3007 PRINTER_INFO_2 current_prt;
3009 for (snum=0; snum<n_services; snum++) {
3010 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3011 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3013 if (construct_printer_info_2(¤t_prt, snum)) {
3014 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
3015 return ERROR_NOT_ENOUGH_MEMORY;
3016 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3017 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
3023 /* check the required size. */
3024 for (i=0; i<*returned; i++)
3025 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3027 if (!alloc_buffer_size(buffer, *needed)) {
3028 for (i=0; i<*returned; i++) {
3029 free_devmode(printers[i].devmode);
3031 safe_free(printers);
3032 return ERROR_INSUFFICIENT_BUFFER;
3035 /* fill the buffer with the structures */
3036 for (i=0; i<*returned; i++)
3037 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3040 for (i=0; i<*returned; i++) {
3041 free_devmode(printers[i].devmode);
3043 safe_free(printers);
3045 if (*needed > offered) {
3047 return ERROR_INSUFFICIENT_BUFFER;
3050 return NT_STATUS_NO_PROBLEMO;
3053 /********************************************************************
3054 * handle enumeration of printers at level 1
3055 ********************************************************************/
3056 static uint32 enumprinters_level1( uint32 flags, fstring name,
3057 NEW_BUFFER *buffer, uint32 offered,
3058 uint32 *needed, uint32 *returned)
3060 /* Not all the flags are equals */
3062 if (flags & PRINTER_ENUM_LOCAL)
3063 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3065 if (flags & PRINTER_ENUM_NAME)
3066 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3068 if (flags & PRINTER_ENUM_REMOTE)
3069 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3071 if (flags & PRINTER_ENUM_NETWORK)
3072 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3074 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
3077 /********************************************************************
3078 * handle enumeration of printers at level 2
3079 ********************************************************************/
3080 static uint32 enumprinters_level2( uint32 flags, fstring servername,
3081 NEW_BUFFER *buffer, uint32 offered,
3082 uint32 *needed, uint32 *returned)
3086 fstrcpy(temp, "\\\\");
3087 fstrcat(temp, global_myname);
3089 if (flags & PRINTER_ENUM_LOCAL) {
3090 if (strequal(servername, temp))
3091 return enum_all_printers_info_2(buffer, offered, needed, returned);
3093 return enum_all_printers_info_2(buffer, offered, needed, returned);
3096 if (flags & PRINTER_ENUM_NAME) {
3097 if (strequal(servername, temp))
3098 return enum_all_printers_info_2(buffer, offered, needed, returned);
3100 return ERROR_INVALID_NAME;
3103 if (flags & PRINTER_ENUM_REMOTE)
3104 return ERROR_INVALID_LEVEL;
3106 return NT_STATUS_NO_PROBLEMO;
3109 /********************************************************************
3110 * handle enumeration of printers at level 5
3111 ********************************************************************/
3112 static uint32 enumprinters_level5( uint32 flags, fstring servername,
3113 NEW_BUFFER *buffer, uint32 offered,
3114 uint32 *needed, uint32 *returned)
3116 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3117 return NT_STATUS_NO_PROBLEMO;
3120 /********************************************************************
3121 * api_spoolss_enumprinters
3123 * called from api_spoolss_enumprinters (see this to understand)
3124 ********************************************************************/
3126 uint32 _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3128 uint32 flags = q_u->flags;
3129 UNISTR2 *servername = &q_u->servername;
3130 uint32 level = q_u->level;
3131 NEW_BUFFER *buffer = NULL;
3132 uint32 offered = q_u->offered;
3133 uint32 *needed = &r_u->needed;
3134 uint32 *returned = &r_u->returned;
3138 /* that's an [in out] buffer */
3139 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3140 buffer = r_u->buffer;
3142 DEBUG(4,("_spoolss_enumprinters\n"));
3149 * flags==PRINTER_ENUM_NAME
3150 * if name=="" then enumerates all printers
3151 * if name!="" then enumerate the printer
3152 * flags==PRINTER_ENUM_REMOTE
3153 * name is NULL, enumerate printers
3154 * Level 2: name!="" enumerates printers, name can't be NULL
3155 * Level 3: doesn't exist
3156 * Level 4: does a local registry lookup
3157 * Level 5: same as Level 2
3160 unistr2_to_ascii(name, servername, sizeof(name)-1);
3165 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3167 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3169 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3173 return ERROR_INVALID_LEVEL;
3177 /****************************************************************************
3178 ****************************************************************************/
3179 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3181 PRINTER_INFO_0 *printer=NULL;
3183 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3184 return ERROR_NOT_ENOUGH_MEMORY;
3186 construct_printer_info_0(printer, snum);
3188 /* check the required size. */
3189 *needed += spoolss_size_printer_info_0(printer);
3191 if (!alloc_buffer_size(buffer, *needed)) {
3193 return ERROR_INSUFFICIENT_BUFFER;
3196 /* fill the buffer with the structures */
3197 new_smb_io_printer_info_0("", buffer, printer, 0);
3202 if (*needed > offered) {
3203 return ERROR_INSUFFICIENT_BUFFER;
3206 return NT_STATUS_NO_PROBLEMO;
3209 /****************************************************************************
3210 ****************************************************************************/
3211 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3213 PRINTER_INFO_1 *printer=NULL;
3215 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3216 return ERROR_NOT_ENOUGH_MEMORY;
3218 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3220 /* check the required size. */
3221 *needed += spoolss_size_printer_info_1(printer);
3223 if (!alloc_buffer_size(buffer, *needed)) {
3225 return ERROR_INSUFFICIENT_BUFFER;
3228 /* fill the buffer with the structures */
3229 new_smb_io_printer_info_1("", buffer, printer, 0);
3234 if (*needed > offered) {
3235 return ERROR_INSUFFICIENT_BUFFER;
3238 return NT_STATUS_NO_PROBLEMO;
3241 /****************************************************************************
3242 ****************************************************************************/
3243 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3245 PRINTER_INFO_2 *printer=NULL;
3247 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3248 return ERROR_NOT_ENOUGH_MEMORY;
3250 construct_printer_info_2(printer, snum);
3252 /* check the required size. */
3253 *needed += spoolss_size_printer_info_2(printer);
3255 if (!alloc_buffer_size(buffer, *needed)) {
3256 free_printer_info_2(printer);
3257 return ERROR_INSUFFICIENT_BUFFER;
3260 /* fill the buffer with the structures */
3261 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
3262 free_printer_info_2(printer);
3263 return ERROR_NOT_ENOUGH_MEMORY;
3267 free_printer_info_2(printer);
3269 if (*needed > offered) {
3270 return ERROR_INSUFFICIENT_BUFFER;
3273 return NT_STATUS_NO_PROBLEMO;
3276 /****************************************************************************
3277 ****************************************************************************/
3278 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3280 PRINTER_INFO_3 *printer=NULL;
3282 if (!construct_printer_info_3(&printer, snum))
3283 return ERROR_NOT_ENOUGH_MEMORY;
3285 /* check the required size. */
3286 *needed += spoolss_size_printer_info_3(printer);
3288 if (!alloc_buffer_size(buffer, *needed)) {
3289 free_printer_info_3(printer);
3290 return ERROR_INSUFFICIENT_BUFFER;
3293 /* fill the buffer with the structures */
3294 new_smb_io_printer_info_3("", buffer, printer, 0);
3297 free_printer_info_3(printer);
3299 if (*needed > offered) {
3300 return ERROR_INSUFFICIENT_BUFFER;
3303 return NT_STATUS_NO_PROBLEMO;
3306 /****************************************************************************
3307 ****************************************************************************/
3309 uint32 _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3311 POLICY_HND *handle = &q_u->handle;
3312 uint32 level = q_u->level;
3313 NEW_BUFFER *buffer = NULL;
3314 uint32 offered = q_u->offered;
3315 uint32 *needed = &r_u->needed;
3319 /* that's an [in out] buffer */
3320 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3321 buffer = r_u->buffer;
3325 if (!get_printer_snum(handle, &snum))
3326 return ERROR_INVALID_HANDLE;
3330 return getprinter_level_0(snum, buffer, offered, needed);
3332 return getprinter_level_1(snum, buffer, offered, needed);
3334 return getprinter_level_2(snum, buffer, offered, needed);
3336 return getprinter_level_3(snum, buffer, offered, needed);
3338 return ERROR_INVALID_LEVEL;
3342 /********************************************************************
3343 * fill a DRIVER_INFO_1 struct
3344 ********************************************************************/
3345 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3347 init_unistr( &info->name, driver.info_3->name);
3350 /********************************************************************
3351 * construct_printer_driver_info_1
3352 ********************************************************************/
3353 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3355 NT_PRINTER_INFO_LEVEL *printer = NULL;
3356 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3358 ZERO_STRUCT(driver);
3360 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3361 return ERROR_INVALID_PRINTER_NAME;
3363 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3364 return ERROR_UNKNOWN_PRINTER_DRIVER;
3366 fill_printer_driver_info_1(info, driver, servername, architecture);
3368 free_a_printer(&printer,2);
3370 return NT_STATUS_NO_PROBLEMO;
3373 /********************************************************************
3374 * construct_printer_driver_info_2
3375 * fill a printer_info_2 struct
3376 ********************************************************************/
3377 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3381 info->version=driver.info_3->cversion;
3383 init_unistr( &info->name, driver.info_3->name );
3384 init_unistr( &info->architecture, driver.info_3->environment );
3387 if (strlen(driver.info_3->driverpath)) {
3388 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3389 init_unistr( &info->driverpath, temp );
3391 init_unistr( &info->driverpath, "" );
3393 if (strlen(driver.info_3->datafile)) {
3394 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3395 init_unistr( &info->datafile, temp );
3397 init_unistr( &info->datafile, "" );
3399 if (strlen(driver.info_3->configfile)) {
3400 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3401 init_unistr( &info->configfile, temp );
3403 init_unistr( &info->configfile, "" );
3406 /********************************************************************
3407 * construct_printer_driver_info_2
3408 * fill a printer_info_2 struct
3409 ********************************************************************/
3410 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3412 NT_PRINTER_INFO_LEVEL *printer = NULL;
3413 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3415 ZERO_STRUCT(printer);
3416 ZERO_STRUCT(driver);
3418 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3419 return ERROR_INVALID_PRINTER_NAME;
3421 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3422 return ERROR_UNKNOWN_PRINTER_DRIVER;
3424 fill_printer_driver_info_2(info, driver, servername);
3426 free_a_printer(&printer,2);
3428 return NT_STATUS_NO_PROBLEMO;
3431 /********************************************************************
3432 * copy a strings array and convert to UNICODE
3434 * convert an array of ascii string to a UNICODE string
3435 ********************************************************************/
3436 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3443 DEBUG(6,("init_unistr_array\n"));
3447 if (char_array == NULL)
3451 if (!v) v = ""; /* hack to handle null lists */
3453 if (strlen(v) == 0) break;
3454 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3455 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3456 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3457 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3460 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3465 (*uni_array)[j]=0x0000;
3468 DEBUGADD(6,("last one:done\n"));
3471 /********************************************************************
3472 * construct_printer_info_3
3473 * fill a printer_info_3 struct
3474 ********************************************************************/
3475 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3481 info->version=driver.info_3->cversion;
3483 init_unistr( &info->name, driver.info_3->name );
3484 init_unistr( &info->architecture, driver.info_3->environment );
3486 if (strlen(driver.info_3->driverpath)) {
3487 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3488 init_unistr( &info->driverpath, temp );
3490 init_unistr( &info->driverpath, "" );
3492 if (strlen(driver.info_3->datafile)) {
3493 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3494 init_unistr( &info->datafile, temp );
3496 init_unistr( &info->datafile, "" );
3498 if (strlen(driver.info_3->configfile)) {
3499 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3500 init_unistr( &info->configfile, temp );
3502 init_unistr( &info->configfile, "" );
3504 if (strlen(driver.info_3->helpfile)) {
3505 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3506 init_unistr( &info->helpfile, temp );
3508 init_unistr( &info->helpfile, "" );
3510 init_unistr( &info->monitorname, driver.info_3->monitorname );
3511 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3513 info->dependentfiles=NULL;
3514 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3517 /********************************************************************
3518 * construct_printer_info_3
3519 * fill a printer_info_3 struct
3520 ********************************************************************/
3521 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3523 NT_PRINTER_INFO_LEVEL *printer = NULL;
3524 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3526 ZERO_STRUCT(driver);
3528 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3529 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3531 return ERROR_INVALID_PRINTER_NAME;
3533 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3534 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3536 free_a_printer(&printer,2);
3537 return ERROR_UNKNOWN_PRINTER_DRIVER;
3540 fill_printer_driver_info_3(info, driver, servername);
3542 free_a_printer(&printer,2);
3544 return NT_STATUS_NO_PROBLEMO;
3547 /********************************************************************
3548 * construct_printer_info_6
3549 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3550 ********************************************************************/
3552 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3558 memset(&nullstr, '\0', sizeof(fstring));
3560 info->version=driver.info_3->cversion;
3562 init_unistr( &info->name, driver.info_3->name );
3563 init_unistr( &info->architecture, driver.info_3->environment );
3565 if (strlen(driver.info_3->driverpath)) {
3566 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3567 init_unistr( &info->driverpath, temp );
3569 init_unistr( &info->driverpath, "" );
3571 if (strlen(driver.info_3->datafile)) {
3572 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3573 init_unistr( &info->datafile, temp );
3575 init_unistr( &info->datafile, "" );
3577 if (strlen(driver.info_3->configfile)) {
3578 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3579 init_unistr( &info->configfile, temp );
3581 init_unistr( &info->configfile, "" );
3583 if (strlen(driver.info_3->helpfile)) {
3584 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3585 init_unistr( &info->helpfile, temp );
3587 init_unistr( &info->helpfile, "" );
3589 init_unistr( &info->monitorname, driver.info_3->monitorname );
3590 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3592 info->dependentfiles=NULL;
3593 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3595 info->previousdrivernames=NULL;
3596 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3598 info->driver_date.low=0;
3599 info->driver_date.high=0;
3602 info->driver_version_low=0;
3603 info->driver_version_high=0;
3605 init_unistr( &info->mfgname, "");
3606 init_unistr( &info->oem_url, "");
3607 init_unistr( &info->hardware_id, "");
3608 init_unistr( &info->provider, "");
3611 /********************************************************************
3612 * construct_printer_info_6
3613 * fill a printer_info_6 struct
3614 ********************************************************************/
3615 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3617 NT_PRINTER_INFO_LEVEL *printer = NULL;
3618 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3620 ZERO_STRUCT(driver);
3622 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3623 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3625 return ERROR_INVALID_PRINTER_NAME;
3627 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3628 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3631 * Is this a W2k client ?
3635 free_a_printer(&printer,2);
3636 return ERROR_UNKNOWN_PRINTER_DRIVER;
3639 /* Yes - try again with a WinNT driver. */
3641 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3642 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3644 free_a_printer(&printer,2);
3645 return ERROR_UNKNOWN_PRINTER_DRIVER;
3649 fill_printer_driver_info_6(info, driver, servername);
3651 free_a_printer(&printer,2);
3653 return NT_STATUS_NO_PROBLEMO;
3656 /****************************************************************************
3657 ****************************************************************************/
3659 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3661 safe_free(info->dependentfiles);
3664 /****************************************************************************
3665 ****************************************************************************/
3667 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3669 safe_free(info->dependentfiles);
3673 /****************************************************************************
3674 ****************************************************************************/
3675 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3677 DRIVER_INFO_1 *info=NULL;
3680 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3681 return ERROR_NOT_ENOUGH_MEMORY;
3683 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3684 if (status != NT_STATUS_NO_PROBLEMO) {
3689 /* check the required size. */
3690 *needed += spoolss_size_printer_driver_info_1(info);
3692 if (!alloc_buffer_size(buffer, *needed)) {
3694 return ERROR_INSUFFICIENT_BUFFER;
3697 /* fill the buffer with the structures */
3698 new_smb_io_printer_driver_info_1("", buffer, info, 0);
3703 if (*needed > offered)
3704 return ERROR_INSUFFICIENT_BUFFER;
3706 return NT_STATUS_NO_PROBLEMO;
3709 /****************************************************************************
3710 ****************************************************************************/
3711 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3713 DRIVER_INFO_2 *info=NULL;
3716 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3717 return ERROR_NOT_ENOUGH_MEMORY;
3719 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3720 if (status != NT_STATUS_NO_PROBLEMO) {
3725 /* check the required size. */
3726 *needed += spoolss_size_printer_driver_info_2(info);
3728 if (!alloc_buffer_size(buffer, *needed)) {
3730 return ERROR_INSUFFICIENT_BUFFER;
3733 /* fill the buffer with the structures */
3734 new_smb_io_printer_driver_info_2("", buffer, info, 0);
3739 if (*needed > offered)
3740 return ERROR_INSUFFICIENT_BUFFER;
3742 return NT_STATUS_NO_PROBLEMO;
3745 /****************************************************************************
3746 ****************************************************************************/
3747 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3754 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3755 if (status != NT_STATUS_NO_PROBLEMO) {
3759 /* check the required size. */
3760 *needed += spoolss_size_printer_driver_info_3(&info);
3762 if (!alloc_buffer_size(buffer, *needed)) {
3763 free_printer_driver_info_3(&info);
3764 return ERROR_INSUFFICIENT_BUFFER;
3767 /* fill the buffer with the structures */
3768 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
3770 free_printer_driver_info_3(&info);
3772 if (*needed > offered)
3773 return ERROR_INSUFFICIENT_BUFFER;
3775 return NT_STATUS_NO_PROBLEMO;
3778 /****************************************************************************
3779 ****************************************************************************/
3780 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3787 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3788 if (status != NT_STATUS_NO_PROBLEMO) {
3792 /* check the required size. */
3793 *needed += spoolss_size_printer_driver_info_6(&info);
3795 if (!alloc_buffer_size(buffer, *needed)) {
3796 free_printer_driver_info_6(&info);
3797 return ERROR_INSUFFICIENT_BUFFER;
3800 /* fill the buffer with the structures */
3801 new_smb_io_printer_driver_info_6("", buffer, &info, 0);
3803 free_printer_driver_info_6(&info);
3805 if (*needed > offered)
3806 return ERROR_INSUFFICIENT_BUFFER;
3808 return NT_STATUS_NO_PROBLEMO;
3811 /****************************************************************************
3812 ****************************************************************************/
3814 uint32 _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3816 POLICY_HND *handle = &q_u->handle;
3817 UNISTR2 *uni_arch = &q_u->architecture;
3818 uint32 level = q_u->level;
3819 uint32 clientmajorversion = q_u->clientmajorversion;
3820 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3821 NEW_BUFFER *buffer = NULL;
3822 uint32 offered = q_u->offered;
3823 uint32 *needed = &r_u->needed;
3824 uint32 *servermajorversion = &r_u->servermajorversion;
3825 uint32 *serverminorversion = &r_u->serverminorversion;
3828 fstring architecture;
3831 /* that's an [in out] buffer */
3832 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3833 buffer = r_u->buffer;
3835 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3838 *servermajorversion=0;
3839 *serverminorversion=0;
3841 pstrcpy(servername, global_myname);
3842 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3844 if (!get_printer_snum(handle, &snum))
3845 return ERROR_INVALID_HANDLE;
3849 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3851 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3853 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3855 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3857 return ERROR_INVALID_LEVEL;
3861 /****************************************************************************
3862 ****************************************************************************/
3864 uint32 _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
3866 POLICY_HND *handle = &q_u->handle;
3868 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3870 if (OPEN_HANDLE(Printer)) {
3871 Printer->page_started=True;
3875 DEBUG(3,("Error in startpageprinter printer handle\n"));
3876 return ERROR_INVALID_HANDLE;
3879 /****************************************************************************
3880 ****************************************************************************/
3882 uint32 _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
3884 POLICY_HND *handle = &q_u->handle;
3886 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3888 if (!OPEN_HANDLE(Printer)) {
3889 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3890 return ERROR_INVALID_HANDLE;
3893 Printer->page_started=False;
3895 return NT_STATUS_NO_PROBLEMO;
3898 /********************************************************************
3899 * api_spoolss_getprinter
3900 * called from the spoolss dispatcher
3902 ********************************************************************/
3904 uint32 _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
3906 POLICY_HND *handle = &q_u->handle;
3907 /* uint32 level = q_u->doc_info_container.level; - notused. */
3908 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
3909 uint32 *jobid = &r_u->jobid;
3911 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3915 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3916 struct current_user user;
3918 if (!OPEN_HANDLE(Printer)) {
3919 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3920 return ERROR_INVALID_HANDLE;
3923 get_current_user(&user, p);
3926 * a nice thing with NT is it doesn't listen to what you tell it.
3927 * when asked to send _only_ RAW datas, it tries to send datas
3930 * So I add checks like in NT Server ...
3932 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3933 * there's a bug in NT client-side code, so we'll fix it in the
3934 * server-side code. *nnnnnggggh!*
3937 if (info_1->p_datatype != 0) {
3938 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3939 if (strcmp(datatype, "RAW") != 0) {
3941 return ERROR_INVALID_DATATYPE;
3945 /* get the share number of the printer */
3946 if (!get_printer_snum(handle, &snum)) {
3947 return ERROR_INVALID_HANDLE;
3950 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3952 Printer->jobid = print_job_start(&user, snum, jobname);
3954 /* An error occured in print_job_start() so return an appropriate
3957 if (Printer->jobid == -1) {
3958 return map_nt_error_from_unix(errno);
3961 Printer->document_started=True;
3962 (*jobid) = Printer->jobid;
3967 /********************************************************************
3968 * api_spoolss_getprinter
3969 * called from the spoolss dispatcher
3971 ********************************************************************/
3973 uint32 _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
3975 POLICY_HND *handle = &q_u->handle;
3977 return _spoolss_enddocprinter_internal(handle);
3980 /****************************************************************************
3981 ****************************************************************************/
3983 uint32 _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
3985 POLICY_HND *handle = &q_u->handle;
3986 uint32 buffer_size = q_u->buffer_size;
3987 uint8 *buffer = q_u->buffer;
3988 uint32 *buffer_written = &q_u->buffer_size2;
3990 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3992 if (!OPEN_HANDLE(Printer)) {
3993 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3994 r_u->buffer_written = q_u->buffer_size2;
3995 return ERROR_INVALID_HANDLE;
3998 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4001 r_u->buffer_written = q_u->buffer_size2;
4006 /********************************************************************
4007 * api_spoolss_getprinter
4008 * called from the spoolss dispatcher
4010 ********************************************************************/
4011 static uint32 control_printer(POLICY_HND *handle, uint32 command,
4014 struct current_user user;
4015 int snum, errcode = ERROR_INVALID_FUNCTION;
4016 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4018 get_current_user(&user, p);
4020 if (!OPEN_HANDLE(Printer)) {
4021 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4022 return ERROR_INVALID_HANDLE;
4025 if (!get_printer_snum(handle, &snum))
4026 return ERROR_INVALID_HANDLE;
4029 case PRINTER_CONTROL_PAUSE:
4030 if (print_queue_pause(&user, snum, &errcode)) {
4034 case PRINTER_CONTROL_RESUME:
4035 case PRINTER_CONTROL_UNPAUSE:
4036 if (print_queue_resume(&user, snum, &errcode)) {
4040 case PRINTER_CONTROL_PURGE:
4041 if (print_queue_purge(&user, snum, &errcode)) {
4046 return ERROR_INVALID_LEVEL;
4052 /********************************************************************
4053 * api_spoolss_abortprinter
4054 ********************************************************************/
4056 uint32 _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4058 POLICY_HND *handle = &q_u->handle;
4060 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4063 /********************************************************************
4064 * called by spoolss_api_setprinter
4065 * when updating a printer description
4066 ********************************************************************/
4067 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
4068 const SPOOL_PRINTER_INFO_LEVEL *info,
4069 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4071 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4072 struct current_user user;
4076 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4078 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
4079 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4080 OUR_HANDLE(handle)));
4082 result = ERROR_INVALID_HANDLE;
4086 /* NT seems to like setting the security descriptor even though
4087 nothing may have actually changed. This causes annoying
4088 dialog boxes when the user doesn't have permission to change
4089 the security descriptor. */
4091 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4093 if (DEBUGLEVEL >= 10) {
4097 acl = old_secdesc_ctr->sec->dacl;
4098 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4099 PRINTERNAME(snum), acl->num_aces));
4101 for (i = 0; i < acl->num_aces; i++) {
4104 sid_to_string(sid_str, &acl->ace[i].sid);
4106 DEBUG(10, ("%s 0x%08x\n", sid_str,
4107 acl->ace[i].info.mask));
4110 acl = secdesc_ctr->sec->dacl;
4113 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4114 PRINTERNAME(snum), acl->num_aces));
4116 for (i = 0; i < acl->num_aces; i++) {
4119 sid_to_string(sid_str, &acl->ace[i].sid);
4121 DEBUG(10, ("%s 0x%08x\n", sid_str,
4122 acl->ace[i].info.mask));
4125 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4129 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4131 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4132 result = NT_STATUS_NO_PROBLEMO;
4136 /* Work out which user is performing the operation */
4138 get_current_user(&user, p);
4140 /* Check the user has permissions to change the security
4141 descriptor. By experimentation with two NT machines, the user
4142 requires Full Access to the printer to change security
4145 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4146 result = ERROR_ACCESS_DENIED;
4150 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4157 /********************************************************************
4158 Do Samba sanity checks on a printer info struct.
4159 this has changed purpose: it now "canonicalises" printer
4160 info from a client rather than just checking it is correct
4161 ********************************************************************/
4163 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4165 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4166 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4168 /* we force some elements to "correct" values */
4169 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4170 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4171 global_myname, lp_servicename(snum));
4172 fstrcpy(info->sharename, lp_servicename(snum));
4173 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4174 | PRINTER_ATTRIBUTE_LOCAL \
4175 | PRINTER_ATTRIBUTE_RAW_ONLY \
4176 | PRINTER_ATTRIBUTE_QUEUED ;
4181 /****************************************************************************
4182 ****************************************************************************/
4183 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4185 pid_t local_pid = sys_getpid();
4186 char *cmd = lp_addprinter_cmd();
4191 pstring driverlocation;
4195 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4196 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4200 /* build driver path... only 9X architecture is needed for legacy reasons */
4201 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4203 /* change \ to \\ for the shell */
4204 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4206 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
4207 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4208 cmd, printer->info_2->printername, printer->info_2->sharename,
4209 printer->info_2->portname, printer->info_2->drivername,
4210 printer->info_2->location, driverlocation);
4214 /* Convert script args to unix-codepage */
4215 dos_to_unix(command, True);
4216 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4217 ret = smbrun(command, tmp_file, False);
4218 DEBUGADD(10,("returned [%d]\n", ret));
4226 /* Get lines and convert them back to dos-codepage */
4227 qlines = file_lines_load(tmp_file, &numlines, True);
4228 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4229 DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
4233 /* Set the portname to what the script says the portname should be. */
4234 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4235 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4237 /* Send SIGHUP to process group... is there a better way? */
4242 file_lines_free(qlines);
4246 /* Return true if two devicemodes are equal */
4248 #define DEVMODE_CHECK_INT(field) \
4249 if (d1->field != d2->field) { \
4250 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4251 d1->field, d2->field)); \
4255 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4257 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4260 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4261 return False; /* if either is exclusively NULL are not equal */
4264 if (!strequal(d1->devicename, d2->devicename)) {
4265 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4269 if (!strequal(d1->formname, d2->formname)) {
4270 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4274 DEVMODE_CHECK_INT(specversion);
4275 DEVMODE_CHECK_INT(driverversion);
4276 DEVMODE_CHECK_INT(driverextra);
4277 DEVMODE_CHECK_INT(orientation);
4278 DEVMODE_CHECK_INT(papersize);
4279 DEVMODE_CHECK_INT(paperlength);
4280 DEVMODE_CHECK_INT(paperwidth);
4281 DEVMODE_CHECK_INT(scale);
4282 DEVMODE_CHECK_INT(copies);
4283 DEVMODE_CHECK_INT(defaultsource);
4284 DEVMODE_CHECK_INT(printquality);
4285 DEVMODE_CHECK_INT(color);
4286 DEVMODE_CHECK_INT(duplex);
4287 DEVMODE_CHECK_INT(yresolution);
4288 DEVMODE_CHECK_INT(ttoption);
4289 DEVMODE_CHECK_INT(collate);
4290 DEVMODE_CHECK_INT(logpixels);
4292 DEVMODE_CHECK_INT(fields);
4293 DEVMODE_CHECK_INT(bitsperpel);
4294 DEVMODE_CHECK_INT(pelswidth);
4295 DEVMODE_CHECK_INT(pelsheight);
4296 DEVMODE_CHECK_INT(displayflags);
4297 DEVMODE_CHECK_INT(displayfrequency);
4298 DEVMODE_CHECK_INT(icmmethod);
4299 DEVMODE_CHECK_INT(icmintent);
4300 DEVMODE_CHECK_INT(mediatype);
4301 DEVMODE_CHECK_INT(dithertype);
4302 DEVMODE_CHECK_INT(reserved1);
4303 DEVMODE_CHECK_INT(reserved2);
4304 DEVMODE_CHECK_INT(panningwidth);
4305 DEVMODE_CHECK_INT(panningheight);
4307 /* compare the private data if it exists */
4308 if (!d1->driverextra && !d2->driverextra) goto equal;
4311 DEVMODE_CHECK_INT(driverextra);
4313 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4314 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4319 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4323 /* Return true if two NT_PRINTER_PARAM structures are equal */
4325 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4326 NT_PRINTER_PARAM *p2)
4328 if (!p1 && !p2) goto equal;
4330 if ((!p1 && p2) || (p1 && !p2)) {
4331 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4335 /* Compare lists of printer parameters */
4339 NT_PRINTER_PARAM *q = p1;
4341 /* Find the parameter in the second structure */
4345 if (strequal(p1->value, q->value)) {
4347 if (p1->type != q->type) {
4348 DEBUG(10, ("nt_printer_param_equal():"
4349 "types for %s differ (%d != %d)\n",
4350 p1->value, p1->type,
4355 if (p1->data_len != q->data_len) {
4356 DEBUG(10, ("nt_printer_param_equal():"
4357 "len for %s differs (%d != %d)\n",
4358 p1->value, p1->data_len,
4363 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4366 DEBUG(10, ("nt_printer_param_equal():"
4367 "data for %s differs\n", p1->value));
4377 DEBUG(10, ("nt_printer_param_equal(): param %s "
4378 "does not exist\n", p1->value));
4387 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4391 /********************************************************************
4392 * Called by update_printer when trying to work out whether to
4393 * actually update printer info.
4394 ********************************************************************/
4396 #define PI_CHECK_INT(field) \
4397 if (pi1->field != pi2->field) { \
4398 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4399 pi1->field, pi2->field)); \
4403 #define PI_CHECK_STR(field) \
4404 if (!strequal(pi1->field, pi2->field)) { \
4405 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4406 pi1->field, pi2->field)); \
4410 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4411 NT_PRINTER_INFO_LEVEL *p2)
4413 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4415 /* Trivial conditions */
4417 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4421 if ((!p1 && p2) || (p1 && !p2) ||
4422 (!p1->info_2 && p2->info_2) ||
4423 (p1->info_2 && !p2->info_2)) {
4424 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4429 /* Compare two nt_printer_info_level structures. Don't compare
4430 status or cjobs as they seem to have something to do with the
4436 /* Don't check the attributes as we stomp on the value in
4437 check_printer_ok() anyway. */
4440 PI_CHECK_INT(attributes);
4443 PI_CHECK_INT(priority);
4444 PI_CHECK_INT(default_priority);
4445 PI_CHECK_INT(starttime);
4446 PI_CHECK_INT(untiltime);
4447 PI_CHECK_INT(averageppm);
4449 /* Yuck - don't check the printername or servername as the
4450 add_a_printer() code plays games with them. You can't
4451 change the printername or the sharename through this interface
4454 PI_CHECK_STR(sharename);
4455 PI_CHECK_STR(portname);
4456 PI_CHECK_STR(drivername);
4457 PI_CHECK_STR(comment);
4458 PI_CHECK_STR(location);
4460 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4464 PI_CHECK_STR(sepfile);
4465 PI_CHECK_STR(printprocessor);
4466 PI_CHECK_STR(datatype);
4467 PI_CHECK_STR(parameters);
4469 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4473 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4477 PI_CHECK_INT(changeid);
4478 PI_CHECK_INT(c_setprinter);
4479 PI_CHECK_INT(setuptime);
4482 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4486 /********************************************************************
4487 * called by spoolss_api_setprinter
4488 * when updating a printer description
4489 ********************************************************************/
4491 static uint32 update_printer(POLICY_HND *handle, uint32 level,
4492 const SPOOL_PRINTER_INFO_LEVEL *info,
4493 DEVICEMODE *devmode)
4496 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4497 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4500 DEBUG(8,("update_printer\n"));
4502 result = NT_STATUS_NO_PROBLEMO;
4505 DEBUG(0,("Send a mail to samba@samba.org\n"));
4506 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4507 result = ERROR_INVALID_LEVEL;
4511 if (!OPEN_HANDLE(Printer)) {
4512 result = ERROR_INVALID_HANDLE;
4516 if (!get_printer_snum(handle, &snum)) {
4517 result = ERROR_INVALID_HANDLE;
4521 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4522 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4523 result = ERROR_INVALID_HANDLE;
4527 DEBUGADD(8,("Converting info_2 struct\n"));
4530 * convert_printer_info converts the incoming
4531 * info from the client and overwrites the info
4532 * just read from the tdb in the pointer 'printer'.
4535 convert_printer_info(info, printer, level);
4537 if (info->info_2->devmode_ptr != 0) {
4538 /* we have a valid devmode
4539 convert it and link it*/
4541 DEBUGADD(8,("Converting the devicemode struct\n"));
4542 if (!convert_devicemode(printer->info_2->printername, devmode,
4543 &printer->info_2->devmode)) {
4544 result = ERROR_NOT_ENOUGH_MEMORY;
4549 /* Do sanity check on the requested changes for Samba */
4551 if (!check_printer_ok(printer->info_2, snum)) {
4552 result = ERROR_INVALID_PARAMETER;
4556 /* NT likes to call this function even though nothing has actually
4557 changed. Check this so the user doesn't end up with an
4558 annoying permission denied dialog box. */
4560 if (nt_printer_info_level_equal(printer, old_printer)) {
4561 DEBUG(3, ("printer info has not changed\n"));
4562 result = NT_STATUS_NO_PROBLEMO;
4566 /* Check calling user has permission to update printer description */
4568 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4569 DEBUG(3, ("printer property change denied by security "
4571 result = ERROR_ACCESS_DENIED;
4575 /* Call addprinter hook */
4577 if (*lp_addprinter_cmd() )
4578 if ( !add_printer_hook(printer) ) {
4579 result = ERROR_ACCESS_DENIED;
4583 /* Update printer info */
4585 if (add_a_printer(*printer, 2)!=0) {
4586 /* I don't really know what to return here !!! */
4587 result = ERROR_ACCESS_DENIED;
4592 free_a_printer(&printer, 2);
4593 free_a_printer(&old_printer, 2);
4595 srv_spoolss_sendnotify(handle);
4600 /****************************************************************************
4601 ****************************************************************************/
4603 uint32 _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4605 POLICY_HND *handle = &q_u->handle;
4606 uint32 level = q_u->level;
4607 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4608 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4609 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4610 uint32 command = q_u->command;
4612 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4614 if (!OPEN_HANDLE(Printer)) {
4615 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4616 return ERROR_INVALID_HANDLE;
4619 /* check the level */
4622 return control_printer(handle, command, p);
4624 return update_printer(handle, level, info, devmode_ctr.devmode);
4626 return update_printer_sec(handle, level, info, p,
4629 return ERROR_INVALID_LEVEL;
4633 /****************************************************************************
4634 ****************************************************************************/
4636 uint32 _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4638 POLICY_HND *handle = &q_u->handle;
4640 Printer_entry *Printer= find_printer_index_by_hnd(handle);
4642 if (!OPEN_HANDLE(Printer)) {
4643 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4644 return ERROR_INVALID_HANDLE;
4647 if (Printer->notify.client_connected==True)
4648 if(!srv_spoolss_replycloseprinter(&Printer->notify.client_hnd))
4649 return ERROR_INVALID_HANDLE;
4651 Printer->notify.flags=0;
4652 Printer->notify.options=0;
4653 Printer->notify.localmachine[0]='\0';
4654 Printer->notify.printerlocal=0;
4655 if (Printer->notify.option)
4656 free_spool_notify_option(&Printer->notify.option);
4657 Printer->notify.client_connected=False;
4659 return NT_STATUS_NO_PROBLEMO;
4662 /****************************************************************************
4663 ****************************************************************************/
4665 uint32 _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4667 /* that's an [in out] buffer (despite appearences to the contrary) */
4668 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4671 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4672 returns for AddJob. AddJob
4673 must fail on non-local
4677 /****************************************************************************
4678 ****************************************************************************/
4679 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4680 int position, int snum)
4686 t=gmtime(&queue->time);
4687 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4689 job_info->jobid=queue->job;
4690 init_unistr(&job_info->printername, lp_servicename(snum));
4691 init_unistr(&job_info->machinename, temp_name);
4692 init_unistr(&job_info->username, queue->user);
4693 init_unistr(&job_info->document, queue->file);
4694 init_unistr(&job_info->datatype, "RAW");
4695 init_unistr(&job_info->text_status, "");
4696 job_info->status=nt_printj_status(queue->status);
4697 job_info->priority=queue->priority;
4698 job_info->position=position;
4699 job_info->totalpages=0;
4700 job_info->pagesprinted=0;
4702 make_systemtime(&job_info->submitted, t);
4705 /****************************************************************************
4706 ****************************************************************************/
4707 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4708 int position, int snum,
4709 NT_PRINTER_INFO_LEVEL *ntprinter)
4715 t=gmtime(&queue->time);
4716 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4718 job_info->jobid=queue->job;
4720 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4722 init_unistr(&job_info->printername, chaine);
4724 init_unistr(&job_info->machinename, temp_name);
4725 init_unistr(&job_info->username, queue->user);
4726 init_unistr(&job_info->document, queue->file);
4727 init_unistr(&job_info->notifyname, queue->user);
4728 init_unistr(&job_info->datatype, "RAW");
4729 init_unistr(&job_info->printprocessor, "winprint");
4730 init_unistr(&job_info->parameters, "");
4731 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4732 init_unistr(&job_info->text_status, "");
4734 /* and here the security descriptor */
4736 job_info->status=nt_printj_status(queue->status);
4737 job_info->priority=queue->priority;
4738 job_info->position=position;
4739 job_info->starttime=0;
4740 job_info->untiltime=0;
4741 job_info->totalpages=0;
4742 job_info->size=queue->size;
4743 make_systemtime(&(job_info->submitted), t);
4744 job_info->timeelapsed=0;
4745 job_info->pagesprinted=0;
4747 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4754 /****************************************************************************
4755 Enumjobs at level 1.
4756 ****************************************************************************/
4757 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4758 NEW_BUFFER *buffer, uint32 offered,
4759 uint32 *needed, uint32 *returned)
4764 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4768 return ERROR_NOT_ENOUGH_MEMORY;
4771 for (i=0; i<*returned; i++)
4772 fill_job_info_1(&info[i], &queue[i], i, snum);
4776 /* check the required size. */
4777 for (i=0; i<*returned; i++)
4778 (*needed) += spoolss_size_job_info_1(&info[i]);
4780 if (!alloc_buffer_size(buffer, *needed)) {
4782 return ERROR_INSUFFICIENT_BUFFER;
4785 /* fill the buffer with the structures */
4786 for (i=0; i<*returned; i++)
4787 new_smb_io_job_info_1("", buffer, &info[i], 0);
4792 if (*needed > offered) {
4794 return ERROR_INSUFFICIENT_BUFFER;
4797 return NT_STATUS_NO_PROBLEMO;
4800 /****************************************************************************
4801 Enumjobs at level 2.
4802 ****************************************************************************/
4803 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4804 NEW_BUFFER *buffer, uint32 offered,
4805 uint32 *needed, uint32 *returned)
4807 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4811 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4814 return ERROR_NOT_ENOUGH_MEMORY;
4817 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4819 return ERROR_NOT_ENOUGH_MEMORY;
4822 for (i=0; i<*returned; i++)
4823 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4825 free_a_printer(&ntprinter, 2);
4828 /* check the required size. */
4829 for (i=0; i<*returned; i++)
4830 (*needed) += spoolss_size_job_info_2(&info[i]);
4832 if (!alloc_buffer_size(buffer, *needed)) {
4834 return ERROR_INSUFFICIENT_BUFFER;
4837 /* fill the buffer with the structures */
4838 for (i=0; i<*returned; i++)
4839 new_smb_io_job_info_2("", buffer, &info[i], 0);
4842 for (i = 0; i < *returned; i++)
4843 free_job_info_2(&info[i]);
4847 if (*needed > offered) {
4849 return ERROR_INSUFFICIENT_BUFFER;
4852 return NT_STATUS_NO_PROBLEMO;
4855 /****************************************************************************
4857 ****************************************************************************/
4859 uint32 _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4861 POLICY_HND *handle = &q_u->handle;
4862 /* uint32 firstjob = q_u->firstjob; - notused. */
4863 /* uint32 numofjobs = q_u->numofjobs; - notused. */
4864 uint32 level = q_u->level;
4865 NEW_BUFFER *buffer = NULL;
4866 uint32 offered = q_u->offered;
4867 uint32 *needed = &r_u->needed;
4868 uint32 *returned = &r_u->returned;
4871 print_queue_struct *queue=NULL;
4872 print_status_struct prt_status;
4874 /* that's an [in out] buffer */
4875 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4876 buffer = r_u->buffer;
4878 DEBUG(4,("_spoolss_enumjobs\n"));
4880 ZERO_STRUCT(prt_status);
4885 if (!get_printer_snum(handle, &snum))
4886 return ERROR_INVALID_HANDLE;
4888 *returned = print_queue_status(snum, &queue, &prt_status);
4889 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4891 if (*returned == 0) {
4893 return NT_STATUS_NO_PROBLEMO;
4898 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4900 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4904 return ERROR_INVALID_LEVEL;
4908 /****************************************************************************
4909 ****************************************************************************/
4911 uint32 _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
4916 /****************************************************************************
4917 ****************************************************************************/
4919 uint32 _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
4921 POLICY_HND *handle = &q_u->handle;
4922 uint32 jobid = q_u->jobid;
4923 /* uint32 level = q_u->level; - notused. */
4924 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
4925 uint32 command = q_u->command;
4927 struct current_user user;
4928 print_status_struct prt_status;
4929 int snum, errcode = ERROR_INVALID_FUNCTION;
4931 memset(&prt_status, 0, sizeof(prt_status));
4933 if (!get_printer_snum(handle, &snum)) {
4934 return ERROR_INVALID_HANDLE;
4937 if (!print_job_exists(jobid)) {
4938 return ERROR_INVALID_PRINTER_NAME;
4941 get_current_user(&user, p);
4944 case JOB_CONTROL_CANCEL:
4945 case JOB_CONTROL_DELETE:
4946 if (print_job_delete(&user, jobid, &errcode)) {
4950 case JOB_CONTROL_PAUSE:
4951 if (print_job_pause(&user, jobid, &errcode)) {
4955 case JOB_CONTROL_RESTART:
4956 case JOB_CONTROL_RESUME:
4957 if (print_job_resume(&user, jobid, &errcode)) {
4962 return ERROR_INVALID_LEVEL;
4968 /****************************************************************************
4969 Enumerates all printer drivers at level 1.
4970 ****************************************************************************/
4971 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4976 fstring *list = NULL;
4978 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4979 DRIVER_INFO_1 *driver_info_1=NULL;
4983 #define MAX_VERSION 4
4985 for (version=0; version<MAX_VERSION; version++) {
4987 ndrivers=get_ntdrivers(&list, architecture, version);
4988 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4991 return ERROR_NOT_ENOUGH_MEMORY;
4994 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4996 return ERROR_NOT_ENOUGH_MEMORY;
5000 for (i=0; i<ndrivers; i++) {
5002 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5003 ZERO_STRUCT(driver);
5004 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5008 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5009 free_a_printer_driver(driver, 3);
5012 *returned+=ndrivers;
5016 /* check the required size. */
5017 for (i=0; i<*returned; i++) {
5018 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5019 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5022 if (!alloc_buffer_size(buffer, *needed)) {
5023 safe_free(driver_info_1);
5024 return ERROR_INSUFFICIENT_BUFFER;
5027 /* fill the buffer with the form structures */
5028 for (i=0; i<*returned; i++) {
5029 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5030 new_smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5033 safe_free(driver_info_1);
5035 if (*needed > offered) {
5037 return ERROR_INSUFFICIENT_BUFFER;
5040 return NT_STATUS_NO_PROBLEMO;
5043 /****************************************************************************
5044 Enumerates all printer drivers at level 2.
5045 ****************************************************************************/
5046 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5051 fstring *list = NULL;
5053 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5054 DRIVER_INFO_2 *driver_info_2=NULL;
5058 #define MAX_VERSION 4
5060 for (version=0; version<MAX_VERSION; version++) {
5062 ndrivers=get_ntdrivers(&list, architecture, version);
5063 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5066 return ERROR_NOT_ENOUGH_MEMORY;
5069 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5071 return ERROR_NOT_ENOUGH_MEMORY;
5075 for (i=0; i<ndrivers; i++) {
5078 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5079 ZERO_STRUCT(driver);
5080 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5084 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5085 free_a_printer_driver(driver, 3);
5088 *returned+=ndrivers;
5092 /* check the required size. */
5093 for (i=0; i<*returned; i++) {
5094 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5095 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5098 if (!alloc_buffer_size(buffer, *needed)) {
5099 safe_free(driver_info_2);
5100 return ERROR_INSUFFICIENT_BUFFER;
5103 /* fill the buffer with the form structures */
5104 for (i=0; i<*returned; i++) {
5105 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5106 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5109 safe_free(driver_info_2);
5111 if (*needed > offered) {
5113 return ERROR_INSUFFICIENT_BUFFER;
5116 return NT_STATUS_NO_PROBLEMO;
5119 /****************************************************************************
5120 Enumerates all printer drivers at level 3.
5121 ****************************************************************************/
5122 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5127 fstring *list = NULL;
5129 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5130 DRIVER_INFO_3 *driver_info_3=NULL;
5134 #define MAX_VERSION 4
5136 for (version=0; version<MAX_VERSION; version++) {
5138 ndrivers=get_ntdrivers(&list, architecture, version);
5139 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5142 return ERROR_NOT_ENOUGH_MEMORY;
5145 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5147 return ERROR_NOT_ENOUGH_MEMORY;
5151 for (i=0; i<ndrivers; i++) {
5154 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5155 ZERO_STRUCT(driver);
5156 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5160 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5161 free_a_printer_driver(driver, 3);
5164 *returned+=ndrivers;
5168 /* check the required size. */
5169 for (i=0; i<*returned; i++) {
5170 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5171 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5174 if (!alloc_buffer_size(buffer, *needed)) {
5175 safe_free(driver_info_3);
5176 return ERROR_INSUFFICIENT_BUFFER;
5179 /* fill the buffer with the driver structures */
5180 for (i=0; i<*returned; i++) {
5181 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5182 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5185 for (i=0; i<*returned; i++)
5186 safe_free(driver_info_3[i].dependentfiles);
5188 safe_free(driver_info_3);
5190 if (*needed > offered) {
5192 return ERROR_INSUFFICIENT_BUFFER;
5195 return NT_STATUS_NO_PROBLEMO;
5198 /****************************************************************************
5199 Enumerates all printer drivers.
5200 ****************************************************************************/
5202 uint32 _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5204 /* UNISTR2 *name = &q_u->name; - notused. */
5205 UNISTR2 *environment = &q_u->environment;
5206 uint32 level = q_u->level;
5207 NEW_BUFFER *buffer = NULL;
5208 uint32 offered = q_u->offered;
5209 uint32 *needed = &r_u->needed;
5210 uint32 *returned = &r_u->returned;
5212 fstring *list = NULL;
5214 fstring architecture;
5216 /* that's an [in out] buffer */
5217 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5218 buffer = r_u->buffer;
5220 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5221 fstrcpy(servername, global_myname);
5225 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5229 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5231 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5233 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5237 return ERROR_INVALID_LEVEL;
5241 /****************************************************************************
5242 ****************************************************************************/
5244 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5246 form->flag=list->flag;
5247 init_unistr(&form->name, list->name);
5248 form->width=list->width;
5249 form->length=list->length;
5250 form->left=list->left;
5251 form->top=list->top;
5252 form->right=list->right;
5253 form->bottom=list->bottom;
5256 /****************************************************************************
5257 ****************************************************************************/
5259 uint32 _new_spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5261 /* POLICY_HND *handle = &q_u->handle; - notused. */
5262 uint32 level = q_u->level;
5263 NEW_BUFFER *buffer = NULL;
5264 uint32 offered = q_u->offered;
5265 uint32 *needed = &r_u->needed;
5266 uint32 *numofforms = &r_u->numofforms;
5268 nt_forms_struct *list=NULL;
5273 /* that's an [in out] buffer */
5274 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5275 buffer = r_u->buffer;
5277 DEBUG(4,("_new_spoolss_enumforms\n"));
5278 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5279 DEBUGADD(5,("Info level [%d]\n", level));
5281 *numofforms = get_ntforms(&list);
5282 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
5284 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
5288 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5290 return ERROR_NOT_ENOUGH_MEMORY;
5293 /* construct the list of form structures */
5294 for (i=0; i<*numofforms; i++) {
5295 DEBUGADD(6,("Filling form number [%d]\n",i));
5296 fill_form_1(&forms_1[i], &list[i]);
5301 /* check the required size. */
5302 for (i=0; i<*numofforms; i++) {
5303 DEBUGADD(6,("adding form [%d]'s size\n",i));
5304 buffer_size += spoolss_size_form_1(&forms_1[i]);
5307 *needed=buffer_size;
5309 if (!alloc_buffer_size(buffer, buffer_size)){
5311 return ERROR_INSUFFICIENT_BUFFER;
5314 /* fill the buffer with the form structures */
5315 for (i=0; i<*numofforms; i++) {
5316 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5317 new_smb_io_form_1("", buffer, &forms_1[i], 0);
5322 if (*needed > offered) {
5324 return ERROR_INSUFFICIENT_BUFFER;
5327 return NT_STATUS_NO_PROBLEMO;
5331 return ERROR_INVALID_LEVEL;
5336 /****************************************************************************
5337 ****************************************************************************/
5339 uint32 _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5341 /* POLICY_HND *handle = &q_u->handle; - notused. */
5342 uint32 level = q_u->level;
5343 UNISTR2 *uni_formname = &q_u->formname;
5344 NEW_BUFFER *buffer = NULL;
5345 uint32 offered = q_u->offered;
5346 uint32 *needed = &r_u->needed;
5348 nt_forms_struct *list=NULL;
5354 /* that's an [in out] buffer */
5355 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5356 buffer = r_u->buffer;
5358 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5360 DEBUG(4,("_spoolss_getform\n"));
5361 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5362 DEBUGADD(5,("Info level [%d]\n", level));
5364 numofforms = get_ntforms(&list);
5365 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5367 if (numofforms == 0)
5368 return ERROR_NO_MORE_ITEMS;
5373 /* Check if the requested name is in the list of form structures */
5374 for (i=0; i<numofforms; i++) {
5376 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5378 if (strequal(form_name, list[i].name)) {
5379 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5380 fill_form_1(&form_1, &list[i]);
5387 /* check the required size. */
5389 *needed=spoolss_size_form_1(&form_1);
5391 if (!alloc_buffer_size(buffer, buffer_size)){
5392 return ERROR_INSUFFICIENT_BUFFER;
5395 if (*needed > offered) {
5396 return ERROR_INSUFFICIENT_BUFFER;
5399 /* fill the buffer with the form structures */
5400 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5401 new_smb_io_form_1("", buffer, &form_1, 0);
5403 return NT_STATUS_NO_PROBLEMO;
5407 return ERROR_INVALID_LEVEL;
5411 /****************************************************************************
5412 ****************************************************************************/
5413 static void fill_port_1(PORT_INFO_1 *port, char *name)
5415 init_unistr(&port->port_name, name);
5418 /****************************************************************************
5419 ****************************************************************************/
5420 static void fill_port_2(PORT_INFO_2 *port, char *name)
5422 init_unistr(&port->port_name, name);
5423 init_unistr(&port->monitor_name, "Local Monitor");
5424 init_unistr(&port->description, "Local Port");
5425 #define PORT_TYPE_WRITE 1
5426 port->port_type=PORT_TYPE_WRITE;
5430 /****************************************************************************
5432 ****************************************************************************/
5433 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5435 PORT_INFO_1 *ports=NULL;
5438 if (*lp_enumports_cmd()) {
5439 pid_t local_pid = sys_getpid();
5440 char *cmd = lp_enumports_cmd();
5448 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5449 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5453 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5454 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5457 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5458 ret = smbrun(command, tmp_file, False);
5459 DEBUG(10,("Returned [%d]\n", ret));
5462 /* Is this the best error to return here? */
5463 return ERROR_ACCESS_DENIED;
5467 qlines = file_lines_load(tmp_file, &numlines,True);
5468 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5469 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5473 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5474 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5475 file_lines_free(qlines);
5476 return ERROR_NOT_ENOUGH_MEMORY;
5479 for (i=0; i<numlines; i++) {
5480 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5481 fill_port_1(&ports[i], qlines[i]);
5484 file_lines_free(qlines);
5487 *returned = numlines;
5490 *returned = 1; /* Sole Samba port returned. */
5492 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5493 return ERROR_NOT_ENOUGH_MEMORY;
5495 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5497 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5500 /* check the required size. */
5501 for (i=0; i<*returned; i++) {
5502 DEBUGADD(6,("adding port [%d]'s size\n", i));
5503 *needed += spoolss_size_port_info_1(&ports[i]);
5506 if (!alloc_buffer_size(buffer, *needed)) {
5508 return ERROR_INSUFFICIENT_BUFFER;
5511 /* fill the buffer with the ports structures */
5512 for (i=0; i<*returned; i++) {
5513 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5514 new_smb_io_port_1("", buffer, &ports[i], 0);
5519 if (*needed > offered) {
5521 return ERROR_INSUFFICIENT_BUFFER;
5524 return NT_STATUS_NO_PROBLEMO;
5527 /****************************************************************************
5529 ****************************************************************************/
5531 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5533 PORT_INFO_2 *ports=NULL;
5536 if (*lp_enumports_cmd()) {
5537 pid_t local_pid = sys_getpid();
5538 char *cmd = lp_enumports_cmd();
5546 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5547 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5551 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5552 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5555 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5556 ret = smbrun(command, tmp_file, False);
5557 DEBUGADD(10,("returned [%d]\n", ret));
5560 /* Is this the best error to return here? */
5561 return ERROR_ACCESS_DENIED;
5565 qlines = file_lines_load(tmp_file, &numlines,True);
5566 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5567 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5571 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5572 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5573 file_lines_free(qlines);
5574 return ERROR_NOT_ENOUGH_MEMORY;
5577 for (i=0; i<numlines; i++) {
5578 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5579 fill_port_2(&(ports[i]), qlines[i]);
5582 file_lines_free(qlines);
5585 *returned = numlines;
5591 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5592 return ERROR_NOT_ENOUGH_MEMORY;
5594 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5596 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5599 /* check the required size. */
5600 for (i=0; i<*returned; i++) {
5601 DEBUGADD(6,("adding port [%d]'s size\n", i));
5602 *needed += spoolss_size_port_info_2(&ports[i]);
5605 if (!alloc_buffer_size(buffer, *needed)) {
5607 return ERROR_INSUFFICIENT_BUFFER;
5610 /* fill the buffer with the ports structures */
5611 for (i=0; i<*returned; i++) {
5612 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5613 new_smb_io_port_2("", buffer, &ports[i], 0);
5618 if (*needed > offered) {
5620 return ERROR_INSUFFICIENT_BUFFER;
5623 return NT_STATUS_NO_PROBLEMO;
5626 /****************************************************************************
5628 ****************************************************************************/
5630 uint32 _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5632 /* UNISTR2 *name = &q_u->name; - notused. */
5633 uint32 level = q_u->level;
5634 NEW_BUFFER *buffer = NULL;
5635 uint32 offered = q_u->offered;
5636 uint32 *needed = &r_u->needed;
5637 uint32 *returned = &r_u->returned;
5639 /* that's an [in out] buffer */
5640 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5641 buffer = r_u->buffer;
5643 DEBUG(4,("_spoolss_enumports\n"));
5650 return enumports_level_1(buffer, offered, needed, returned);
5652 return enumports_level_2(buffer, offered, needed, returned);
5654 return ERROR_INVALID_LEVEL;
5658 /****************************************************************************
5659 ****************************************************************************/
5660 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
5661 const SPOOL_PRINTER_INFO_LEVEL *info,
5662 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5663 uint32 user_switch, const SPOOL_USER_CTR *user,
5666 NT_PRINTER_INFO_LEVEL *printer = NULL;
5670 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5671 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5672 return ERROR_NOT_ENOUGH_MEMORY;
5675 ZERO_STRUCTP(printer);
5677 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5678 convert_printer_info(info, printer, 2);
5680 if (*lp_addprinter_cmd() )
5681 if ( !add_printer_hook(printer) ) {
5682 free_a_printer(&printer,2);
5683 return ERROR_ACCESS_DENIED;
5686 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5687 printer->info_2->sharename);
5689 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5690 free_a_printer(&printer,2);
5691 return ERROR_ACCESS_DENIED;
5694 /* you must be a printer admin to add a new printer */
5695 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5696 free_a_printer(&printer,2);
5697 return ERROR_ACCESS_DENIED;
5701 * Do sanity check on the requested changes for Samba.
5704 if (!check_printer_ok(printer->info_2, snum)) {
5705 free_a_printer(&printer,2);
5706 return ERROR_INVALID_PARAMETER;
5709 /* write the ASCII on disk */
5710 if (add_a_printer(*printer, 2) != 0) {
5711 free_a_printer(&printer,2);
5712 return ERROR_ACCESS_DENIED;
5715 if (!open_printer_hnd(handle, name)) {
5716 /* Handle open failed - remove addition. */
5717 del_a_printer(printer->info_2->sharename);
5718 free_a_printer(&printer,2);
5719 return ERROR_ACCESS_DENIED;
5722 free_a_printer(&printer,2);
5724 srv_spoolss_sendnotify(handle);
5726 return NT_STATUS_NO_PROBLEMO;
5729 /****************************************************************************
5730 ****************************************************************************/
5732 uint32 _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5734 UNISTR2 *uni_srv_name = &q_u->server_name;
5735 uint32 level = q_u->level;
5736 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5737 uint32 unk0 = q_u->unk0;
5738 uint32 unk1 = q_u->unk1;
5739 uint32 unk2 = q_u->unk2;
5740 uint32 unk3 = q_u->unk3;
5741 uint32 user_switch = q_u->user_switch;
5742 SPOOL_USER_CTR *user = &q_u->user_ctr;
5743 POLICY_HND *handle = &r_u->handle;
5747 /* we don't handle yet */
5748 /* but I know what to do ... */
5749 return ERROR_INVALID_LEVEL;
5751 return spoolss_addprinterex_level_2(uni_srv_name, info,
5752 unk0, unk1, unk2, unk3,
5753 user_switch, user, handle);
5755 return ERROR_INVALID_LEVEL;
5759 /****************************************************************************
5760 ****************************************************************************/
5762 uint32 _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5764 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5765 uint32 level = q_u->level;
5766 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5768 uint32 err = NT_STATUS_NO_PROBLEMO;
5769 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5770 struct current_user user;
5772 ZERO_STRUCT(driver);
5774 get_current_user(&user, p);
5776 convert_printer_driver_info(info, &driver, level);
5778 DEBUG(5,("Cleaning driver's information\n"));
5779 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5782 DEBUG(5,("Moving driver to final destination\n"));
5783 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5785 err = ERROR_ACCESS_DENIED;
5789 if (add_a_printer_driver(driver, level)!=0) {
5790 err = ERROR_ACCESS_DENIED;
5795 free_a_printer_driver(driver, level);
5799 /****************************************************************************
5800 ****************************************************************************/
5801 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5803 init_unistr(&info->name, name);
5806 /****************************************************************************
5807 ****************************************************************************/
5808 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5812 pstring short_archi;
5813 DRIVER_DIRECTORY_1 *info=NULL;
5815 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5817 if (get_short_archi(short_archi, long_archi)==FALSE)
5818 return ERROR_INVALID_ENVIRONMENT;
5820 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5821 return ERROR_NOT_ENOUGH_MEMORY;
5823 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5825 DEBUG(4,("printer driver directory: [%s]\n", path));
5827 fill_driverdir_1(info, path);
5829 *needed += spoolss_size_driverdir_info_1(info);
5831 if (!alloc_buffer_size(buffer, *needed)) {
5833 return ERROR_INSUFFICIENT_BUFFER;
5836 new_smb_io_driverdir_1("", buffer, info, 0);
5840 if (*needed > offered)
5841 return ERROR_INSUFFICIENT_BUFFER;
5843 return NT_STATUS_NO_PROBLEMO;
5846 /****************************************************************************
5847 ****************************************************************************/
5849 uint32 _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
5851 UNISTR2 *name = &q_u->name;
5852 UNISTR2 *uni_environment = &q_u->environment;
5853 uint32 level = q_u->level;
5854 NEW_BUFFER *buffer = NULL;
5855 uint32 offered = q_u->offered;
5856 uint32 *needed = &r_u->needed;
5858 /* that's an [in out] buffer */
5859 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5860 buffer = r_u->buffer;
5862 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5868 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5870 return ERROR_INVALID_LEVEL;
5874 /****************************************************************************
5875 ****************************************************************************/
5877 uint32 _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
5879 POLICY_HND *handle = &q_u->handle;
5880 uint32 idx = q_u->index;
5881 uint32 in_value_len = q_u->valuesize;
5882 uint32 in_data_len = q_u->datasize;
5883 uint32 *out_max_value_len = &r_u->valuesize;
5884 uint16 **out_value = &r_u->value;
5885 uint32 *out_value_len = &r_u->realvaluesize;
5886 uint32 *out_type = &r_u->type;
5887 uint32 *out_max_data_len = &r_u->datasize;
5888 uint8 **data_out = &r_u->data;
5889 uint32 *out_data_len = &r_u->realdatasize;
5891 NT_PRINTER_INFO_LEVEL *printer = NULL;
5896 uint32 biggest_valuesize;
5897 uint32 biggest_datasize;
5899 Printer_entry *Printer = find_printer_index_by_hnd(handle);
5904 ZERO_STRUCT(printer);
5906 *out_max_value_len=0;
5912 *out_max_data_len=0;
5916 DEBUG(5,("spoolss_enumprinterdata\n"));
5918 if (!OPEN_HANDLE(Printer)) {
5919 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5920 return ERROR_INVALID_HANDLE;
5923 if (!get_printer_snum(handle, &snum))
5924 return ERROR_INVALID_HANDLE;
5926 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5927 return ERROR_INVALID_HANDLE;
5930 * The NT machine wants to know the biggest size of value and data
5932 * cf: MSDN EnumPrinterData remark section
5934 if ( (in_value_len==0) && (in_data_len==0) ) {
5935 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5939 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5940 * if this parameter size doesn't exist.
5941 * Ok - my opinion here is that the client is not asking for the greatest
5942 * possible size of all the parameters, but is asking specifically for the size needed
5943 * for this specific parameter. In that case we can remove the loop below and
5944 * simplify this lookup code considerably. JF - comments welcome. JRA.
5947 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5949 free_a_printer(&printer, 2);
5950 return ERROR_NO_MORE_ITEMS;
5958 biggest_valuesize=0;
5961 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5962 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5963 if (data_len > biggest_datasize) biggest_datasize=data_len;
5965 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5973 * I think this is correct, it doesn't break APW and
5974 * allows Gerald's Win32 test programs to work correctly,
5975 * but may need altering.... JRA.
5978 if (param_index == 0) {
5979 /* No parameters found. */
5980 free_a_printer(&printer, 2);
5981 return ERROR_NO_MORE_ITEMS;
5984 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5985 *out_value_len=2*(1+biggest_valuesize);
5986 *out_data_len=biggest_datasize;
5988 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5990 free_a_printer(&printer, 2);
5991 return NT_STATUS_NO_PROBLEMO;
5995 * the value len is wrong in NT sp3
5996 * that's the number of bytes not the number of unicode chars
5999 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6001 free_a_printer(&printer, 2);
6002 return ERROR_NO_MORE_ITEMS;
6005 free_a_printer(&printer, 2);
6009 * - counted in bytes in the request
6010 * - counted in UNICODE chars in the max reply
6011 * - counted in bytes in the real size
6013 * take a pause *before* coding not *during* coding
6016 *out_max_value_len=(in_value_len/sizeof(uint16));
6017 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6019 return ERROR_NOT_ENOUGH_MEMORY;
6022 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
6026 /* the data is counted in bytes */
6027 *out_max_data_len=in_data_len;
6028 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6030 return ERROR_NOT_ENOUGH_MEMORY;
6033 memcpy(*data_out, data, (size_t)data_len);
6034 *out_data_len=data_len;
6038 return NT_STATUS_NO_PROBLEMO;
6041 /****************************************************************************
6042 ****************************************************************************/
6044 uint32 _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6046 POLICY_HND *handle = &q_u->handle;
6047 UNISTR2 *value = &q_u->value;
6048 uint32 type = q_u->type;
6049 /* uint32 max_len = q_u->max_len; - notused. */
6050 uint8 *data = q_u->data;
6051 uint32 real_len = q_u->real_len;
6052 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6054 NT_PRINTER_INFO_LEVEL *printer = NULL;
6055 NT_PRINTER_PARAM *param = NULL, old_param;
6057 uint32 status = 0x0;
6058 Printer_entry *Printer=find_printer_index_by_hnd(handle);
6060 DEBUG(5,("spoolss_setprinterdata\n"));
6062 if (!OPEN_HANDLE(Printer)) {
6063 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6064 return ERROR_INVALID_HANDLE;
6067 if (!get_printer_snum(handle, &snum))
6068 return ERROR_INVALID_HANDLE;
6070 status = get_a_printer(&printer, 2, lp_servicename(snum));
6072 return ERROR_INVALID_NAME;
6074 convert_specific_param(¶m, value , type, data, real_len);
6076 /* Check if we are making any changes or not. Return true if
6077 nothing is actually changing. */
6079 ZERO_STRUCT(old_param);
6081 if (get_specific_param(*printer, 2, param->value, &old_param.data,
6082 &old_param.type, (unsigned int *)&old_param.data_len)) {
6084 if (param->type == old_param.type &&
6085 param->data_len == old_param.data_len &&
6086 memcmp(param->data, old_param.data,
6087 old_param.data_len) == 0) {
6089 DEBUG(3, ("setprinterdata hasn't changed\n"));
6090 status = NT_STATUS_NO_PROBLEMO;
6097 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6098 DEBUG(3, ("security descriptor change denied by existing "
6099 "security descriptor\n"));
6100 status = ERROR_ACCESS_DENIED;
6104 unlink_specific_param_if_exist(printer->info_2, param);
6106 add_a_specific_param(printer->info_2, ¶m);
6107 status = mod_a_printer(*printer, 2);
6110 free_a_printer(&printer, 2);
6112 free_nt_printer_param(¶m);
6113 safe_free(old_param.data);
6118 /****************************************************************************
6119 ****************************************************************************/
6121 uint32 _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6123 POLICY_HND *handle = &q_u->handle;
6124 UNISTR2 *value = &q_u->valuename;
6126 NT_PRINTER_INFO_LEVEL *printer = NULL;
6127 NT_PRINTER_PARAM param;
6129 uint32 status = 0x0;
6130 Printer_entry *Printer=find_printer_index_by_hnd(handle);
6132 DEBUG(5,("spoolss_deleteprinterdata\n"));
6134 if (!OPEN_HANDLE(Printer)) {
6135 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6136 return ERROR_INVALID_HANDLE;
6139 if (!get_printer_snum(handle, &snum))
6140 return ERROR_INVALID_HANDLE;
6142 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6143 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6144 "change denied by existing security descriptor\n"));
6145 return ERROR_ACCESS_DENIED;
6148 status = get_a_printer(&printer, 2, lp_servicename(snum));
6150 return ERROR_INVALID_NAME;
6152 ZERO_STRUCTP(¶m);
6153 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6155 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
6156 status = ERROR_INVALID_PARAMETER;
6158 status = mod_a_printer(*printer, 2);
6160 free_a_printer(&printer, 2);
6164 /****************************************************************************
6165 ****************************************************************************/
6167 uint32 _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6169 POLICY_HND *handle = &q_u->handle;
6170 /* uint32 level = q_u->level; - notused. */
6171 FORM *form = &q_u->form;
6174 nt_forms_struct *list=NULL;
6175 Printer_entry *Printer = find_printer_index_by_hnd(handle);
6177 DEBUG(5,("spoolss_addform\n"));
6179 if (!OPEN_HANDLE(Printer)) {
6180 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6181 return ERROR_INVALID_HANDLE;
6184 count=get_ntforms(&list);
6185 if(!add_a_form(&list, form, &count))
6186 return ERROR_NOT_ENOUGH_MEMORY;
6187 write_ntforms(&list, count);
6194 /****************************************************************************
6195 ****************************************************************************/
6197 uint32 _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6199 POLICY_HND *handle = &q_u->handle;
6200 UNISTR2 *form_name = &q_u->name;
6204 nt_forms_struct *list=NULL;
6205 Printer_entry *Printer = find_printer_index_by_hnd(handle);
6207 DEBUG(5,("spoolss_deleteform\n"));
6209 if (!OPEN_HANDLE(Printer)) {
6210 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6211 return ERROR_INVALID_HANDLE;
6214 count = get_ntforms(&list);
6215 if(!delete_a_form(&list, form_name, &count, &ret))
6216 return ERROR_INVALID_PARAMETER;
6223 /****************************************************************************
6224 ****************************************************************************/
6226 uint32 _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6228 POLICY_HND *handle = &q_u->handle;
6229 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6230 /* uint32 level = q_u->level; - notused. */
6231 FORM *form = &q_u->form;
6234 nt_forms_struct *list=NULL;
6235 Printer_entry *Printer = find_printer_index_by_hnd(handle);
6237 DEBUG(5,("spoolss_setform\n"));
6239 if (!OPEN_HANDLE(Printer)) {
6240 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6241 return ERROR_INVALID_HANDLE;
6243 count=get_ntforms(&list);
6244 update_a_form(&list, form, count);
6245 write_ntforms(&list, count);
6252 /****************************************************************************
6253 enumprintprocessors level 1.
6254 ****************************************************************************/
6255 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6257 PRINTPROCESSOR_1 *info_1=NULL;
6259 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6260 return ERROR_NOT_ENOUGH_MEMORY;
6264 init_unistr(&info_1->name, "winprint");
6266 *needed += spoolss_size_printprocessor_info_1(info_1);
6268 if (!alloc_buffer_size(buffer, *needed))
6269 return ERROR_INSUFFICIENT_BUFFER;
6271 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6275 if (*needed > offered) {
6277 return ERROR_INSUFFICIENT_BUFFER;
6280 return NT_STATUS_NO_PROBLEMO;
6283 /****************************************************************************
6284 ****************************************************************************/
6286 uint32 _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6288 /* UNISTR2 *name = &q_u->name; - notused. */
6289 /* UNISTR2 *environment = &q_u->environment; - notused. */
6290 uint32 level = q_u->level;
6291 NEW_BUFFER *buffer = NULL;
6292 uint32 offered = q_u->offered;
6293 uint32 *needed = &r_u->needed;
6294 uint32 *returned = &r_u->returned;
6296 /* that's an [in out] buffer */
6297 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6298 buffer = r_u->buffer;
6300 DEBUG(5,("spoolss_enumprintprocessors\n"));
6303 * Enumerate the print processors ...
6305 * Just reply with "winprint", to keep NT happy
6306 * and I can use my nice printer checker.
6314 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6316 return ERROR_INVALID_LEVEL;
6320 /****************************************************************************
6321 enumprintprocdatatypes level 1.
6322 ****************************************************************************/
6323 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6325 PRINTPROCDATATYPE_1 *info_1=NULL;
6327 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6328 return ERROR_NOT_ENOUGH_MEMORY;
6332 init_unistr(&info_1->name, "RAW");
6334 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6336 if (!alloc_buffer_size(buffer, *needed))
6337 return ERROR_INSUFFICIENT_BUFFER;
6339 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6343 if (*needed > offered) {
6345 return ERROR_INSUFFICIENT_BUFFER;
6348 return NT_STATUS_NO_PROBLEMO;
6351 /****************************************************************************
6352 ****************************************************************************/
6354 uint32 _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6356 /* UNISTR2 *name = &q_u->name; - notused. */
6357 /* UNISTR2 *processor = &q_u->processor; - notused. */
6358 uint32 level = q_u->level;
6359 NEW_BUFFER *buffer = NULL;
6360 uint32 offered = q_u->offered;
6361 uint32 *needed = &r_u->needed;
6362 uint32 *returned = &r_u->returned;
6364 /* that's an [in out] buffer */
6365 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6366 buffer = r_u->buffer;
6368 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6375 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6377 return ERROR_INVALID_LEVEL;
6381 /****************************************************************************
6382 enumprintmonitors level 1.
6383 ****************************************************************************/
6385 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6387 PRINTMONITOR_1 *info_1=NULL;
6389 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6390 return ERROR_NOT_ENOUGH_MEMORY;
6394 init_unistr(&info_1->name, "Local Port");
6396 *needed += spoolss_size_printmonitor_info_1(info_1);
6398 if (!alloc_buffer_size(buffer, *needed))
6399 return ERROR_INSUFFICIENT_BUFFER;
6401 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6405 if (*needed > offered) {
6407 return ERROR_INSUFFICIENT_BUFFER;
6410 return NT_STATUS_NO_PROBLEMO;
6413 /****************************************************************************
6414 enumprintmonitors level 2.
6415 ****************************************************************************/
6416 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6418 PRINTMONITOR_2 *info_2=NULL;
6420 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6421 return ERROR_NOT_ENOUGH_MEMORY;
6425 init_unistr(&info_2->name, "Local Port");
6426 init_unistr(&info_2->environment, "Windows NT X86");
6427 init_unistr(&info_2->dll_name, "localmon.dll");
6429 *needed += spoolss_size_printmonitor_info_2(info_2);
6431 if (!alloc_buffer_size(buffer, *needed))
6432 return ERROR_INSUFFICIENT_BUFFER;
6434 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6438 if (*needed > offered) {
6440 return ERROR_INSUFFICIENT_BUFFER;
6443 return NT_STATUS_NO_PROBLEMO;
6446 /****************************************************************************
6447 ****************************************************************************/
6449 uint32 _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6451 /* UNISTR2 *name = &q_u->name; - notused. */
6452 uint32 level = q_u->level;
6453 NEW_BUFFER *buffer = NULL;
6454 uint32 offered = q_u->offered;
6455 uint32 *needed = &r_u->needed;
6456 uint32 *returned = &r_u->returned;
6458 /* that's an [in out] buffer */
6459 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6460 buffer = r_u->buffer;
6462 DEBUG(5,("spoolss_enumprintmonitors\n"));
6465 * Enumerate the print monitors ...
6467 * Just reply with "Local Port", to keep NT happy
6468 * and I can use my nice printer checker.
6476 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6478 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6480 return ERROR_INVALID_LEVEL;
6484 /****************************************************************************
6485 ****************************************************************************/
6486 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6490 JOB_INFO_1 *info_1=NULL;
6492 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6494 if (info_1 == NULL) {
6496 return ERROR_NOT_ENOUGH_MEMORY;
6499 for (i=0; i<count && found==False; i++) {
6500 if (queue[i].job==(int)jobid)
6507 /* I shoud reply something else ... I can't find the good one */
6508 return NT_STATUS_NO_PROBLEMO;
6511 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6515 *needed += spoolss_size_job_info_1(info_1);
6517 if (!alloc_buffer_size(buffer, *needed)) {
6519 return ERROR_INSUFFICIENT_BUFFER;
6522 new_smb_io_job_info_1("", buffer, info_1, 0);
6526 if (*needed > offered)
6527 return ERROR_INSUFFICIENT_BUFFER;
6529 return NT_STATUS_NO_PROBLEMO;
6533 /****************************************************************************
6534 ****************************************************************************/
6535 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6540 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6542 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6544 ZERO_STRUCTP(info_2);
6546 if (info_2 == NULL) {
6548 return ERROR_NOT_ENOUGH_MEMORY;
6551 for (i=0; i<count && found==False; i++) {
6552 if (queue[i].job==(int)jobid)
6559 /* I shoud reply something else ... I can't find the good one */
6560 return NT_STATUS_NO_PROBLEMO;
6563 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6565 return ERROR_NOT_ENOUGH_MEMORY;
6568 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6570 free_a_printer(&ntprinter, 2);
6573 *needed += spoolss_size_job_info_2(info_2);
6575 if (!alloc_buffer_size(buffer, *needed)) {
6577 return ERROR_INSUFFICIENT_BUFFER;
6580 new_smb_io_job_info_2("", buffer, info_2, 0);
6582 free_job_info_2(info_2);
6585 if (*needed > offered)
6586 return ERROR_INSUFFICIENT_BUFFER;
6588 return NT_STATUS_NO_PROBLEMO;
6591 /****************************************************************************
6592 ****************************************************************************/
6594 uint32 _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6596 POLICY_HND *handle = &q_u->handle;
6597 uint32 jobid = q_u->jobid;
6598 uint32 level = q_u->level;
6599 NEW_BUFFER *buffer = NULL;
6600 uint32 offered = q_u->offered;
6601 uint32 *needed = &r_u->needed;
6605 print_queue_struct *queue=NULL;
6606 print_status_struct prt_status;
6608 /* that's an [in out] buffer */
6609 new_spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6610 buffer = r_u->buffer;
6612 DEBUG(5,("spoolss_getjob\n"));
6614 memset(&prt_status, 0, sizeof(prt_status));
6618 if (!get_printer_snum(handle, &snum))
6619 return ERROR_INVALID_HANDLE;
6621 count = print_queue_status(snum, &queue, &prt_status);
6623 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6624 count, prt_status.status, prt_status.message));
6628 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6630 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6633 return ERROR_INVALID_LEVEL;