2 * Unix SMB/Netbios implementation.
4 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-2000,
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7 * Copyright (C) Jean François Micouleau 1998-2000.
8 * Copyright (C) Jeremy Allison 2001.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int DEBUGLEVEL;
28 extern pstring global_myname;
30 #ifndef MAX_OPEN_PRINTER_EXS
31 #define MAX_OPEN_PRINTER_EXS 50
34 #define PRINTER_HANDLE_IS_PRINTER 0
35 #define PRINTER_HANDLE_IS_PRINTSERVER 1
37 /* structure to store the printer handles */
38 /* and a reference to what it's pointing to */
39 /* and the notify info asked about */
40 /* that's the central struct */
41 typedef struct _Printer{
42 BOOL document_started;
44 int jobid; /* jobid in printing backend */
48 fstring printerservername;
57 SPOOL_NOTIFY_OPTION *option;
58 POLICY_HND client_hnd;
59 uint32 client_connected;
67 typedef struct _counter_printer_0 {
75 static ubi_dlList counter_list;
77 static struct cli_state cli;
78 static uint32 smb_connections=0;
80 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
82 /* translate between internal status numbers and NT status numbers */
83 static int nt_printj_status(int v)
89 return JOB_STATUS_PAUSED;
91 return JOB_STATUS_SPOOLING;
93 return JOB_STATUS_PRINTING;
95 return JOB_STATUS_ERROR;
97 return JOB_STATUS_DELETING;
99 return JOB_STATUS_OFFLINE;
101 return JOB_STATUS_PAPEROUT;
103 return JOB_STATUS_PRINTED;
105 return JOB_STATUS_DELETED;
107 return JOB_STATUS_BLOCKED;
108 case LPQ_USER_INTERVENTION:
109 return JOB_STATUS_USER_INTERVENTION;
114 static int nt_printq_status(int v)
118 return PRINTER_STATUS_PAUSED;
127 /****************************************************************************
128 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
129 ****************************************************************************/
131 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
133 SPOOL_NOTIFY_OPTION *sp = *pp;
141 safe_free(sp->ctr.type);
146 /***************************************************************************
147 Disconnect from the client
148 ****************************************************************************/
150 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
154 /* weird if the test succeds !!! */
155 if (smb_connections==0) {
156 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
160 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
161 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
163 /* if it's the last connection, deconnect the IPC$ share */
164 if (smb_connections==1) {
165 if(!spoolss_disconnect_from_client(&cli))
168 message_deregister(MSG_PRINTER_NOTIFY);
174 /****************************************************************************
175 Functions to free a printer entry datastruct.
176 ****************************************************************************/
178 static void free_printer_entry(void *ptr)
180 Printer_entry *Printer = (Printer_entry *)ptr;
182 if (Printer->notify.client_connected==True)
183 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
185 Printer->notify.flags=0;
186 Printer->notify.options=0;
187 Printer->notify.localmachine[0]='\0';
188 Printer->notify.printerlocal=0;
189 free_spool_notify_option(&Printer->notify.option);
190 Printer->notify.option=NULL;
191 Printer->notify.client_connected=False;
196 /****************************************************************************
197 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
198 ****************************************************************************/
200 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
202 SPOOL_NOTIFY_OPTION *new_sp = NULL;
207 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
214 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
216 if (!new_sp->ctr.type) {
225 /****************************************************************************
226 find printer index by handle
227 ****************************************************************************/
229 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
231 Printer_entry *find_printer = NULL;
233 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
234 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
241 /****************************************************************************
242 close printer index by handle
243 ****************************************************************************/
245 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
247 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
250 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
254 close_policy_hnd(p, hnd);
259 /****************************************************************************
260 delete a printer given a handle
261 ****************************************************************************/
262 static uint32 delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
264 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
267 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
268 return ERROR_INVALID_HANDLE;
271 if (del_a_printer(Printer->dev.handlename) != 0) {
272 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
273 return ERROR_INVALID_HANDLE;
276 /* Check calling user has permission to delete printer. Note that
277 since we set the snum parameter to -1 only administrators can
278 delete the printer. This stops people with the Full Control
279 permission from deleting the printer. */
281 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
282 DEBUG(3, ("printer delete denied by security descriptor\n"));
283 return ERROR_ACCESS_DENIED;
286 if (*lp_deleteprinter_cmd()) {
288 pid_t local_pid = sys_getpid();
289 char *cmd = lp_deleteprinter_cmd();
296 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
297 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
301 /* Printer->dev.handlename equals portname equals sharename */
302 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
303 Printer->dev.handlename);
304 dos_to_unix(command, True); /* Convert printername to unix-codepage */
305 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
308 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
309 ret = smbrun(command, tmp_file, False);
312 return ERROR_INVALID_HANDLE; /* What to return here? */
314 DEBUGADD(10,("returned [%d]\n", ret));
315 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
318 /* Send SIGHUP to process group... is there a better way? */
321 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
323 return ERROR_SUCCESS;
325 return ERROR_ACCESS_DENIED;
328 return ERROR_SUCCESS;
331 /****************************************************************************
332 return the snum of a printer corresponding to an handle
333 ****************************************************************************/
334 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
336 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
339 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
343 switch (Printer->printer_type) {
344 case PRINTER_HANDLE_IS_PRINTER:
345 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
346 *number = print_queue_snum(Printer->dev.handlename);
347 return (*number != -1);
348 case PRINTER_HANDLE_IS_PRINTSERVER:
355 /****************************************************************************
356 set printer handle type.
357 ****************************************************************************/
358 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
360 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
363 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
367 DEBUG(4,("Setting printer access=%x\n", access_required));
368 Printer->access = access_required;
372 /****************************************************************************
373 Set printer handle type.
374 Check if it's \\server or \\server\printer
375 ****************************************************************************/
377 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
379 DEBUG(3,("Setting printer type=%s\n", handlename));
381 if ( strlen(handlename) < 3 ) {
382 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
386 /* it's a print server */
387 if (!strchr(handlename+2, '\\')) {
388 DEBUGADD(4,("Printer is a print server\n"));
389 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
393 DEBUGADD(4,("Printer is a printer\n"));
394 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
400 /****************************************************************************
401 Set printer handle name.
402 ****************************************************************************/
404 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
406 NT_PRINTER_INFO_LEVEL *printer = NULL;
408 int n_services=lp_numservices();
412 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
414 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
415 ZERO_STRUCT(Printer->dev.printerservername);
416 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
420 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
423 aprinter=strchr(handlename+2, '\\');
426 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
429 * store the Samba share name in it
430 * in back we have the long printer name
431 * need to iterate all the snum and do a
432 * get_a_printer each time to find the printer
433 * faster to do it here than later.
436 for (snum=0;snum<n_services && found==False;snum++) {
439 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
442 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
444 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
447 printername=strchr(printer->info_2->printername+2, '\\');
450 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
451 printer->info_2->printername, aprinter ));
453 if ( strlen(printername) != strlen(aprinter) ) {
454 free_a_printer(&printer, 2);
458 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
459 free_a_printer(&printer, 2);
467 * if we haven't found a printer with the given handlename
468 * then it can be a share name as you can open both \\server\printer and
473 * we still check if the printer description file exists as NT won't be happy
474 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
478 DEBUGADD(5,("Printer not found, checking for share now\n"));
480 for (snum=0;snum<n_services && found==False;snum++) {
482 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
485 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
487 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
490 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
491 printer->info_2->printername, aprinter ));
493 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
494 free_a_printer(&printer, 2);
498 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
499 free_a_printer(&printer, 2);
508 DEBUGADD(4,("Printer not found\n"));
513 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
514 printer->info_2->printername, lp_servicename(snum),snum));
516 ZERO_STRUCT(Printer->dev.handlename);
517 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
519 free_a_printer(&printer, 2);
524 /****************************************************************************
525 find first available printer slot. creates a printer handle for you.
526 ****************************************************************************/
528 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
530 Printer_entry *new_printer;
532 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
534 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
537 ZERO_STRUCTP(new_printer);
539 new_printer->notify.option=NULL;
541 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
542 safe_free(new_printer);
546 if (!set_printer_hnd_printertype(new_printer, name)) {
547 close_printer_handle(p, hnd);
551 if (!set_printer_hnd_name(new_printer, name)) {
552 close_printer_handle(p, hnd);
556 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
561 /********************************************************************
562 Return True is the handle is a print server.
563 ********************************************************************/
565 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
567 Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
572 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
578 /****************************************************************************
579 allocate more memory for a BUFFER.
580 ****************************************************************************/
581 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
589 /* damn, I'm doing the reverse operation of prs_grow() :) */
590 if (buffer_size < prs_data_size(ps))
593 extra_space = buffer_size - prs_data_size(ps);
596 * save the offset and move to the end of the buffer
597 * prs_grow() checks the extra_space against the offset
599 old_offset=prs_offset(ps);
600 prs_set_offset(ps, prs_data_size(ps));
602 if (!prs_grow(ps, extra_space))
605 prs_set_offset(ps, old_offset);
607 buffer->string_at_end=prs_data_size(ps);
612 /***************************************************************************
613 receive the notify message
614 ****************************************************************************/
616 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
620 struct pipes_struct *p;
622 struct handle_list *hl;
625 fstrcpy(printer,buf);
628 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
632 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
635 * We need to enumerate all printers. The handle list is shared
636 * across pipes of the same name, so just find the first open
641 for ( p = get_first_pipe(); p; get_next_pipe(p)) {
642 if (strequal(p->name, "spoolss")) {
643 hl = p->pipe_handles;
649 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
653 /* Iterate the printer list on this pipe. */
654 for (pol = hl->Policy; pol; pol = pol->next ) {
655 Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
661 * if the entry is the given printer or if it's a printerserver
662 * we send the message
665 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
666 if (strcmp(find_printer->dev.handlename, printer))
669 if (find_printer->notify.client_connected==True)
670 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
674 /***************************************************************************
676 ****************************************************************************/
677 static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle)
681 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
684 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
688 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
689 fstrcpy(printer, Printer->dev.handlename);
691 fstrcpy(printer, "");
693 /*srv_spoolss_receive_message(printer);*/
694 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
696 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
701 /********************************************************************
702 * spoolss_open_printer
704 * called from the spoolss dispatcher
705 ********************************************************************/
707 uint32 _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
710 uint32 result = NT_STATUS_NO_PROBLEMO;
713 UNISTR2 *printername = NULL;
714 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
715 /* uint32 user_switch = q_u->user_switch; - notused */
716 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
717 POLICY_HND *handle = &r_u->handle;
721 struct current_user user;
723 if (q_u->printername_ptr != 0)
724 printername = &q_u->printername;
726 if (printername == NULL)
727 return ERROR_INVALID_PRINTER_NAME;
729 /* some sanity check because you can open a printer or a print server */
730 /* aka: \\server\printer or \\server */
731 unistr2_to_ascii(name, printername, sizeof(name)-1);
733 DEBUGADD(3,("checking name: %s\n",name));
735 if (!open_printer_hnd(p, handle, name))
736 return ERROR_INVALID_PRINTER_NAME;
739 if (printer_default->datatype_ptr != NULL)
741 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
742 set_printer_hnd_datatype(handle, datatype);
745 set_printer_hnd_datatype(handle, "");
748 if (!set_printer_hnd_accesstype(p, handle, printer_default->access_required)) {
749 close_printer_handle(p, handle);
750 return ERROR_ACCESS_DENIED;
754 First case: the user is opening the print server:
756 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
757 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
759 Then both Win2k and WinNT clients try an OpenPrinterEx with
760 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
761 or if the user is listed in the smb.conf printer admin parameter.
763 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
764 client view printer folder, but does not show the MSAPW.
766 Note: this test needs code to check access rights here too. Jeremy
767 could you look at this?
770 Second case: the user is opening a printer:
771 NT doesn't let us connect to a printer if the connecting user
772 doesn't have print permission.
776 get_current_user(&user, p);
778 if (handle_is_printserver(p, handle)) {
779 if (printer_default->access_required == 0) {
780 return NT_STATUS_NO_PROBLEMO;
782 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
784 /* Printserver handles use global struct... */
787 if (!lp_ms_add_printer_wizard()) {
788 close_printer_handle(p, handle);
789 return ERROR_ACCESS_DENIED;
791 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
792 return NT_STATUS_NO_PROBLEMO;
795 close_printer_handle(p, handle);
796 return ERROR_ACCESS_DENIED;
802 /* NT doesn't let us connect to a printer if the connecting user
803 doesn't have print permission. */
805 if (!get_printer_snum(p, handle, &snum))
806 return ERROR_INVALID_HANDLE;
808 /* map an empty access mask to the minimum access mask */
809 if (printer_default->access_required == 0x0)
810 printer_default->access_required = PRINTER_ACCESS_USE;
812 if (!print_access_check(&user, snum, printer_default->access_required)) {
813 DEBUG(3, ("access DENIED for printer open\n"));
814 close_printer_handle(p, handle);
815 return ERROR_ACCESS_DENIED;
819 * If we have a default device pointer in the
820 * printer_default struct, then we need to get
821 * the printer info from the tdb and if there is
822 * no default devicemode there then we do a *SET*
823 * here ! This is insanity.... JRA.
827 * If the openprinterex rpc call contains a devmode,
828 * it's a per-user one. This per-user devmode is derivated
829 * from the global devmode. Openprinterex() contains a per-user
830 * devmode for when you do EMF printing and spooling.
831 * In the EMF case, the NT workstation is only doing half the job
832 * of rendering the page. The other half is done by running the printer
833 * driver on the server.
834 * The EMF file doesn't contain the page description (paper size, orientation, ...).
835 * The EMF file only contains what is to be printed on the page.
836 * So in order for the server to know how to print, the NT client sends
837 * a devicemode attached to the openprinterex call.
838 * But this devicemode is short lived, it's only valid for the current print job.
840 * If Samba would have supported EMF spooling, this devicemode would
841 * have been attached to the handle, to sent it to the driver to correctly
842 * rasterize the EMF file.
844 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
845 * we just act as a pass-thru between windows and the printer.
847 * In order to know that Samba supports only RAW spooling, NT has to call
848 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
849 * and until NT sends a RAW job, we refuse it.
851 * But to call getprinter() or startdoc(), you first need a valid handle,
852 * and to get an handle you have to call openprintex(). Hence why you have
853 * a devicemode in the openprinterex() call.
856 * Differences between NT4 and NT 2000.
859 * On NT4, you only have a global devicemode. This global devicemode can be changed
860 * by the administrator (or by a user with enough privs). Everytime a user
861 * wants to print, the devicemode is resetted to the default. In Word, everytime
862 * you print, the printer's characteristics are always reset to the global devicemode.
866 * In W2K, there is the notion of per-user devicemode. The first time you use
867 * a printer, a per-user devicemode is build from the global devicemode.
868 * If you change your per-user devicemode, it is saved in the registry, under the
869 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
870 * printer preferences available.
872 * To change the per-user devicemode: it's the "Printing Preferences ..." button
873 * on the General Tab of the printer properties windows.
875 * To change the global devicemode: it's the "Printing Defaults..." button
876 * on the Advanced Tab of the printer properties window.
884 if (printer_default->devmode_cont.devmode != NULL) {
885 result = printer_write_default_dev( snum, printer_default);
887 close_printer_handle(p, handle);
894 return NT_STATUS_NO_PROBLEMO;
897 /****************************************************************************
898 ****************************************************************************/
899 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
900 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
904 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
913 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
914 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
918 printer->info_3=NULL;
919 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
922 printer->info_6=NULL;
923 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
932 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
933 NT_DEVICEMODE **pp_nt_devmode)
935 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
938 * Ensure nt_devmode is a valid pointer
939 * as we will be overwriting it.
942 if (nt_devmode == NULL) {
943 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
944 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
948 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
949 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
951 nt_devmode->specversion=devmode->specversion;
952 nt_devmode->driverversion=devmode->driverversion;
953 nt_devmode->size=devmode->size;
954 nt_devmode->fields=devmode->fields;
955 nt_devmode->orientation=devmode->orientation;
956 nt_devmode->papersize=devmode->papersize;
957 nt_devmode->paperlength=devmode->paperlength;
958 nt_devmode->paperwidth=devmode->paperwidth;
959 nt_devmode->scale=devmode->scale;
960 nt_devmode->copies=devmode->copies;
961 nt_devmode->defaultsource=devmode->defaultsource;
962 nt_devmode->printquality=devmode->printquality;
963 nt_devmode->color=devmode->color;
964 nt_devmode->duplex=devmode->duplex;
965 nt_devmode->yresolution=devmode->yresolution;
966 nt_devmode->ttoption=devmode->ttoption;
967 nt_devmode->collate=devmode->collate;
969 nt_devmode->logpixels=devmode->logpixels;
970 nt_devmode->bitsperpel=devmode->bitsperpel;
971 nt_devmode->pelswidth=devmode->pelswidth;
972 nt_devmode->pelsheight=devmode->pelsheight;
973 nt_devmode->displayflags=devmode->displayflags;
974 nt_devmode->displayfrequency=devmode->displayfrequency;
975 nt_devmode->icmmethod=devmode->icmmethod;
976 nt_devmode->icmintent=devmode->icmintent;
977 nt_devmode->mediatype=devmode->mediatype;
978 nt_devmode->dithertype=devmode->dithertype;
979 nt_devmode->reserved1=devmode->reserved1;
980 nt_devmode->reserved2=devmode->reserved2;
981 nt_devmode->panningwidth=devmode->panningwidth;
982 nt_devmode->panningheight=devmode->panningheight;
985 * Only change private and driverextra if the incoming devmode
986 * has a new one. JRA.
989 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
990 safe_free(nt_devmode->private);
991 nt_devmode->driverextra=devmode->driverextra;
992 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
994 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
997 *pp_nt_devmode = nt_devmode;
1002 /********************************************************************
1003 * _spoolss_enddocprinter_internal.
1004 ********************************************************************/
1006 static uint32 _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1008 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1011 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1012 return ERROR_INVALID_HANDLE;
1015 Printer->document_started=False;
1016 print_job_end(Printer->jobid,True);
1017 /* error codes unhandled so far ... */
1022 /********************************************************************
1023 * api_spoolss_closeprinter
1024 ********************************************************************/
1026 uint32 _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1028 POLICY_HND *handle = &q_u->handle;
1030 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1032 if (Printer && Printer->document_started)
1033 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1035 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1037 if (!close_printer_handle(p, handle))
1038 return ERROR_INVALID_HANDLE;
1040 return NT_STATUS_NO_PROBLEMO;
1043 /********************************************************************
1044 * api_spoolss_deleteprinter
1046 ********************************************************************/
1048 uint32 _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1050 POLICY_HND *handle = &q_u->handle;
1052 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1055 if (Printer && Printer->document_started)
1056 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1058 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1060 result = delete_printer_handle(p, handle);
1062 if (result == ERROR_SUCCESS) {
1063 srv_spoolss_sendnotify(p, handle);
1069 /********************************************************************
1070 GetPrinterData on a printer server Handle.
1071 ********************************************************************/
1072 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1076 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1078 if (!strcmp(value, "BeepEnabled")) {
1080 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1082 SIVAL(*data, 0, 0x01);
1087 if (!strcmp(value, "EventLog")) {
1089 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1091 SIVAL(*data, 0, 0x1B);
1096 if (!strcmp(value, "NetPopup")) {
1098 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1100 SIVAL(*data, 0, 0x01);
1105 if (!strcmp(value, "MajorVersion")) {
1107 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1109 SIVAL(*data, 0, 0x02);
1114 if (!strcmp(value, "DefaultSpoolDirectory")) {
1115 pstring string="You are using a Samba server";
1117 *needed = 2*(strlen(string)+1);
1118 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1120 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1122 /* it's done by hand ready to go on the wire */
1123 for (i=0; i<strlen(string); i++) {
1124 (*data)[2*i]=string[i];
1125 (*data)[2*i+1]='\0';
1130 if (!strcmp(value, "Architecture")) {
1131 pstring string="Windows NT x86";
1133 *needed = 2*(strlen(string)+1);
1134 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1136 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1137 for (i=0; i<strlen(string); i++) {
1138 (*data)[2*i]=string[i];
1139 (*data)[2*i+1]='\0';
1147 /********************************************************************
1148 GetPrinterData on a printer Handle.
1149 ********************************************************************/
1150 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1151 fstring value, uint32 *type,
1152 uint8 **data, uint32 *needed, uint32 in_size )
1154 NT_PRINTER_INFO_LEVEL *printer = NULL;
1158 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1160 DEBUG(5,("getprinterdata_printer\n"));
1163 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1167 if(!get_printer_snum(p, handle, &snum))
1170 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1173 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1174 free_a_printer(&printer, 2);
1178 free_a_printer(&printer, 2);
1180 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1183 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1187 memset(*data, 0, in_size *sizeof(uint8));
1188 /* copy the min(in_size, len) */
1189 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1196 DEBUG(5,("getprinterdata_printer:copy done\n"));
1203 /********************************************************************
1204 * spoolss_getprinterdata
1205 ********************************************************************/
1207 uint32 _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1209 POLICY_HND *handle = &q_u->handle;
1210 UNISTR2 *valuename = &q_u->valuename;
1211 uint32 in_size = q_u->size;
1212 uint32 *type = &r_u->type;
1213 uint32 *out_size = &r_u->size;
1214 uint8 **data = &r_u->data;
1215 uint32 *needed = &r_u->needed;
1219 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1222 * Reminder: when it's a string, the length is in BYTES
1223 * even if UNICODE is negociated.
1230 /* in case of problem, return some default values */
1234 DEBUG(4,("_spoolss_getprinterdata\n"));
1237 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1238 return ERROR_NOT_ENOUGH_MEMORY;
1239 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1240 return ERROR_INVALID_HANDLE;
1243 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1245 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1246 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1248 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1251 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1252 /* reply this param doesn't exist */
1254 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1255 return ERROR_NOT_ENOUGH_MEMORY;
1260 return ERROR_INVALID_PARAMETER;
1263 if (*needed > *out_size)
1264 return ERROR_MORE_DATA;
1266 return NT_STATUS_NO_PROBLEMO;
1270 /***************************************************************************
1271 connect to the client
1272 ****************************************************************************/
1273 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1278 * If it's the first connection, contact the client
1279 * and connect to the IPC$ share anonumously
1281 if (smb_connections==0) {
1282 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1284 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1290 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1296 /********************************************************************
1298 * ReplyFindFirstPrinterChangeNotifyEx
1300 * jfmxxxx: before replying OK: status=0
1301 * should do a rpc call to the workstation asking ReplyOpenPrinter
1302 * have to code it, later.
1304 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1305 * called from api_spoolss_rffpcnex
1306 ********************************************************************/
1308 uint32 _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1310 POLICY_HND *handle = &q_u->handle;
1311 uint32 flags = q_u->flags;
1312 uint32 options = q_u->options;
1313 UNISTR2 *localmachine = &q_u->localmachine;
1314 uint32 printerlocal = q_u->printerlocal;
1315 SPOOL_NOTIFY_OPTION *option = q_u->option;
1317 /* store the notify value in the printer struct */
1319 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1322 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1323 return ERROR_INVALID_HANDLE;
1326 Printer->notify.flags=flags;
1327 Printer->notify.options=options;
1328 Printer->notify.printerlocal=printerlocal;
1330 if (Printer->notify.option)
1331 free_spool_notify_option(&Printer->notify.option);
1333 Printer->notify.option=dup_spool_notify_option(option);
1335 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1337 /* connect to the client machine and send a ReplyOpenPrinter */
1338 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1339 Printer->notify.printerlocal, 1,
1340 &Printer->notify.client_hnd))
1341 Printer->notify.client_connected=True;
1343 return NT_STATUS_NO_PROBLEMO;
1346 /*******************************************************************
1347 * fill a notify_info_data with the servername
1348 ********************************************************************/
1350 static void spoolss_notify_server_name(int snum,
1351 SPOOL_NOTIFY_INFO_DATA *data,
1352 print_queue_struct *queue,
1353 NT_PRINTER_INFO_LEVEL *printer,
1354 TALLOC_CTX *mem_ctx)
1356 pstring temp_name, temp;
1359 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1361 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1363 data->notify_data.data.length = len / 2 - 1;
1364 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1366 if (!data->notify_data.data.string) {
1367 data->notify_data.data.length = 0;
1371 memcpy(data->notify_data.data.string, temp, len);
1374 /*******************************************************************
1375 * fill a notify_info_data with the printername (not including the servername).
1376 ********************************************************************/
1377 static void spoolss_notify_printer_name(int snum,
1378 SPOOL_NOTIFY_INFO_DATA *data,
1379 print_queue_struct *queue,
1380 NT_PRINTER_INFO_LEVEL *printer,
1381 TALLOC_CTX *mem_ctx)
1386 /* the notify name should not contain the \\server\ part */
1387 char *p = strrchr(printer->info_2->printername, '\\');
1390 p = printer->info_2->printername;
1395 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1397 data->notify_data.data.length = len / 2 - 1;
1398 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1400 if (!data->notify_data.data.string) {
1401 data->notify_data.data.length = 0;
1405 memcpy(data->notify_data.data.string, temp, len);
1408 /*******************************************************************
1409 * fill a notify_info_data with the servicename
1410 ********************************************************************/
1411 static void spoolss_notify_share_name(int snum,
1412 SPOOL_NOTIFY_INFO_DATA *data,
1413 print_queue_struct *queue,
1414 NT_PRINTER_INFO_LEVEL *printer,
1415 TALLOC_CTX *mem_ctx)
1420 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1421 sizeof(temp) - 2, True);
1423 data->notify_data.data.length = len / 2 - 1;
1424 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1426 if (!data->notify_data.data.string) {
1427 data->notify_data.data.length = 0;
1431 memcpy(data->notify_data.data.string, temp, len);
1434 /*******************************************************************
1435 * fill a notify_info_data with the port name
1436 ********************************************************************/
1437 static void spoolss_notify_port_name(int snum,
1438 SPOOL_NOTIFY_INFO_DATA *data,
1439 print_queue_struct *queue,
1440 NT_PRINTER_INFO_LEVEL *printer,
1441 TALLOC_CTX *mem_ctx)
1446 /* even if it's strange, that's consistant in all the code */
1448 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1449 sizeof(temp) - 2, True);
1451 data->notify_data.data.length = len / 2 - 1;
1452 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1454 if (!data->notify_data.data.string) {
1455 data->notify_data.data.length = 0;
1459 memcpy(data->notify_data.data.string, temp, len);
1462 /*******************************************************************
1463 * fill a notify_info_data with the printername
1464 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1465 * but it doesn't exist, have to see what to do
1466 ********************************************************************/
1467 static void spoolss_notify_driver_name(int snum,
1468 SPOOL_NOTIFY_INFO_DATA *data,
1469 print_queue_struct *queue,
1470 NT_PRINTER_INFO_LEVEL *printer,
1471 TALLOC_CTX *mem_ctx)
1476 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1477 sizeof(temp) - 2, True);
1479 data->notify_data.data.length = len / 2 - 1;
1480 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1482 if (!data->notify_data.data.string) {
1483 data->notify_data.data.length = 0;
1487 memcpy(data->notify_data.data.string, temp, len);
1490 /*******************************************************************
1491 * fill a notify_info_data with the comment
1492 ********************************************************************/
1493 static void spoolss_notify_comment(int snum,
1494 SPOOL_NOTIFY_INFO_DATA *data,
1495 print_queue_struct *queue,
1496 NT_PRINTER_INFO_LEVEL *printer,
1497 TALLOC_CTX *mem_ctx)
1502 if (*printer->info_2->comment == '\0')
1503 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1504 sizeof(temp) - 2, True);
1506 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1507 sizeof(temp) - 2, True);
1509 data->notify_data.data.length = len / 2 - 1;
1510 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1512 if (!data->notify_data.data.string) {
1513 data->notify_data.data.length = 0;
1517 memcpy(data->notify_data.data.string, temp, len);
1520 /*******************************************************************
1521 * fill a notify_info_data with the comment
1522 * jfm:xxxx incorrect, have to create a new smb.conf option
1523 * location = "Room 1, floor 2, building 3"
1524 ********************************************************************/
1525 static void spoolss_notify_location(int snum,
1526 SPOOL_NOTIFY_INFO_DATA *data,
1527 print_queue_struct *queue,
1528 NT_PRINTER_INFO_LEVEL *printer,
1529 TALLOC_CTX *mem_ctx)
1534 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1535 sizeof(temp) - 2, True);
1537 data->notify_data.data.length = len / 2 - 1;
1538 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1540 if (!data->notify_data.data.string) {
1541 data->notify_data.data.length = 0;
1545 memcpy(data->notify_data.data.string, temp, len);
1548 /*******************************************************************
1549 * fill a notify_info_data with the device mode
1550 * jfm:xxxx don't to it for know but that's a real problem !!!
1551 ********************************************************************/
1552 static void spoolss_notify_devmode(int snum,
1553 SPOOL_NOTIFY_INFO_DATA *data,
1554 print_queue_struct *queue,
1555 NT_PRINTER_INFO_LEVEL *printer,
1556 TALLOC_CTX *mem_ctx)
1560 /*******************************************************************
1561 * fill a notify_info_data with the separator file name
1562 * jfm:xxxx just return no file could add an option to smb.conf
1563 * separator file = "separator.txt"
1564 ********************************************************************/
1565 static void spoolss_notify_sepfile(int snum,
1566 SPOOL_NOTIFY_INFO_DATA *data,
1567 print_queue_struct *queue,
1568 NT_PRINTER_INFO_LEVEL *printer,
1569 TALLOC_CTX *mem_ctx)
1574 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1575 sizeof(temp) - 2, True);
1577 data->notify_data.data.length = len / 2 - 1;
1578 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1580 if (!data->notify_data.data.string) {
1581 data->notify_data.data.length = 0;
1585 memcpy(data->notify_data.data.string, temp, len);
1588 /*******************************************************************
1589 * fill a notify_info_data with the print processor
1590 * jfm:xxxx return always winprint to indicate we don't do anything to it
1591 ********************************************************************/
1592 static void spoolss_notify_print_processor(int snum,
1593 SPOOL_NOTIFY_INFO_DATA *data,
1594 print_queue_struct *queue,
1595 NT_PRINTER_INFO_LEVEL *printer,
1596 TALLOC_CTX *mem_ctx)
1601 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
1602 sizeof(temp) - 2, True);
1604 data->notify_data.data.length = len / 2 - 1;
1605 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1607 if (!data->notify_data.data.string) {
1608 data->notify_data.data.length = 0;
1612 memcpy(data->notify_data.data.string, temp, len);
1615 /*******************************************************************
1616 * fill a notify_info_data with the print processor options
1617 * jfm:xxxx send an empty string
1618 ********************************************************************/
1619 static void spoolss_notify_parameters(int snum,
1620 SPOOL_NOTIFY_INFO_DATA *data,
1621 print_queue_struct *queue,
1622 NT_PRINTER_INFO_LEVEL *printer,
1623 TALLOC_CTX *mem_ctx)
1628 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1629 sizeof(temp) - 2, True);
1631 data->notify_data.data.length = len / 2 - 1;
1632 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1634 if (!data->notify_data.data.string) {
1635 data->notify_data.data.length = 0;
1639 memcpy(data->notify_data.data.string, temp, len);
1642 /*******************************************************************
1643 * fill a notify_info_data with the data type
1644 * jfm:xxxx always send RAW as data type
1645 ********************************************************************/
1646 static void spoolss_notify_datatype(int snum,
1647 SPOOL_NOTIFY_INFO_DATA *data,
1648 print_queue_struct *queue,
1649 NT_PRINTER_INFO_LEVEL *printer,
1650 TALLOC_CTX *mem_ctx)
1655 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1656 sizeof(pstring) - 2, True);
1658 data->notify_data.data.length = len / 2 - 1;
1659 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1661 if (!data->notify_data.data.string) {
1662 data->notify_data.data.length = 0;
1666 memcpy(data->notify_data.data.string, temp, len);
1669 /*******************************************************************
1670 * fill a notify_info_data with the security descriptor
1671 * jfm:xxxx send an null pointer to say no security desc
1672 * have to implement security before !
1673 ********************************************************************/
1674 static void spoolss_notify_security_desc(int snum,
1675 SPOOL_NOTIFY_INFO_DATA *data,
1676 print_queue_struct *queue,
1677 NT_PRINTER_INFO_LEVEL *printer,
1678 TALLOC_CTX *mem_ctx)
1680 data->notify_data.data.length=0;
1681 data->notify_data.data.string = NULL;
1684 /*******************************************************************
1685 * fill a notify_info_data with the attributes
1686 * jfm:xxxx a samba printer is always shared
1687 ********************************************************************/
1688 static void spoolss_notify_attributes(int snum,
1689 SPOOL_NOTIFY_INFO_DATA *data,
1690 print_queue_struct *queue,
1691 NT_PRINTER_INFO_LEVEL *printer,
1692 TALLOC_CTX *mem_ctx)
1694 data->notify_data.value[0] = printer->info_2->attributes;
1697 /*******************************************************************
1698 * fill a notify_info_data with the priority
1699 ********************************************************************/
1700 static void spoolss_notify_priority(int snum,
1701 SPOOL_NOTIFY_INFO_DATA *data,
1702 print_queue_struct *queue,
1703 NT_PRINTER_INFO_LEVEL *printer,
1704 TALLOC_CTX *mem_ctx)
1706 data->notify_data.value[0] = printer->info_2->priority;
1709 /*******************************************************************
1710 * fill a notify_info_data with the default priority
1711 ********************************************************************/
1712 static void spoolss_notify_default_priority(int snum,
1713 SPOOL_NOTIFY_INFO_DATA *data,
1714 print_queue_struct *queue,
1715 NT_PRINTER_INFO_LEVEL *printer,
1716 TALLOC_CTX *mem_ctx)
1718 data->notify_data.value[0] = printer->info_2->default_priority;
1721 /*******************************************************************
1722 * fill a notify_info_data with the start time
1723 ********************************************************************/
1724 static void spoolss_notify_start_time(int snum,
1725 SPOOL_NOTIFY_INFO_DATA *data,
1726 print_queue_struct *queue,
1727 NT_PRINTER_INFO_LEVEL *printer,
1728 TALLOC_CTX *mem_ctx)
1730 data->notify_data.value[0] = printer->info_2->starttime;
1733 /*******************************************************************
1734 * fill a notify_info_data with the until time
1735 ********************************************************************/
1736 static void spoolss_notify_until_time(int snum,
1737 SPOOL_NOTIFY_INFO_DATA *data,
1738 print_queue_struct *queue,
1739 NT_PRINTER_INFO_LEVEL *printer,
1740 TALLOC_CTX *mem_ctx)
1742 data->notify_data.value[0] = printer->info_2->untiltime;
1745 /*******************************************************************
1746 * fill a notify_info_data with the status
1747 ********************************************************************/
1748 static void spoolss_notify_status(int snum,
1749 SPOOL_NOTIFY_INFO_DATA *data,
1750 print_queue_struct *queue,
1751 NT_PRINTER_INFO_LEVEL *printer,
1752 TALLOC_CTX *mem_ctx)
1754 print_queue_struct *q=NULL;
1755 print_status_struct status;
1757 memset(&status, 0, sizeof(status));
1758 print_queue_status(snum, &q, &status);
1759 data->notify_data.value[0]=(uint32) status.status;
1763 /*******************************************************************
1764 * fill a notify_info_data with the number of jobs queued
1765 ********************************************************************/
1766 static void spoolss_notify_cjobs(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 print_queue_struct *q=NULL;
1773 print_status_struct status;
1775 memset(&status, 0, sizeof(status));
1776 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1780 /*******************************************************************
1781 * fill a notify_info_data with the average ppm
1782 ********************************************************************/
1783 static void spoolss_notify_average_ppm(int snum,
1784 SPOOL_NOTIFY_INFO_DATA *data,
1785 print_queue_struct *queue,
1786 NT_PRINTER_INFO_LEVEL *printer,
1787 TALLOC_CTX *mem_ctx)
1789 /* always respond 8 pages per minutes */
1790 /* a little hard ! */
1791 data->notify_data.value[0] = printer->info_2->averageppm;
1794 /*******************************************************************
1795 * fill a notify_info_data with username
1796 ********************************************************************/
1797 static void spoolss_notify_username(int snum,
1798 SPOOL_NOTIFY_INFO_DATA *data,
1799 print_queue_struct *queue,
1800 NT_PRINTER_INFO_LEVEL *printer,
1801 TALLOC_CTX *mem_ctx)
1806 len = (uint32)dos_PutUniCode(temp, queue->user,
1807 sizeof(temp) - 2, True);
1809 data->notify_data.data.length = len / 2 - 1;
1810 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1812 if (!data->notify_data.data.string) {
1813 data->notify_data.data.length = 0;
1817 memcpy(data->notify_data.data.string, temp, len);
1820 /*******************************************************************
1821 * fill a notify_info_data with job status
1822 ********************************************************************/
1823 static void spoolss_notify_job_status(int snum,
1824 SPOOL_NOTIFY_INFO_DATA *data,
1825 print_queue_struct *queue,
1826 NT_PRINTER_INFO_LEVEL *printer,
1827 TALLOC_CTX *mem_ctx)
1829 data->notify_data.value[0]=nt_printj_status(queue->status);
1832 /*******************************************************************
1833 * fill a notify_info_data with job name
1834 ********************************************************************/
1835 static void spoolss_notify_job_name(int snum,
1836 SPOOL_NOTIFY_INFO_DATA *data,
1837 print_queue_struct *queue,
1838 NT_PRINTER_INFO_LEVEL *printer,
1839 TALLOC_CTX *mem_ctx)
1844 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1847 data->notify_data.data.length = len / 2 - 1;
1848 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1850 if (!data->notify_data.data.string) {
1851 data->notify_data.data.length = 0;
1855 memcpy(data->notify_data.data.string, temp, len);
1858 /*******************************************************************
1859 * fill a notify_info_data with job status
1860 ********************************************************************/
1861 static void spoolss_notify_job_status_string(int snum,
1862 SPOOL_NOTIFY_INFO_DATA *data,
1863 print_queue_struct *queue,
1864 NT_PRINTER_INFO_LEVEL *printer,
1865 TALLOC_CTX *mem_ctx)
1868 * Now we're returning job status codes we just return a "" here. JRA.
1875 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1878 switch (queue->status) {
1883 p = ""; /* NT provides the paused string */
1892 #endif /* NO LONGER NEEDED. */
1894 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1896 data->notify_data.data.length = len / 2 - 1;
1897 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1899 if (!data->notify_data.data.string) {
1900 data->notify_data.data.length = 0;
1904 memcpy(data->notify_data.data.string, temp, len);
1907 /*******************************************************************
1908 * fill a notify_info_data with job time
1909 ********************************************************************/
1910 static void spoolss_notify_job_time(int snum,
1911 SPOOL_NOTIFY_INFO_DATA *data,
1912 print_queue_struct *queue,
1913 NT_PRINTER_INFO_LEVEL *printer,
1914 TALLOC_CTX *mem_ctx)
1916 data->notify_data.value[0]=0x0;
1919 /*******************************************************************
1920 * fill a notify_info_data with job size
1921 ********************************************************************/
1922 static void spoolss_notify_job_size(int snum,
1923 SPOOL_NOTIFY_INFO_DATA *data,
1924 print_queue_struct *queue,
1925 NT_PRINTER_INFO_LEVEL *printer,
1926 TALLOC_CTX *mem_ctx)
1928 data->notify_data.value[0]=queue->size;
1931 /*******************************************************************
1932 * fill a notify_info_data with job position
1933 ********************************************************************/
1934 static void spoolss_notify_job_position(int snum,
1935 SPOOL_NOTIFY_INFO_DATA *data,
1936 print_queue_struct *queue,
1937 NT_PRINTER_INFO_LEVEL *printer,
1938 TALLOC_CTX *mem_ctx)
1940 data->notify_data.value[0]=queue->job;
1943 /*******************************************************************
1944 * fill a notify_info_data with submitted time
1945 ********************************************************************/
1946 static void spoolss_notify_submitted_time(int snum,
1947 SPOOL_NOTIFY_INFO_DATA *data,
1948 print_queue_struct *queue,
1949 NT_PRINTER_INFO_LEVEL *printer,
1950 TALLOC_CTX *mem_ctx)
1956 t=gmtime(&queue->time);
1958 len = sizeof(SYSTEMTIME);
1960 data->notify_data.data.length = len/2 - 1;
1961 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1963 if (!data->notify_data.data.string) {
1964 data->notify_data.data.length = 0;
1968 make_systemtime(&st, t);
1969 memcpy(data->notify_data.data.string,&st,len);
1974 struct s_notify_info_data_table
1980 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1981 print_queue_struct *queue,
1982 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
1985 struct s_notify_info_data_table notify_info_data_table[] =
1987 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1988 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1989 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1990 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1991 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1992 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1993 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1994 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1995 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1996 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1997 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1998 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1999 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2000 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2001 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2002 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2003 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2004 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2005 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2006 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2007 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2008 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2009 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2010 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2011 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2012 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2013 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2014 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2015 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2016 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2017 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2018 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2019 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2020 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2021 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2022 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2023 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2024 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2025 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2026 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2027 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2028 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2029 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2030 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2031 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2032 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2033 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2034 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2035 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2036 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2037 { END, END, "", END, NULL }
2040 /*******************************************************************
2041 return the size of info_data structure
2042 ********************************************************************/
2043 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2047 while (notify_info_data_table[i].type != END)
2049 if ( (notify_info_data_table[i].type == type ) &&
2050 (notify_info_data_table[i].field == field ) )
2052 return (notify_info_data_table[i].size);
2059 /*******************************************************************
2060 return the type of notify_info_data
2061 ********************************************************************/
2062 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2066 while (notify_info_data_table[i].type != END)
2068 if ( (notify_info_data_table[i].type == type ) &&
2069 (notify_info_data_table[i].field == field ) )
2071 if (notify_info_data_table[i].size == POINTER)
2085 /****************************************************************************
2086 ****************************************************************************/
2087 static int search_notify(uint16 type, uint16 field, int *value)
2092 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2094 if ( (notify_info_data_table[j].type == type ) &&
2095 (notify_info_data_table[j].field == field ) )
2100 if ( found && (notify_info_data_table[j].fn != NULL) )
2106 /****************************************************************************
2107 ****************************************************************************/
2108 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2110 info_data->type = type;
2111 info_data->field = field;
2112 info_data->reserved = 0;
2114 info_data->size = size_of_notify_info_data(type, field);
2115 info_data->enc_type = type_of_notify_info_data(type, field);
2119 /*******************************************************************
2121 * fill a notify_info struct with info asked
2123 ********************************************************************/
2124 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2125 snum, SPOOL_NOTIFY_OPTION_TYPE
2126 *option_type, uint32 id,
2127 TALLOC_CTX *mem_ctx)
2133 SPOOL_NOTIFY_INFO_DATA *current_data;
2134 NT_PRINTER_INFO_LEVEL *printer = NULL;
2135 print_queue_struct *queue=NULL;
2137 type=option_type->type;
2139 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2140 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2141 option_type->count, lp_servicename(snum)));
2143 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2146 for(field_num=0; field_num<option_type->count; field_num++) {
2147 field = option_type->fields[field_num];
2148 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2150 if (!search_notify(type, field, &j) )
2153 if((info->data=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2156 current_data=&info->data[info->count];
2158 construct_info_data(current_data, type, field, id);
2160 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2161 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2163 notify_info_data_table[j].fn(snum, current_data, queue,
2169 free_a_printer(&printer, 2);
2173 /*******************************************************************
2175 * fill a notify_info struct with info asked
2177 ********************************************************************/
2178 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2179 SPOOL_NOTIFY_INFO *info,
2180 NT_PRINTER_INFO_LEVEL *printer,
2181 int snum, SPOOL_NOTIFY_OPTION_TYPE
2182 *option_type, uint32 id,
2183 TALLOC_CTX *mem_ctx)
2189 SPOOL_NOTIFY_INFO_DATA *current_data;
2191 DEBUG(4,("construct_notify_jobs_info\n"));
2193 type = option_type->type;
2195 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2196 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2197 option_type->count));
2199 for(field_num=0; field_num<option_type->count; field_num++) {
2200 field = option_type->fields[field_num];
2202 if (!search_notify(type, field, &j) )
2205 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2209 current_data=&(info->data[info->count]);
2211 construct_info_data(current_data, type, field, id);
2212 notify_info_data_table[j].fn(snum, current_data, queue,
2221 * JFM: The enumeration is not that simple, it's even non obvious.
2223 * let's take an example: I want to monitor the PRINTER SERVER for
2224 * the printer's name and the number of jobs currently queued.
2225 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2226 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2228 * I have 3 printers on the back of my server.
2230 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2233 * 1 printer 1 name 1
2234 * 2 printer 1 cjob 1
2235 * 3 printer 2 name 2
2236 * 4 printer 2 cjob 2
2237 * 5 printer 3 name 3
2238 * 6 printer 3 name 3
2240 * that's the print server case, the printer case is even worse.
2243 /*******************************************************************
2245 * enumerate all printers on the printserver
2246 * fill a notify_info struct with info asked
2248 ********************************************************************/
2250 static uint32 printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2251 SPOOL_NOTIFY_INFO *info,
2252 TALLOC_CTX *mem_ctx)
2255 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2256 int n_services=lp_numservices();
2259 SPOOL_NOTIFY_OPTION *option;
2260 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2262 DEBUG(4,("printserver_notify_info\n"));
2264 option=Printer->notify.option;
2270 for (i=0; i<option->count; i++) {
2271 option_type=&(option->ctr.type[i]);
2273 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2276 for (snum=0; snum<n_services; snum++)
2277 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2278 if (construct_notify_printer_info
2279 (info, snum, option_type, id, mem_ctx))
2284 * Debugging information, don't delete.
2287 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2288 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2289 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2291 for (i=0; i<info->count; i++) {
2292 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2293 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2294 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2298 return NT_STATUS_NO_PROBLEMO;
2301 /*******************************************************************
2303 * fill a notify_info struct with info asked
2305 ********************************************************************/
2306 static uint32 printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2307 TALLOC_CTX *mem_ctx)
2310 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2313 SPOOL_NOTIFY_OPTION *option;
2314 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2316 print_queue_struct *queue=NULL;
2317 print_status_struct status;
2319 DEBUG(4,("printer_notify_info\n"));
2321 option=Printer->notify.option;
2327 get_printer_snum(p, hnd, &snum);
2329 for (i=0; i<option->count; i++) {
2330 option_type=&option->ctr.type[i];
2332 switch ( option_type->type ) {
2333 case PRINTER_NOTIFY_TYPE:
2334 if(construct_notify_printer_info(info, snum,
2340 case JOB_NOTIFY_TYPE: {
2341 NT_PRINTER_INFO_LEVEL *printer = NULL;
2343 memset(&status, 0, sizeof(status));
2344 count = print_queue_status(snum, &queue, &status);
2346 if (get_a_printer(&printer, 2,
2347 lp_servicename(snum)) != 0)
2350 for (j=0; j<count; j++) {
2351 construct_notify_jobs_info(&queue[j], info,
2358 free_a_printer(&printer, 2);
2368 * Debugging information, don't delete.
2371 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2372 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2373 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2375 for (i=0; i<info->count; i++) {
2376 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2377 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2378 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2381 return NT_STATUS_NO_PROBLEMO;
2384 /********************************************************************
2386 ********************************************************************/
2388 uint32 _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2390 POLICY_HND *handle = &q_u->handle;
2391 /* uint32 change = q_u->change; - notused. */
2392 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2393 SPOOL_NOTIFY_INFO *info = &r_u->info;
2395 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2396 uint32 result = ERROR_INVALID_HANDLE;
2398 /* we always have a NOTIFY_INFO struct */
2402 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2403 OUR_HANDLE(handle)));
2407 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2409 /* jfm: the change value isn't used right now.
2410 * we will honour it when
2411 * a) we'll be able to send notification to the client
2412 * b) we'll have a way to communicate between the spoolss process.
2414 * same thing for option->flags
2415 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2416 * I don't have a global notification system, I'm sending back all the
2417 * informations even when _NOTHING_ has changed.
2420 /* just ignore the SPOOL_NOTIFY_OPTION */
2422 switch (Printer->printer_type) {
2423 case PRINTER_HANDLE_IS_PRINTSERVER:
2424 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2427 case PRINTER_HANDLE_IS_PRINTER:
2428 result = printer_notify_info(p, handle, info, p->mem_ctx);
2436 /********************************************************************
2437 * construct_printer_info_0
2438 * fill a printer_info_0 struct
2439 ********************************************************************/
2440 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2444 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2445 counter_printer_0 *session_counter;
2446 uint32 global_counter;
2450 print_queue_struct *queue=NULL;
2451 print_status_struct status;
2453 memset(&status, 0, sizeof(status));
2455 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2458 count = print_queue_status(snum, &queue, &status);
2460 /* check if we already have a counter for this printer */
2461 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2463 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2464 if (session_counter->snum == snum)
2468 /* it's the first time, add it to the list */
2469 if (session_counter==NULL) {
2470 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2471 free_a_printer(&ntprinter, 2);
2474 ZERO_STRUCTP(session_counter);
2475 session_counter->snum=snum;
2476 session_counter->counter=0;
2477 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2481 session_counter->counter++;
2484 * the global_counter should be stored in a TDB as it's common to all the clients
2485 * and should be zeroed on samba startup
2487 global_counter=session_counter->counter;
2489 pstrcpy(chaine,ntprinter->info_2->printername);
2491 init_unistr(&printer->printername, chaine);
2493 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2494 init_unistr(&printer->servername, chaine);
2496 printer->cjobs = count;
2497 printer->total_jobs = 0;
2498 printer->total_bytes = 0;
2500 setuptime = (time_t)ntprinter->info_2->setuptime;
2501 t=gmtime(&setuptime);
2503 printer->year = t->tm_year+1900;
2504 printer->month = t->tm_mon+1;
2505 printer->dayofweek = t->tm_wday;
2506 printer->day = t->tm_mday;
2507 printer->hour = t->tm_hour;
2508 printer->minute = t->tm_min;
2509 printer->second = t->tm_sec;
2510 printer->milliseconds = 0;
2512 printer->global_counter = global_counter;
2513 printer->total_pages = 0;
2514 printer->major_version = 0x0004; /* NT 4 */
2515 printer->build_version = 0x0565; /* build 1381 */
2516 printer->unknown7 = 0x1;
2517 printer->unknown8 = 0x0;
2518 printer->unknown9 = 0x0;
2519 printer->session_counter = session_counter->counter;
2520 printer->unknown11 = 0x0;
2521 printer->printer_errors = 0x0; /* number of print failure */
2522 printer->unknown13 = 0x0;
2523 printer->unknown14 = 0x1;
2524 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2525 printer->unknown16 = 0x0;
2526 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2527 printer->unknown18 = 0x0;
2528 printer->status = nt_printq_status(status.status);
2529 printer->unknown20 = 0x0;
2530 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2531 printer->unknown22 = 0x0;
2532 printer->unknown23 = 0x6; /* 6 ???*/
2533 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2534 printer->unknown25 = 0;
2535 printer->unknown26 = 0;
2536 printer->unknown27 = 0;
2537 printer->unknown28 = 0;
2538 printer->unknown29 = 0;
2541 free_a_printer(&ntprinter,2);
2545 /********************************************************************
2546 * construct_printer_info_1
2547 * fill a printer_info_1 struct
2548 ********************************************************************/
2549 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2553 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2555 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2558 printer->flags=flags;
2560 if (*ntprinter->info_2->comment == '\0') {
2561 init_unistr(&printer->comment, lp_comment(snum));
2562 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2563 ntprinter->info_2->drivername, lp_comment(snum));
2566 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2567 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2568 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2571 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2573 init_unistr(&printer->description, chaine);
2574 init_unistr(&printer->name, chaine2);
2576 free_a_printer(&ntprinter,2);
2581 /****************************************************************************
2582 Free a DEVMODE struct.
2583 ****************************************************************************/
2585 static void free_dev_mode(DEVICEMODE *dev)
2591 safe_free(dev->private);
2596 /****************************************************************************
2597 Create a DEVMODE struct. Returns malloced memory.
2598 ****************************************************************************/
2600 static DEVICEMODE *construct_dev_mode(int snum)
2604 NT_PRINTER_INFO_LEVEL *printer = NULL;
2605 NT_DEVICEMODE *ntdevmode = NULL;
2606 DEVICEMODE *devmode = NULL;
2608 DEBUG(7,("construct_dev_mode\n"));
2610 DEBUGADD(8,("getting printer characteristics\n"));
2612 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2613 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2617 ZERO_STRUCTP(devmode);
2619 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2622 if (printer->info_2->devmode)
2623 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2625 if (ntdevmode == NULL)
2628 DEBUGADD(8,("loading DEVICEMODE\n"));
2630 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2631 init_unistr(&devmode->devicename, adevice);
2633 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2634 init_unistr(&devmode->formname, aform);
2636 devmode->specversion = ntdevmode->specversion;
2637 devmode->driverversion = ntdevmode->driverversion;
2638 devmode->size = ntdevmode->size;
2639 devmode->driverextra = ntdevmode->driverextra;
2640 devmode->fields = ntdevmode->fields;
2642 devmode->orientation = ntdevmode->orientation;
2643 devmode->papersize = ntdevmode->papersize;
2644 devmode->paperlength = ntdevmode->paperlength;
2645 devmode->paperwidth = ntdevmode->paperwidth;
2646 devmode->scale = ntdevmode->scale;
2647 devmode->copies = ntdevmode->copies;
2648 devmode->defaultsource = ntdevmode->defaultsource;
2649 devmode->printquality = ntdevmode->printquality;
2650 devmode->color = ntdevmode->color;
2651 devmode->duplex = ntdevmode->duplex;
2652 devmode->yresolution = ntdevmode->yresolution;
2653 devmode->ttoption = ntdevmode->ttoption;
2654 devmode->collate = ntdevmode->collate;
2655 devmode->icmmethod = ntdevmode->icmmethod;
2656 devmode->icmintent = ntdevmode->icmintent;
2657 devmode->mediatype = ntdevmode->mediatype;
2658 devmode->dithertype = ntdevmode->dithertype;
2660 if (ntdevmode->private != NULL) {
2661 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2665 free_nt_devicemode(&ntdevmode);
2666 free_a_printer(&printer,2);
2673 free_nt_devicemode(&ntdevmode);
2675 free_a_printer(&printer,2);
2676 free_dev_mode(devmode);
2681 /********************************************************************
2682 * construct_printer_info_2
2683 * fill a printer_info_2 struct
2684 ********************************************************************/
2686 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2689 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2691 print_queue_struct *queue=NULL;
2692 print_status_struct status;
2693 memset(&status, 0, sizeof(status));
2695 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2698 memset(&status, 0, sizeof(status));
2699 count = print_queue_status(snum, &queue, &status);
2701 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2702 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2703 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2704 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2705 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2707 if (*ntprinter->info_2->comment == '\0')
2708 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2710 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2712 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2713 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2714 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2715 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2716 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2718 printer->attributes = ntprinter->info_2->attributes;
2720 printer->priority = ntprinter->info_2->priority; /* priority */
2721 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2722 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2723 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2724 printer->status = nt_printq_status(status.status); /* status */
2725 printer->cjobs = count; /* jobs */
2726 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2728 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2729 DEBUG(8, ("Returning NULL Devicemode!\n"));
2732 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2733 /* steal the printer info sec_desc structure. [badly done]. */
2734 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2735 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2736 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2737 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2740 printer->secdesc = NULL;
2743 free_a_printer(&ntprinter, 2);
2748 /********************************************************************
2749 * construct_printer_info_3
2750 * fill a printer_info_3 struct
2751 ********************************************************************/
2752 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2754 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2755 PRINTER_INFO_3 *printer = NULL;
2757 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2761 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2762 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2766 ZERO_STRUCTP(printer);
2768 printer->flags = 4; /* These are the components of the SD we are returning. */
2769 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2770 /* steal the printer info sec_desc structure. [badly done]. */
2771 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2775 * Set the flags for the components we are returning.
2778 if (printer->secdesc->owner_sid)
2779 printer->flags |= OWNER_SECURITY_INFORMATION;
2781 if (printer->secdesc->grp_sid)
2782 printer->flags |= GROUP_SECURITY_INFORMATION;
2784 if (printer->secdesc->dacl)
2785 printer->flags |= DACL_SECURITY_INFORMATION;
2787 if (printer->secdesc->sacl)
2788 printer->flags |= SACL_SECURITY_INFORMATION;
2791 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2792 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2793 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2796 free_a_printer(&ntprinter, 2);
2798 *pp_printer = printer;
2802 /********************************************************************
2803 Spoolss_enumprinters.
2804 ********************************************************************/
2805 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2809 int n_services=lp_numservices();
2810 PRINTER_INFO_1 *printers=NULL;
2811 PRINTER_INFO_1 current_prt;
2813 DEBUG(4,("enum_all_printers_info_1\n"));
2815 for (snum=0; snum<n_services; snum++) {
2816 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2817 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2819 if (construct_printer_info_1(flags, ¤t_prt, snum)) {
2820 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2822 return ERROR_NOT_ENOUGH_MEMORY;
2824 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2825 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
2831 /* check the required size. */
2832 for (i=0; i<*returned; i++)
2833 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2835 if (!alloc_buffer_size(buffer, *needed))
2836 return ERROR_INSUFFICIENT_BUFFER;
2838 /* fill the buffer with the structures */
2839 for (i=0; i<*returned; i++)
2840 smb_io_printer_info_1("", buffer, &printers[i], 0);
2843 safe_free(printers);
2845 if (*needed > offered) {
2847 return ERROR_INSUFFICIENT_BUFFER;
2850 return NT_STATUS_NO_PROBLEMO;
2853 /********************************************************************
2854 enum_all_printers_info_1_local.
2855 *********************************************************************/
2856 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2858 DEBUG(4,("enum_all_printers_info_1_local\n"));
2860 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2863 /********************************************************************
2864 enum_all_printers_info_1_name.
2865 *********************************************************************/
2866 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2869 DEBUG(4,("enum_all_printers_info_1_name\n"));
2871 fstrcpy(temp, "\\\\");
2872 fstrcat(temp, global_myname);
2874 if (strequal(name, temp)) {
2875 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2878 return ERROR_INVALID_NAME;
2881 /********************************************************************
2882 enum_all_printers_info_1_remote.
2883 *********************************************************************/
2884 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2886 PRINTER_INFO_1 *printer;
2887 fstring printername;
2890 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2892 /* JFM: currently it's more a place holder than anything else.
2893 * In the spooler world there is a notion of server registration.
2894 * the print servers are registring (sp ?) on the PDC (in the same domain)
2896 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2899 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2900 return ERROR_NOT_ENOUGH_MEMORY;
2904 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2905 slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2906 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2908 init_unistr(&printer->description, desc);
2909 init_unistr(&printer->name, printername);
2910 init_unistr(&printer->comment, comment);
2911 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2913 /* check the required size. */
2914 *needed += spoolss_size_printer_info_1(printer);
2916 if (!alloc_buffer_size(buffer, *needed)) {
2918 return ERROR_INSUFFICIENT_BUFFER;
2921 /* fill the buffer with the structures */
2922 smb_io_printer_info_1("", buffer, printer, 0);
2927 if (*needed > offered) {
2929 return ERROR_INSUFFICIENT_BUFFER;
2932 return NT_STATUS_NO_PROBLEMO;
2935 /********************************************************************
2936 enum_all_printers_info_1_network.
2937 *********************************************************************/
2939 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2941 DEBUG(4,("enum_all_printers_info_1_network\n"));
2943 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2946 /********************************************************************
2947 * api_spoolss_enumprinters
2949 * called from api_spoolss_enumprinters (see this to understand)
2950 ********************************************************************/
2952 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2956 int n_services=lp_numservices();
2957 PRINTER_INFO_2 *printers=NULL;
2958 PRINTER_INFO_2 current_prt;
2960 for (snum=0; snum<n_services; snum++) {
2961 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2962 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2964 if (construct_printer_info_2(¤t_prt, snum)) {
2965 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2966 return ERROR_NOT_ENOUGH_MEMORY;
2967 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2968 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2974 /* check the required size. */
2975 for (i=0; i<*returned; i++)
2976 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2978 if (!alloc_buffer_size(buffer, *needed)) {
2979 for (i=0; i<*returned; i++) {
2980 free_devmode(printers[i].devmode);
2982 safe_free(printers);
2983 return ERROR_INSUFFICIENT_BUFFER;
2986 /* fill the buffer with the structures */
2987 for (i=0; i<*returned; i++)
2988 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2991 for (i=0; i<*returned; i++) {
2992 free_devmode(printers[i].devmode);
2994 safe_free(printers);
2996 if (*needed > offered) {
2998 return ERROR_INSUFFICIENT_BUFFER;
3001 return NT_STATUS_NO_PROBLEMO;
3004 /********************************************************************
3005 * handle enumeration of printers at level 1
3006 ********************************************************************/
3007 static uint32 enumprinters_level1( uint32 flags, fstring name,
3008 NEW_BUFFER *buffer, uint32 offered,
3009 uint32 *needed, uint32 *returned)
3011 /* Not all the flags are equals */
3013 if (flags & PRINTER_ENUM_LOCAL)
3014 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3016 if (flags & PRINTER_ENUM_NAME)
3017 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3019 if (flags & PRINTER_ENUM_REMOTE)
3020 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3022 if (flags & PRINTER_ENUM_NETWORK)
3023 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3025 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
3028 /********************************************************************
3029 * handle enumeration of printers at level 2
3030 ********************************************************************/
3031 static uint32 enumprinters_level2( uint32 flags, fstring servername,
3032 NEW_BUFFER *buffer, uint32 offered,
3033 uint32 *needed, uint32 *returned)
3037 fstrcpy(temp, "\\\\");
3038 fstrcat(temp, global_myname);
3040 if (flags & PRINTER_ENUM_LOCAL) {
3041 if (strequal(servername, temp))
3042 return enum_all_printers_info_2(buffer, offered, needed, returned);
3044 return enum_all_printers_info_2(buffer, offered, needed, returned);
3047 if (flags & PRINTER_ENUM_NAME) {
3048 if (strequal(servername, temp))
3049 return enum_all_printers_info_2(buffer, offered, needed, returned);
3051 return ERROR_INVALID_NAME;
3054 if (flags & PRINTER_ENUM_REMOTE)
3055 return ERROR_INVALID_LEVEL;
3057 return NT_STATUS_NO_PROBLEMO;
3060 /********************************************************************
3061 * handle enumeration of printers at level 5
3062 ********************************************************************/
3063 static uint32 enumprinters_level5( uint32 flags, fstring servername,
3064 NEW_BUFFER *buffer, uint32 offered,
3065 uint32 *needed, uint32 *returned)
3067 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3068 return NT_STATUS_NO_PROBLEMO;
3071 /********************************************************************
3072 * api_spoolss_enumprinters
3074 * called from api_spoolss_enumprinters (see this to understand)
3075 ********************************************************************/
3077 uint32 _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3079 uint32 flags = q_u->flags;
3080 UNISTR2 *servername = &q_u->servername;
3081 uint32 level = q_u->level;
3082 NEW_BUFFER *buffer = NULL;
3083 uint32 offered = q_u->offered;
3084 uint32 *needed = &r_u->needed;
3085 uint32 *returned = &r_u->returned;
3089 /* that's an [in out] buffer */
3090 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3091 buffer = r_u->buffer;
3093 DEBUG(4,("_spoolss_enumprinters\n"));
3100 * flags==PRINTER_ENUM_NAME
3101 * if name=="" then enumerates all printers
3102 * if name!="" then enumerate the printer
3103 * flags==PRINTER_ENUM_REMOTE
3104 * name is NULL, enumerate printers
3105 * Level 2: name!="" enumerates printers, name can't be NULL
3106 * Level 3: doesn't exist
3107 * Level 4: does a local registry lookup
3108 * Level 5: same as Level 2
3111 unistr2_to_ascii(name, servername, sizeof(name)-1);
3116 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3118 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3120 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3124 return ERROR_INVALID_LEVEL;
3128 /****************************************************************************
3129 ****************************************************************************/
3130 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3132 PRINTER_INFO_0 *printer=NULL;
3134 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3135 return ERROR_NOT_ENOUGH_MEMORY;
3137 construct_printer_info_0(printer, snum);
3139 /* check the required size. */
3140 *needed += spoolss_size_printer_info_0(printer);
3142 if (!alloc_buffer_size(buffer, *needed)) {
3144 return ERROR_INSUFFICIENT_BUFFER;
3147 /* fill the buffer with the structures */
3148 smb_io_printer_info_0("", buffer, printer, 0);
3153 if (*needed > offered) {
3154 return ERROR_INSUFFICIENT_BUFFER;
3157 return NT_STATUS_NO_PROBLEMO;
3160 /****************************************************************************
3161 ****************************************************************************/
3162 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3164 PRINTER_INFO_1 *printer=NULL;
3166 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3167 return ERROR_NOT_ENOUGH_MEMORY;
3169 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3171 /* check the required size. */
3172 *needed += spoolss_size_printer_info_1(printer);
3174 if (!alloc_buffer_size(buffer, *needed)) {
3176 return ERROR_INSUFFICIENT_BUFFER;
3179 /* fill the buffer with the structures */
3180 smb_io_printer_info_1("", buffer, printer, 0);
3185 if (*needed > offered) {
3186 return ERROR_INSUFFICIENT_BUFFER;
3189 return NT_STATUS_NO_PROBLEMO;
3192 /****************************************************************************
3193 ****************************************************************************/
3194 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3196 PRINTER_INFO_2 *printer=NULL;
3198 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3199 return ERROR_NOT_ENOUGH_MEMORY;
3201 construct_printer_info_2(printer, snum);
3203 /* check the required size. */
3204 *needed += spoolss_size_printer_info_2(printer);
3206 if (!alloc_buffer_size(buffer, *needed)) {
3207 free_printer_info_2(printer);
3208 return ERROR_INSUFFICIENT_BUFFER;
3211 /* fill the buffer with the structures */
3212 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3213 free_printer_info_2(printer);
3214 return ERROR_NOT_ENOUGH_MEMORY;
3218 free_printer_info_2(printer);
3220 if (*needed > offered) {
3221 return ERROR_INSUFFICIENT_BUFFER;
3224 return NT_STATUS_NO_PROBLEMO;
3227 /****************************************************************************
3228 ****************************************************************************/
3229 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3231 PRINTER_INFO_3 *printer=NULL;
3233 if (!construct_printer_info_3(&printer, snum))
3234 return ERROR_NOT_ENOUGH_MEMORY;
3236 /* check the required size. */
3237 *needed += spoolss_size_printer_info_3(printer);
3239 if (!alloc_buffer_size(buffer, *needed)) {
3240 free_printer_info_3(printer);
3241 return ERROR_INSUFFICIENT_BUFFER;
3244 /* fill the buffer with the structures */
3245 smb_io_printer_info_3("", buffer, printer, 0);
3248 free_printer_info_3(printer);
3250 if (*needed > offered) {
3251 return ERROR_INSUFFICIENT_BUFFER;
3254 return NT_STATUS_NO_PROBLEMO;
3257 /****************************************************************************
3258 ****************************************************************************/
3260 uint32 _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3262 POLICY_HND *handle = &q_u->handle;
3263 uint32 level = q_u->level;
3264 NEW_BUFFER *buffer = NULL;
3265 uint32 offered = q_u->offered;
3266 uint32 *needed = &r_u->needed;
3270 /* that's an [in out] buffer */
3271 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3272 buffer = r_u->buffer;
3276 if (!get_printer_snum(p, handle, &snum))
3277 return ERROR_INVALID_HANDLE;
3281 return getprinter_level_0(snum, buffer, offered, needed);
3283 return getprinter_level_1(snum, buffer, offered, needed);
3285 return getprinter_level_2(snum, buffer, offered, needed);
3287 return getprinter_level_3(snum, buffer, offered, needed);
3289 return ERROR_INVALID_LEVEL;
3293 /********************************************************************
3294 * fill a DRIVER_INFO_1 struct
3295 ********************************************************************/
3296 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3298 init_unistr( &info->name, driver.info_3->name);
3301 /********************************************************************
3302 * construct_printer_driver_info_1
3303 ********************************************************************/
3304 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3306 NT_PRINTER_INFO_LEVEL *printer = NULL;
3307 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3309 ZERO_STRUCT(driver);
3311 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3312 return ERROR_INVALID_PRINTER_NAME;
3314 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3315 return ERROR_UNKNOWN_PRINTER_DRIVER;
3317 fill_printer_driver_info_1(info, driver, servername, architecture);
3319 free_a_printer(&printer,2);
3321 return NT_STATUS_NO_PROBLEMO;
3324 /********************************************************************
3325 * construct_printer_driver_info_2
3326 * fill a printer_info_2 struct
3327 ********************************************************************/
3328 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3332 info->version=driver.info_3->cversion;
3334 init_unistr( &info->name, driver.info_3->name );
3335 init_unistr( &info->architecture, driver.info_3->environment );
3338 if (strlen(driver.info_3->driverpath)) {
3339 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3340 init_unistr( &info->driverpath, temp );
3342 init_unistr( &info->driverpath, "" );
3344 if (strlen(driver.info_3->datafile)) {
3345 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3346 init_unistr( &info->datafile, temp );
3348 init_unistr( &info->datafile, "" );
3350 if (strlen(driver.info_3->configfile)) {
3351 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3352 init_unistr( &info->configfile, temp );
3354 init_unistr( &info->configfile, "" );
3357 /********************************************************************
3358 * construct_printer_driver_info_2
3359 * fill a printer_info_2 struct
3360 ********************************************************************/
3361 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3363 NT_PRINTER_INFO_LEVEL *printer = NULL;
3364 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3366 ZERO_STRUCT(printer);
3367 ZERO_STRUCT(driver);
3369 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3370 return ERROR_INVALID_PRINTER_NAME;
3372 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3373 return ERROR_UNKNOWN_PRINTER_DRIVER;
3375 fill_printer_driver_info_2(info, driver, servername);
3377 free_a_printer(&printer,2);
3379 return NT_STATUS_NO_PROBLEMO;
3382 /********************************************************************
3383 * copy a strings array and convert to UNICODE
3385 * convert an array of ascii string to a UNICODE string
3386 ********************************************************************/
3387 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3394 DEBUG(6,("init_unistr_array\n"));
3398 if (char_array == NULL)
3402 if (!v) v = ""; /* hack to handle null lists */
3404 if (strlen(v) == 0) break;
3405 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3406 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3407 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3408 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3411 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3416 (*uni_array)[j]=0x0000;
3419 DEBUGADD(6,("last one:done\n"));
3422 /********************************************************************
3423 * construct_printer_info_3
3424 * fill a printer_info_3 struct
3425 ********************************************************************/
3426 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3432 info->version=driver.info_3->cversion;
3434 init_unistr( &info->name, driver.info_3->name );
3435 init_unistr( &info->architecture, driver.info_3->environment );
3437 if (strlen(driver.info_3->driverpath)) {
3438 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3439 init_unistr( &info->driverpath, temp );
3441 init_unistr( &info->driverpath, "" );
3443 if (strlen(driver.info_3->datafile)) {
3444 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3445 init_unistr( &info->datafile, temp );
3447 init_unistr( &info->datafile, "" );
3449 if (strlen(driver.info_3->configfile)) {
3450 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3451 init_unistr( &info->configfile, temp );
3453 init_unistr( &info->configfile, "" );
3455 if (strlen(driver.info_3->helpfile)) {
3456 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3457 init_unistr( &info->helpfile, temp );
3459 init_unistr( &info->helpfile, "" );
3461 init_unistr( &info->monitorname, driver.info_3->monitorname );
3462 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3464 info->dependentfiles=NULL;
3465 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3468 /********************************************************************
3469 * construct_printer_info_3
3470 * fill a printer_info_3 struct
3471 ********************************************************************/
3472 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3474 NT_PRINTER_INFO_LEVEL *printer = NULL;
3475 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3477 ZERO_STRUCT(driver);
3479 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3480 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3482 return ERROR_INVALID_PRINTER_NAME;
3484 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3485 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3487 free_a_printer(&printer,2);
3488 return ERROR_UNKNOWN_PRINTER_DRIVER;
3491 fill_printer_driver_info_3(info, driver, servername);
3493 free_a_printer(&printer,2);
3495 return NT_STATUS_NO_PROBLEMO;
3498 /********************************************************************
3499 * construct_printer_info_6
3500 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3501 ********************************************************************/
3503 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3509 memset(&nullstr, '\0', sizeof(fstring));
3511 info->version=driver.info_3->cversion;
3513 init_unistr( &info->name, driver.info_3->name );
3514 init_unistr( &info->architecture, driver.info_3->environment );
3516 if (strlen(driver.info_3->driverpath)) {
3517 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3518 init_unistr( &info->driverpath, temp );
3520 init_unistr( &info->driverpath, "" );
3522 if (strlen(driver.info_3->datafile)) {
3523 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3524 init_unistr( &info->datafile, temp );
3526 init_unistr( &info->datafile, "" );
3528 if (strlen(driver.info_3->configfile)) {
3529 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3530 init_unistr( &info->configfile, temp );
3532 init_unistr( &info->configfile, "" );
3534 if (strlen(driver.info_3->helpfile)) {
3535 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3536 init_unistr( &info->helpfile, temp );
3538 init_unistr( &info->helpfile, "" );
3540 init_unistr( &info->monitorname, driver.info_3->monitorname );
3541 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3543 info->dependentfiles=NULL;
3544 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3546 info->previousdrivernames=NULL;
3547 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3549 info->driver_date.low=0;
3550 info->driver_date.high=0;
3553 info->driver_version_low=0;
3554 info->driver_version_high=0;
3556 init_unistr( &info->mfgname, "");
3557 init_unistr( &info->oem_url, "");
3558 init_unistr( &info->hardware_id, "");
3559 init_unistr( &info->provider, "");
3562 /********************************************************************
3563 * construct_printer_info_6
3564 * fill a printer_info_6 struct
3565 ********************************************************************/
3566 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3568 NT_PRINTER_INFO_LEVEL *printer = NULL;
3569 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3571 ZERO_STRUCT(driver);
3573 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3574 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3576 return ERROR_INVALID_PRINTER_NAME;
3578 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3579 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3582 * Is this a W2k client ?
3586 free_a_printer(&printer,2);
3587 return ERROR_UNKNOWN_PRINTER_DRIVER;
3590 /* Yes - try again with a WinNT driver. */
3592 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3593 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3595 free_a_printer(&printer,2);
3596 return ERROR_UNKNOWN_PRINTER_DRIVER;
3600 fill_printer_driver_info_6(info, driver, servername);
3602 free_a_printer(&printer,2);
3604 return NT_STATUS_NO_PROBLEMO;
3607 /****************************************************************************
3608 ****************************************************************************/
3610 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3612 safe_free(info->dependentfiles);
3615 /****************************************************************************
3616 ****************************************************************************/
3618 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3620 safe_free(info->dependentfiles);
3624 /****************************************************************************
3625 ****************************************************************************/
3626 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3628 DRIVER_INFO_1 *info=NULL;
3631 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3632 return ERROR_NOT_ENOUGH_MEMORY;
3634 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3635 if (status != NT_STATUS_NO_PROBLEMO) {
3640 /* check the required size. */
3641 *needed += spoolss_size_printer_driver_info_1(info);
3643 if (!alloc_buffer_size(buffer, *needed)) {
3645 return ERROR_INSUFFICIENT_BUFFER;
3648 /* fill the buffer with the structures */
3649 smb_io_printer_driver_info_1("", buffer, info, 0);
3654 if (*needed > offered)
3655 return ERROR_INSUFFICIENT_BUFFER;
3657 return NT_STATUS_NO_PROBLEMO;
3660 /****************************************************************************
3661 ****************************************************************************/
3662 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3664 DRIVER_INFO_2 *info=NULL;
3667 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3668 return ERROR_NOT_ENOUGH_MEMORY;
3670 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3671 if (status != NT_STATUS_NO_PROBLEMO) {
3676 /* check the required size. */
3677 *needed += spoolss_size_printer_driver_info_2(info);
3679 if (!alloc_buffer_size(buffer, *needed)) {
3681 return ERROR_INSUFFICIENT_BUFFER;
3684 /* fill the buffer with the structures */
3685 smb_io_printer_driver_info_2("", buffer, info, 0);
3690 if (*needed > offered)
3691 return ERROR_INSUFFICIENT_BUFFER;
3693 return NT_STATUS_NO_PROBLEMO;
3696 /****************************************************************************
3697 ****************************************************************************/
3698 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3705 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3706 if (status != NT_STATUS_NO_PROBLEMO) {
3710 /* check the required size. */
3711 *needed += spoolss_size_printer_driver_info_3(&info);
3713 if (!alloc_buffer_size(buffer, *needed)) {
3714 free_printer_driver_info_3(&info);
3715 return ERROR_INSUFFICIENT_BUFFER;
3718 /* fill the buffer with the structures */
3719 smb_io_printer_driver_info_3("", buffer, &info, 0);
3721 free_printer_driver_info_3(&info);
3723 if (*needed > offered)
3724 return ERROR_INSUFFICIENT_BUFFER;
3726 return NT_STATUS_NO_PROBLEMO;
3729 /****************************************************************************
3730 ****************************************************************************/
3731 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3738 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3739 if (status != NT_STATUS_NO_PROBLEMO) {
3743 /* check the required size. */
3744 *needed += spoolss_size_printer_driver_info_6(&info);
3746 if (!alloc_buffer_size(buffer, *needed)) {
3747 free_printer_driver_info_6(&info);
3748 return ERROR_INSUFFICIENT_BUFFER;
3751 /* fill the buffer with the structures */
3752 smb_io_printer_driver_info_6("", buffer, &info, 0);
3754 free_printer_driver_info_6(&info);
3756 if (*needed > offered)
3757 return ERROR_INSUFFICIENT_BUFFER;
3759 return NT_STATUS_NO_PROBLEMO;
3762 /****************************************************************************
3763 ****************************************************************************/
3765 uint32 _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3767 POLICY_HND *handle = &q_u->handle;
3768 UNISTR2 *uni_arch = &q_u->architecture;
3769 uint32 level = q_u->level;
3770 uint32 clientmajorversion = q_u->clientmajorversion;
3771 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3772 NEW_BUFFER *buffer = NULL;
3773 uint32 offered = q_u->offered;
3774 uint32 *needed = &r_u->needed;
3775 uint32 *servermajorversion = &r_u->servermajorversion;
3776 uint32 *serverminorversion = &r_u->serverminorversion;
3779 fstring architecture;
3782 /* that's an [in out] buffer */
3783 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3784 buffer = r_u->buffer;
3786 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3789 *servermajorversion=0;
3790 *serverminorversion=0;
3792 pstrcpy(servername, global_myname);
3793 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3795 if (!get_printer_snum(p, handle, &snum))
3796 return ERROR_INVALID_HANDLE;
3800 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3802 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3804 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3806 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3808 return ERROR_INVALID_LEVEL;
3812 /****************************************************************************
3813 ****************************************************************************/
3815 uint32 _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
3817 POLICY_HND *handle = &q_u->handle;
3819 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3822 Printer->page_started=True;
3826 DEBUG(3,("Error in startpageprinter printer handle\n"));
3827 return ERROR_INVALID_HANDLE;
3830 /****************************************************************************
3831 ****************************************************************************/
3833 uint32 _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
3835 POLICY_HND *handle = &q_u->handle;
3837 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3840 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3841 return ERROR_INVALID_HANDLE;
3844 Printer->page_started=False;
3846 return NT_STATUS_NO_PROBLEMO;
3849 /********************************************************************
3850 * api_spoolss_getprinter
3851 * called from the spoolss dispatcher
3853 ********************************************************************/
3855 uint32 _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
3857 POLICY_HND *handle = &q_u->handle;
3858 /* uint32 level = q_u->doc_info_container.level; - notused. */
3859 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
3860 uint32 *jobid = &r_u->jobid;
3862 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3866 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3867 struct current_user user;
3870 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3871 return ERROR_INVALID_HANDLE;
3874 get_current_user(&user, p);
3877 * a nice thing with NT is it doesn't listen to what you tell it.
3878 * when asked to send _only_ RAW datas, it tries to send datas
3881 * So I add checks like in NT Server ...
3883 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3884 * there's a bug in NT client-side code, so we'll fix it in the
3885 * server-side code. *nnnnnggggh!*
3888 if (info_1->p_datatype != 0) {
3889 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3890 if (strcmp(datatype, "RAW") != 0) {
3892 return ERROR_INVALID_DATATYPE;
3896 /* get the share number of the printer */
3897 if (!get_printer_snum(p, handle, &snum)) {
3898 return ERROR_INVALID_HANDLE;
3901 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3903 Printer->jobid = print_job_start(&user, snum, jobname);
3905 /* An error occured in print_job_start() so return an appropriate
3908 if (Printer->jobid == -1) {
3909 return map_nt_error_from_unix(errno);
3912 Printer->document_started=True;
3913 (*jobid) = Printer->jobid;
3918 /********************************************************************
3919 * api_spoolss_getprinter
3920 * called from the spoolss dispatcher
3922 ********************************************************************/
3924 uint32 _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
3926 POLICY_HND *handle = &q_u->handle;
3928 return _spoolss_enddocprinter_internal(p, handle);
3931 /****************************************************************************
3932 ****************************************************************************/
3934 uint32 _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
3936 POLICY_HND *handle = &q_u->handle;
3937 uint32 buffer_size = q_u->buffer_size;
3938 uint8 *buffer = q_u->buffer;
3939 uint32 *buffer_written = &q_u->buffer_size2;
3941 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3944 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3945 r_u->buffer_written = q_u->buffer_size2;
3946 return ERROR_INVALID_HANDLE;
3949 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
3952 r_u->buffer_written = q_u->buffer_size2;
3957 /********************************************************************
3958 * api_spoolss_getprinter
3959 * called from the spoolss dispatcher
3961 ********************************************************************/
3962 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3965 struct current_user user;
3966 int snum, errcode = ERROR_INVALID_FUNCTION;
3967 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3969 get_current_user(&user, p);
3972 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3973 return ERROR_INVALID_HANDLE;
3976 if (!get_printer_snum(p, handle, &snum))
3977 return ERROR_INVALID_HANDLE;
3980 case PRINTER_CONTROL_PAUSE:
3981 if (print_queue_pause(&user, snum, &errcode)) {
3985 case PRINTER_CONTROL_RESUME:
3986 case PRINTER_CONTROL_UNPAUSE:
3987 if (print_queue_resume(&user, snum, &errcode)) {
3991 case PRINTER_CONTROL_PURGE:
3992 if (print_queue_purge(&user, snum, &errcode)) {
3997 return ERROR_INVALID_LEVEL;
4003 /********************************************************************
4004 * api_spoolss_abortprinter
4005 ********************************************************************/
4007 uint32 _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4009 POLICY_HND *handle = &q_u->handle;
4011 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4014 /********************************************************************
4015 * called by spoolss_api_setprinter
4016 * when updating a printer description
4017 ********************************************************************/
4018 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
4019 const SPOOL_PRINTER_INFO_LEVEL *info,
4020 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4022 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4023 struct current_user user;
4027 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4029 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4030 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4031 OUR_HANDLE(handle)));
4033 result = ERROR_INVALID_HANDLE;
4037 /* NT seems to like setting the security descriptor even though
4038 nothing may have actually changed. This causes annoying
4039 dialog boxes when the user doesn't have permission to change
4040 the security descriptor. */
4042 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4044 if (DEBUGLEVEL >= 10) {
4048 acl = old_secdesc_ctr->sec->dacl;
4049 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4050 PRINTERNAME(snum), acl->num_aces));
4052 for (i = 0; i < acl->num_aces; i++) {
4055 sid_to_string(sid_str, &acl->ace[i].sid);
4057 DEBUG(10, ("%s 0x%08x\n", sid_str,
4058 acl->ace[i].info.mask));
4061 acl = secdesc_ctr->sec->dacl;
4064 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4065 PRINTERNAME(snum), acl->num_aces));
4067 for (i = 0; i < acl->num_aces; i++) {
4070 sid_to_string(sid_str, &acl->ace[i].sid);
4072 DEBUG(10, ("%s 0x%08x\n", sid_str,
4073 acl->ace[i].info.mask));
4076 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4080 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4082 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4083 result = NT_STATUS_NO_PROBLEMO;
4087 /* Work out which user is performing the operation */
4089 get_current_user(&user, p);
4091 /* Check the user has permissions to change the security
4092 descriptor. By experimentation with two NT machines, the user
4093 requires Full Access to the printer to change security
4096 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4097 result = ERROR_ACCESS_DENIED;
4101 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4108 /********************************************************************
4109 Do Samba sanity checks on a printer info struct.
4110 this has changed purpose: it now "canonicalises" printer
4111 info from a client rather than just checking it is correct
4112 ********************************************************************/
4114 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4116 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4117 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4119 /* we force some elements to "correct" values */
4120 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4121 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4122 global_myname, lp_servicename(snum));
4123 fstrcpy(info->sharename, lp_servicename(snum));
4124 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4125 | PRINTER_ATTRIBUTE_LOCAL \
4126 | PRINTER_ATTRIBUTE_RAW_ONLY \
4127 | PRINTER_ATTRIBUTE_QUEUED ;
4132 /****************************************************************************
4133 ****************************************************************************/
4134 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4136 pid_t local_pid = sys_getpid();
4137 char *cmd = lp_addprinter_cmd();
4142 pstring driverlocation;
4146 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4147 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4151 /* build driver path... only 9X architecture is needed for legacy reasons */
4152 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4154 /* change \ to \\ for the shell */
4155 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4157 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
4158 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4159 cmd, printer->info_2->printername, printer->info_2->sharename,
4160 printer->info_2->portname, printer->info_2->drivername,
4161 printer->info_2->location, driverlocation);
4165 /* Convert script args to unix-codepage */
4166 dos_to_unix(command, True);
4167 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4168 ret = smbrun(command, tmp_file, False);
4169 DEBUGADD(10,("returned [%d]\n", ret));
4177 /* Get lines and convert them back to dos-codepage */
4178 qlines = file_lines_load(tmp_file, &numlines, True);
4179 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4180 DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
4184 /* Set the portname to what the script says the portname should be. */
4185 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4186 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4188 /* Send SIGHUP to process group... is there a better way? */
4193 file_lines_free(qlines);
4197 /* Return true if two devicemodes are equal */
4199 #define DEVMODE_CHECK_INT(field) \
4200 if (d1->field != d2->field) { \
4201 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4202 d1->field, d2->field)); \
4206 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4208 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4211 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4212 return False; /* if either is exclusively NULL are not equal */
4215 if (!strequal(d1->devicename, d2->devicename)) {
4216 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4220 if (!strequal(d1->formname, d2->formname)) {
4221 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4225 DEVMODE_CHECK_INT(specversion);
4226 DEVMODE_CHECK_INT(driverversion);
4227 DEVMODE_CHECK_INT(driverextra);
4228 DEVMODE_CHECK_INT(orientation);
4229 DEVMODE_CHECK_INT(papersize);
4230 DEVMODE_CHECK_INT(paperlength);
4231 DEVMODE_CHECK_INT(paperwidth);
4232 DEVMODE_CHECK_INT(scale);
4233 DEVMODE_CHECK_INT(copies);
4234 DEVMODE_CHECK_INT(defaultsource);
4235 DEVMODE_CHECK_INT(printquality);
4236 DEVMODE_CHECK_INT(color);
4237 DEVMODE_CHECK_INT(duplex);
4238 DEVMODE_CHECK_INT(yresolution);
4239 DEVMODE_CHECK_INT(ttoption);
4240 DEVMODE_CHECK_INT(collate);
4241 DEVMODE_CHECK_INT(logpixels);
4243 DEVMODE_CHECK_INT(fields);
4244 DEVMODE_CHECK_INT(bitsperpel);
4245 DEVMODE_CHECK_INT(pelswidth);
4246 DEVMODE_CHECK_INT(pelsheight);
4247 DEVMODE_CHECK_INT(displayflags);
4248 DEVMODE_CHECK_INT(displayfrequency);
4249 DEVMODE_CHECK_INT(icmmethod);
4250 DEVMODE_CHECK_INT(icmintent);
4251 DEVMODE_CHECK_INT(mediatype);
4252 DEVMODE_CHECK_INT(dithertype);
4253 DEVMODE_CHECK_INT(reserved1);
4254 DEVMODE_CHECK_INT(reserved2);
4255 DEVMODE_CHECK_INT(panningwidth);
4256 DEVMODE_CHECK_INT(panningheight);
4258 /* compare the private data if it exists */
4259 if (!d1->driverextra && !d2->driverextra) goto equal;
4262 DEVMODE_CHECK_INT(driverextra);
4264 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4265 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4270 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4274 /* Return true if two NT_PRINTER_PARAM structures are equal */
4276 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4277 NT_PRINTER_PARAM *p2)
4279 if (!p1 && !p2) goto equal;
4281 if ((!p1 && p2) || (p1 && !p2)) {
4282 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4286 /* Compare lists of printer parameters */
4290 NT_PRINTER_PARAM *q = p1;
4292 /* Find the parameter in the second structure */
4296 if (strequal(p1->value, q->value)) {
4298 if (p1->type != q->type) {
4299 DEBUG(10, ("nt_printer_param_equal():"
4300 "types for %s differ (%d != %d)\n",
4301 p1->value, p1->type,
4306 if (p1->data_len != q->data_len) {
4307 DEBUG(10, ("nt_printer_param_equal():"
4308 "len for %s differs (%d != %d)\n",
4309 p1->value, p1->data_len,
4314 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4317 DEBUG(10, ("nt_printer_param_equal():"
4318 "data for %s differs\n", p1->value));
4328 DEBUG(10, ("nt_printer_param_equal(): param %s "
4329 "does not exist\n", p1->value));
4338 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4342 /********************************************************************
4343 * Called by update_printer when trying to work out whether to
4344 * actually update printer info.
4345 ********************************************************************/
4347 #define PI_CHECK_INT(field) \
4348 if (pi1->field != pi2->field) { \
4349 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4350 pi1->field, pi2->field)); \
4354 #define PI_CHECK_STR(field) \
4355 if (!strequal(pi1->field, pi2->field)) { \
4356 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4357 pi1->field, pi2->field)); \
4361 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4362 NT_PRINTER_INFO_LEVEL *p2)
4364 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4366 /* Trivial conditions */
4368 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4372 if ((!p1 && p2) || (p1 && !p2) ||
4373 (!p1->info_2 && p2->info_2) ||
4374 (p1->info_2 && !p2->info_2)) {
4375 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4380 /* Compare two nt_printer_info_level structures. Don't compare
4381 status or cjobs as they seem to have something to do with the
4387 /* Don't check the attributes as we stomp on the value in
4388 check_printer_ok() anyway. */
4391 PI_CHECK_INT(attributes);
4394 PI_CHECK_INT(priority);
4395 PI_CHECK_INT(default_priority);
4396 PI_CHECK_INT(starttime);
4397 PI_CHECK_INT(untiltime);
4398 PI_CHECK_INT(averageppm);
4400 /* Yuck - don't check the printername or servername as the
4401 add_a_printer() code plays games with them. You can't
4402 change the printername or the sharename through this interface
4405 PI_CHECK_STR(sharename);
4406 PI_CHECK_STR(portname);
4407 PI_CHECK_STR(drivername);
4408 PI_CHECK_STR(comment);
4409 PI_CHECK_STR(location);
4411 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4415 PI_CHECK_STR(sepfile);
4416 PI_CHECK_STR(printprocessor);
4417 PI_CHECK_STR(datatype);
4418 PI_CHECK_STR(parameters);
4420 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4424 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4428 PI_CHECK_INT(changeid);
4429 PI_CHECK_INT(c_setprinter);
4430 PI_CHECK_INT(setuptime);
4433 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4437 /********************************************************************
4438 * called by spoolss_api_setprinter
4439 * when updating a printer description
4440 ********************************************************************/
4442 static uint32 update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4443 const SPOOL_PRINTER_INFO_LEVEL *info,
4444 DEVICEMODE *devmode)
4447 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4448 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4451 DEBUG(8,("update_printer\n"));
4453 result = NT_STATUS_NO_PROBLEMO;
4456 DEBUG(0,("Send a mail to samba@samba.org\n"));
4457 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4458 result = ERROR_INVALID_LEVEL;
4463 result = ERROR_INVALID_HANDLE;
4467 if (!get_printer_snum(p, handle, &snum)) {
4468 result = ERROR_INVALID_HANDLE;
4472 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4473 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4474 result = ERROR_INVALID_HANDLE;
4478 DEBUGADD(8,("Converting info_2 struct\n"));
4481 * convert_printer_info converts the incoming
4482 * info from the client and overwrites the info
4483 * just read from the tdb in the pointer 'printer'.
4486 convert_printer_info(info, printer, level);
4488 if (info->info_2->devmode_ptr != 0) {
4489 /* we have a valid devmode
4490 convert it and link it*/
4492 DEBUGADD(8,("Converting the devicemode struct\n"));
4493 if (!convert_devicemode(printer->info_2->printername, devmode,
4494 &printer->info_2->devmode)) {
4495 result = ERROR_NOT_ENOUGH_MEMORY;
4500 /* Do sanity check on the requested changes for Samba */
4502 if (!check_printer_ok(printer->info_2, snum)) {
4503 result = ERROR_INVALID_PARAMETER;
4507 /* NT likes to call this function even though nothing has actually
4508 changed. Check this so the user doesn't end up with an
4509 annoying permission denied dialog box. */
4511 if (nt_printer_info_level_equal(printer, old_printer)) {
4512 DEBUG(3, ("printer info has not changed\n"));
4513 result = NT_STATUS_NO_PROBLEMO;
4517 /* Check calling user has permission to update printer description */
4519 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4520 DEBUG(3, ("printer property change denied by security "
4522 result = ERROR_ACCESS_DENIED;
4526 /* Call addprinter hook */
4528 if (*lp_addprinter_cmd() )
4529 if ( !add_printer_hook(printer) ) {
4530 result = ERROR_ACCESS_DENIED;
4534 /* Update printer info */
4536 if (add_a_printer(*printer, 2)!=0) {
4537 /* I don't really know what to return here !!! */
4538 result = ERROR_ACCESS_DENIED;
4543 free_a_printer(&printer, 2);
4544 free_a_printer(&old_printer, 2);
4546 srv_spoolss_sendnotify(p, handle);
4551 /****************************************************************************
4552 ****************************************************************************/
4554 uint32 _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4556 POLICY_HND *handle = &q_u->handle;
4557 uint32 level = q_u->level;
4558 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4559 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4560 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4561 uint32 command = q_u->command;
4563 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4566 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4567 return ERROR_INVALID_HANDLE;
4570 /* check the level */
4573 return control_printer(handle, command, p);
4575 return update_printer(p, handle, level, info, devmode_ctr.devmode);
4577 return update_printer_sec(handle, level, info, p,
4580 return ERROR_INVALID_LEVEL;
4584 /****************************************************************************
4585 ****************************************************************************/
4587 uint32 _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4589 POLICY_HND *handle = &q_u->handle;
4591 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4594 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4595 return ERROR_INVALID_HANDLE;
4598 if (Printer->notify.client_connected==True)
4599 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4601 Printer->notify.flags=0;
4602 Printer->notify.options=0;
4603 Printer->notify.localmachine[0]='\0';
4604 Printer->notify.printerlocal=0;
4605 if (Printer->notify.option)
4606 free_spool_notify_option(&Printer->notify.option);
4607 Printer->notify.client_connected=False;
4609 return NT_STATUS_NO_PROBLEMO;
4612 /****************************************************************************
4613 ****************************************************************************/
4615 uint32 _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4617 /* that's an [in out] buffer (despite appearences to the contrary) */
4618 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4621 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4622 returns for AddJob. AddJob
4623 must fail on non-local
4627 /****************************************************************************
4628 ****************************************************************************/
4629 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4630 int position, int snum)
4636 t=gmtime(&queue->time);
4637 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4639 job_info->jobid=queue->job;
4640 init_unistr(&job_info->printername, lp_servicename(snum));
4641 init_unistr(&job_info->machinename, temp_name);
4642 init_unistr(&job_info->username, queue->user);
4643 init_unistr(&job_info->document, queue->file);
4644 init_unistr(&job_info->datatype, "RAW");
4645 init_unistr(&job_info->text_status, "");
4646 job_info->status=nt_printj_status(queue->status);
4647 job_info->priority=queue->priority;
4648 job_info->position=position;
4649 job_info->totalpages=0;
4650 job_info->pagesprinted=0;
4652 make_systemtime(&job_info->submitted, t);
4655 /****************************************************************************
4656 ****************************************************************************/
4657 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4658 int position, int snum,
4659 NT_PRINTER_INFO_LEVEL *ntprinter)
4665 t=gmtime(&queue->time);
4666 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4668 job_info->jobid=queue->job;
4670 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4672 init_unistr(&job_info->printername, chaine);
4674 init_unistr(&job_info->machinename, temp_name);
4675 init_unistr(&job_info->username, queue->user);
4676 init_unistr(&job_info->document, queue->file);
4677 init_unistr(&job_info->notifyname, queue->user);
4678 init_unistr(&job_info->datatype, "RAW");
4679 init_unistr(&job_info->printprocessor, "winprint");
4680 init_unistr(&job_info->parameters, "");
4681 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4682 init_unistr(&job_info->text_status, "");
4684 /* and here the security descriptor */
4686 job_info->status=nt_printj_status(queue->status);
4687 job_info->priority=queue->priority;
4688 job_info->position=position;
4689 job_info->starttime=0;
4690 job_info->untiltime=0;
4691 job_info->totalpages=0;
4692 job_info->size=queue->size;
4693 make_systemtime(&(job_info->submitted), t);
4694 job_info->timeelapsed=0;
4695 job_info->pagesprinted=0;
4697 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4704 /****************************************************************************
4705 Enumjobs at level 1.
4706 ****************************************************************************/
4707 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4708 NEW_BUFFER *buffer, uint32 offered,
4709 uint32 *needed, uint32 *returned)
4714 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4718 return ERROR_NOT_ENOUGH_MEMORY;
4721 for (i=0; i<*returned; i++)
4722 fill_job_info_1(&info[i], &queue[i], i, snum);
4726 /* check the required size. */
4727 for (i=0; i<*returned; i++)
4728 (*needed) += spoolss_size_job_info_1(&info[i]);
4730 if (!alloc_buffer_size(buffer, *needed)) {
4732 return ERROR_INSUFFICIENT_BUFFER;
4735 /* fill the buffer with the structures */
4736 for (i=0; i<*returned; i++)
4737 smb_io_job_info_1("", buffer, &info[i], 0);
4742 if (*needed > offered) {
4744 return ERROR_INSUFFICIENT_BUFFER;
4747 return NT_STATUS_NO_PROBLEMO;
4750 /****************************************************************************
4751 Enumjobs at level 2.
4752 ****************************************************************************/
4753 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4754 NEW_BUFFER *buffer, uint32 offered,
4755 uint32 *needed, uint32 *returned)
4757 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4761 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4764 return ERROR_NOT_ENOUGH_MEMORY;
4767 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4769 return ERROR_NOT_ENOUGH_MEMORY;
4772 for (i=0; i<*returned; i++)
4773 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4775 free_a_printer(&ntprinter, 2);
4778 /* check the required size. */
4779 for (i=0; i<*returned; i++)
4780 (*needed) += spoolss_size_job_info_2(&info[i]);
4782 if (!alloc_buffer_size(buffer, *needed)) {
4784 return ERROR_INSUFFICIENT_BUFFER;
4787 /* fill the buffer with the structures */
4788 for (i=0; i<*returned; i++)
4789 smb_io_job_info_2("", buffer, &info[i], 0);
4792 for (i = 0; i < *returned; i++)
4793 free_job_info_2(&info[i]);
4797 if (*needed > offered) {
4799 return ERROR_INSUFFICIENT_BUFFER;
4802 return NT_STATUS_NO_PROBLEMO;
4805 /****************************************************************************
4807 ****************************************************************************/
4809 uint32 _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4811 POLICY_HND *handle = &q_u->handle;
4812 /* uint32 firstjob = q_u->firstjob; - notused. */
4813 /* uint32 numofjobs = q_u->numofjobs; - notused. */
4814 uint32 level = q_u->level;
4815 NEW_BUFFER *buffer = NULL;
4816 uint32 offered = q_u->offered;
4817 uint32 *needed = &r_u->needed;
4818 uint32 *returned = &r_u->returned;
4821 print_queue_struct *queue=NULL;
4822 print_status_struct prt_status;
4824 /* that's an [in out] buffer */
4825 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4826 buffer = r_u->buffer;
4828 DEBUG(4,("_spoolss_enumjobs\n"));
4830 ZERO_STRUCT(prt_status);
4835 if (!get_printer_snum(p, handle, &snum))
4836 return ERROR_INVALID_HANDLE;
4838 *returned = print_queue_status(snum, &queue, &prt_status);
4839 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4841 if (*returned == 0) {
4843 return NT_STATUS_NO_PROBLEMO;
4848 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4850 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4854 return ERROR_INVALID_LEVEL;
4858 /****************************************************************************
4859 ****************************************************************************/
4861 uint32 _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
4866 /****************************************************************************
4867 ****************************************************************************/
4869 uint32 _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
4871 POLICY_HND *handle = &q_u->handle;
4872 uint32 jobid = q_u->jobid;
4873 /* uint32 level = q_u->level; - notused. */
4874 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
4875 uint32 command = q_u->command;
4877 struct current_user user;
4878 print_status_struct prt_status;
4879 int snum, errcode = ERROR_INVALID_FUNCTION;
4881 memset(&prt_status, 0, sizeof(prt_status));
4883 if (!get_printer_snum(p, handle, &snum)) {
4884 return ERROR_INVALID_HANDLE;
4887 if (!print_job_exists(jobid)) {
4888 return ERROR_INVALID_PRINTER_NAME;
4891 get_current_user(&user, p);
4894 case JOB_CONTROL_CANCEL:
4895 case JOB_CONTROL_DELETE:
4896 if (print_job_delete(&user, jobid, &errcode)) {
4900 case JOB_CONTROL_PAUSE:
4901 if (print_job_pause(&user, jobid, &errcode)) {
4905 case JOB_CONTROL_RESTART:
4906 case JOB_CONTROL_RESUME:
4907 if (print_job_resume(&user, jobid, &errcode)) {
4912 return ERROR_INVALID_LEVEL;
4918 /****************************************************************************
4919 Enumerates all printer drivers at level 1.
4920 ****************************************************************************/
4921 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4926 fstring *list = NULL;
4928 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4929 DRIVER_INFO_1 *driver_info_1=NULL;
4933 #define MAX_VERSION 4
4935 for (version=0; version<MAX_VERSION; version++) {
4937 ndrivers=get_ntdrivers(&list, architecture, version);
4938 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4941 return ERROR_NOT_ENOUGH_MEMORY;
4944 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4946 return ERROR_NOT_ENOUGH_MEMORY;
4950 for (i=0; i<ndrivers; i++) {
4952 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4953 ZERO_STRUCT(driver);
4954 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4958 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
4959 free_a_printer_driver(driver, 3);
4962 *returned+=ndrivers;
4966 /* check the required size. */
4967 for (i=0; i<*returned; i++) {
4968 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4969 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4972 if (!alloc_buffer_size(buffer, *needed)) {
4973 safe_free(driver_info_1);
4974 return ERROR_INSUFFICIENT_BUFFER;
4977 /* fill the buffer with the driver structures */
4978 for (i=0; i<*returned; i++) {
4979 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4980 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4983 safe_free(driver_info_1);
4985 if (*needed > offered) {
4987 return ERROR_INSUFFICIENT_BUFFER;
4990 return NT_STATUS_NO_PROBLEMO;
4993 /****************************************************************************
4994 Enumerates all printer drivers at level 2.
4995 ****************************************************************************/
4996 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5001 fstring *list = NULL;
5003 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5004 DRIVER_INFO_2 *driver_info_2=NULL;
5008 #define MAX_VERSION 4
5010 for (version=0; version<MAX_VERSION; version++) {
5012 ndrivers=get_ntdrivers(&list, architecture, version);
5013 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5016 return ERROR_NOT_ENOUGH_MEMORY;
5019 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5021 return ERROR_NOT_ENOUGH_MEMORY;
5025 for (i=0; i<ndrivers; i++) {
5028 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5029 ZERO_STRUCT(driver);
5030 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5034 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5035 free_a_printer_driver(driver, 3);
5038 *returned+=ndrivers;
5042 /* check the required size. */
5043 for (i=0; i<*returned; i++) {
5044 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5045 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5048 if (!alloc_buffer_size(buffer, *needed)) {
5049 safe_free(driver_info_2);
5050 return ERROR_INSUFFICIENT_BUFFER;
5053 /* fill the buffer with the form structures */
5054 for (i=0; i<*returned; i++) {
5055 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5056 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5059 safe_free(driver_info_2);
5061 if (*needed > offered) {
5063 return ERROR_INSUFFICIENT_BUFFER;
5066 return NT_STATUS_NO_PROBLEMO;
5069 /****************************************************************************
5070 Enumerates all printer drivers at level 3.
5071 ****************************************************************************/
5072 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5077 fstring *list = NULL;
5079 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5080 DRIVER_INFO_3 *driver_info_3=NULL;
5084 #define MAX_VERSION 4
5086 for (version=0; version<MAX_VERSION; version++) {
5088 ndrivers=get_ntdrivers(&list, architecture, version);
5089 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5092 return ERROR_NOT_ENOUGH_MEMORY;
5095 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5097 return ERROR_NOT_ENOUGH_MEMORY;
5101 for (i=0; i<ndrivers; i++) {
5104 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5105 ZERO_STRUCT(driver);
5106 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5110 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5111 free_a_printer_driver(driver, 3);
5114 *returned+=ndrivers;
5118 /* check the required size. */
5119 for (i=0; i<*returned; i++) {
5120 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5121 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5124 if (!alloc_buffer_size(buffer, *needed)) {
5125 safe_free(driver_info_3);
5126 return ERROR_INSUFFICIENT_BUFFER;
5129 /* fill the buffer with the driver structures */
5130 for (i=0; i<*returned; i++) {
5131 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5132 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5135 for (i=0; i<*returned; i++)
5136 safe_free(driver_info_3[i].dependentfiles);
5138 safe_free(driver_info_3);
5140 if (*needed > offered) {
5142 return ERROR_INSUFFICIENT_BUFFER;
5145 return NT_STATUS_NO_PROBLEMO;
5148 /****************************************************************************
5149 Enumerates all printer drivers.
5150 ****************************************************************************/
5152 uint32 _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5154 /* UNISTR2 *name = &q_u->name; - notused. */
5155 UNISTR2 *environment = &q_u->environment;
5156 uint32 level = q_u->level;
5157 NEW_BUFFER *buffer = NULL;
5158 uint32 offered = q_u->offered;
5159 uint32 *needed = &r_u->needed;
5160 uint32 *returned = &r_u->returned;
5162 fstring *list = NULL;
5164 fstring architecture;
5166 /* that's an [in out] buffer */
5167 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5168 buffer = r_u->buffer;
5170 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5171 fstrcpy(servername, global_myname);
5175 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5179 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5181 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5183 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5187 return ERROR_INVALID_LEVEL;
5191 /****************************************************************************
5192 ****************************************************************************/
5194 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5196 form->flag=list->flag;
5197 init_unistr(&form->name, list->name);
5198 form->width=list->width;
5199 form->length=list->length;
5200 form->left=list->left;
5201 form->top=list->top;
5202 form->right=list->right;
5203 form->bottom=list->bottom;
5206 /****************************************************************************
5207 ****************************************************************************/
5209 uint32 _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5211 /* POLICY_HND *handle = &q_u->handle; - notused. */
5212 uint32 level = q_u->level;
5213 NEW_BUFFER *buffer = NULL;
5214 uint32 offered = q_u->offered;
5215 uint32 *needed = &r_u->needed;
5216 uint32 *numofforms = &r_u->numofforms;
5217 uint32 numbuiltinforms;
5219 nt_forms_struct *list=NULL;
5220 nt_forms_struct *builtinlist=NULL;
5225 /* that's an [in out] buffer */
5226 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5227 buffer = r_u->buffer;
5229 DEBUG(4,("_spoolss_enumforms\n"));
5230 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5231 DEBUGADD(5,("Info level [%d]\n", level));
5233 numbuiltinforms = get_builtin_ntforms(&builtinlist);
5234 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
5235 *numofforms = get_ntforms(&list);
5236 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
5237 *numofforms += numbuiltinforms;
5239 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
5243 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5245 return ERROR_NOT_ENOUGH_MEMORY;
5248 /* construct the list of form structures */
5249 for (i=0; i<numbuiltinforms; i++) {
5250 DEBUGADD(6,("Filling form number [%d]\n",i));
5251 fill_form_1(&forms_1[i], &builtinlist[i]);
5254 safe_free(builtinlist);
5256 for (; i<*numofforms; i++) {
5257 DEBUGADD(6,("Filling form number [%d]\n",i));
5258 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5263 /* check the required size. */
5264 for (i=0; i<numbuiltinforms; i++) {
5265 DEBUGADD(6,("adding form [%d]'s size\n",i));
5266 buffer_size += spoolss_size_form_1(&forms_1[i]);
5268 for (; i<*numofforms; i++) {
5269 DEBUGADD(6,("adding form [%d]'s size\n",i));
5270 buffer_size += spoolss_size_form_1(&forms_1[i]);
5273 *needed=buffer_size;
5275 if (!alloc_buffer_size(buffer, buffer_size)){
5277 return ERROR_INSUFFICIENT_BUFFER;
5280 /* fill the buffer with the form structures */
5281 for (i=0; i<numbuiltinforms; i++) {
5282 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5283 smb_io_form_1("", buffer, &forms_1[i], 0);
5285 for (; i<*numofforms; i++) {
5286 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5287 smb_io_form_1("", buffer, &forms_1[i], 0);
5292 if (*needed > offered) {
5294 return ERROR_INSUFFICIENT_BUFFER;
5297 return NT_STATUS_NO_PROBLEMO;
5301 safe_free(builtinlist);
5302 return ERROR_INVALID_LEVEL;
5307 /****************************************************************************
5308 ****************************************************************************/
5310 uint32 _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5312 /* POLICY_HND *handle = &q_u->handle; - notused. */
5313 uint32 level = q_u->level;
5314 UNISTR2 *uni_formname = &q_u->formname;
5315 NEW_BUFFER *buffer = NULL;
5316 uint32 offered = q_u->offered;
5317 uint32 *needed = &r_u->needed;
5319 nt_forms_struct *list=NULL;
5320 nt_forms_struct builtin_form;
5327 /* that's an [in out] buffer */
5328 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5329 buffer = r_u->buffer;
5331 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5333 DEBUG(4,("_spoolss_getform\n"));
5334 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5335 DEBUGADD(5,("Info level [%d]\n", level));
5337 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5338 if (!foundBuiltin) {
5339 numofforms = get_ntforms(&list);
5340 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5342 if (numofforms == 0)
5343 return ERROR_INVALID_HANDLE;
5349 fill_form_1(&form_1, &builtin_form);
5352 /* Check if the requested name is in the list of form structures */
5353 for (i=0; i<numofforms; i++) {
5355 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5357 if (strequal(form_name, list[i].name)) {
5358 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5359 fill_form_1(&form_1, &list[i]);
5365 if (i == numofforms) {
5366 return ERROR_INVALID_HANDLE;
5369 /* check the required size. */
5371 *needed=spoolss_size_form_1(&form_1);
5373 if (!alloc_buffer_size(buffer, buffer_size)){
5374 return ERROR_INSUFFICIENT_BUFFER;
5377 if (*needed > offered) {
5378 return ERROR_INSUFFICIENT_BUFFER;
5381 /* fill the buffer with the form structures */
5382 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5383 smb_io_form_1("", buffer, &form_1, 0);
5385 return NT_STATUS_NO_PROBLEMO;
5389 return ERROR_INVALID_LEVEL;
5393 /****************************************************************************
5394 ****************************************************************************/
5395 static void fill_port_1(PORT_INFO_1 *port, char *name)
5397 init_unistr(&port->port_name, name);
5400 /****************************************************************************
5401 ****************************************************************************/
5402 static void fill_port_2(PORT_INFO_2 *port, char *name)
5404 init_unistr(&port->port_name, name);
5405 init_unistr(&port->monitor_name, "Local Monitor");
5406 init_unistr(&port->description, "Local Port");
5407 #define PORT_TYPE_WRITE 1
5408 port->port_type=PORT_TYPE_WRITE;
5412 /****************************************************************************
5414 ****************************************************************************/
5415 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5417 PORT_INFO_1 *ports=NULL;
5420 if (*lp_enumports_cmd()) {
5421 pid_t local_pid = sys_getpid();
5422 char *cmd = lp_enumports_cmd();
5430 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5431 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5435 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5436 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5439 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5440 ret = smbrun(command, tmp_file, False);
5441 DEBUG(10,("Returned [%d]\n", ret));
5444 /* Is this the best error to return here? */
5445 return ERROR_ACCESS_DENIED;
5449 qlines = file_lines_load(tmp_file, &numlines,True);
5450 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5451 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5455 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5456 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5457 file_lines_free(qlines);
5458 return ERROR_NOT_ENOUGH_MEMORY;
5461 for (i=0; i<numlines; i++) {
5462 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5463 fill_port_1(&ports[i], qlines[i]);
5466 file_lines_free(qlines);
5469 *returned = numlines;
5472 *returned = 1; /* Sole Samba port returned. */
5474 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5475 return ERROR_NOT_ENOUGH_MEMORY;
5477 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5479 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5482 /* check the required size. */
5483 for (i=0; i<*returned; i++) {
5484 DEBUGADD(6,("adding port [%d]'s size\n", i));
5485 *needed += spoolss_size_port_info_1(&ports[i]);
5488 if (!alloc_buffer_size(buffer, *needed)) {
5490 return ERROR_INSUFFICIENT_BUFFER;
5493 /* fill the buffer with the ports structures */
5494 for (i=0; i<*returned; i++) {
5495 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5496 smb_io_port_1("", buffer, &ports[i], 0);
5501 if (*needed > offered) {
5503 return ERROR_INSUFFICIENT_BUFFER;
5506 return NT_STATUS_NO_PROBLEMO;
5509 /****************************************************************************
5511 ****************************************************************************/
5513 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5515 PORT_INFO_2 *ports=NULL;
5518 if (*lp_enumports_cmd()) {
5519 pid_t local_pid = sys_getpid();
5520 char *cmd = lp_enumports_cmd();
5528 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5529 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5533 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5534 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5537 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5538 ret = smbrun(command, tmp_file, False);
5539 DEBUGADD(10,("returned [%d]\n", ret));
5542 /* Is this the best error to return here? */
5543 return ERROR_ACCESS_DENIED;
5547 qlines = file_lines_load(tmp_file, &numlines,True);
5548 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5549 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5553 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5554 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5555 file_lines_free(qlines);
5556 return ERROR_NOT_ENOUGH_MEMORY;
5559 for (i=0; i<numlines; i++) {
5560 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5561 fill_port_2(&(ports[i]), qlines[i]);
5564 file_lines_free(qlines);
5567 *returned = numlines;
5573 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5574 return ERROR_NOT_ENOUGH_MEMORY;
5576 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5578 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5581 /* check the required size. */
5582 for (i=0; i<*returned; i++) {
5583 DEBUGADD(6,("adding port [%d]'s size\n", i));
5584 *needed += spoolss_size_port_info_2(&ports[i]);
5587 if (!alloc_buffer_size(buffer, *needed)) {
5589 return ERROR_INSUFFICIENT_BUFFER;
5592 /* fill the buffer with the ports structures */
5593 for (i=0; i<*returned; i++) {
5594 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5595 smb_io_port_2("", buffer, &ports[i], 0);
5600 if (*needed > offered) {
5602 return ERROR_INSUFFICIENT_BUFFER;
5605 return NT_STATUS_NO_PROBLEMO;
5608 /****************************************************************************
5610 ****************************************************************************/
5612 uint32 _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5614 /* UNISTR2 *name = &q_u->name; - notused. */
5615 uint32 level = q_u->level;
5616 NEW_BUFFER *buffer = NULL;
5617 uint32 offered = q_u->offered;
5618 uint32 *needed = &r_u->needed;
5619 uint32 *returned = &r_u->returned;
5621 /* that's an [in out] buffer */
5622 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5623 buffer = r_u->buffer;
5625 DEBUG(4,("_spoolss_enumports\n"));
5632 return enumports_level_1(buffer, offered, needed, returned);
5634 return enumports_level_2(buffer, offered, needed, returned);
5636 return ERROR_INVALID_LEVEL;
5640 /****************************************************************************
5641 ****************************************************************************/
5642 static uint32 spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5643 const SPOOL_PRINTER_INFO_LEVEL *info,
5644 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5645 uint32 user_switch, const SPOOL_USER_CTR *user,
5648 NT_PRINTER_INFO_LEVEL *printer = NULL;
5652 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5653 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5654 return ERROR_NOT_ENOUGH_MEMORY;
5657 ZERO_STRUCTP(printer);
5659 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5660 convert_printer_info(info, printer, 2);
5662 if (*lp_addprinter_cmd() )
5663 if ( !add_printer_hook(printer) ) {
5664 free_a_printer(&printer,2);
5665 return ERROR_ACCESS_DENIED;
5668 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5669 printer->info_2->sharename);
5671 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5672 free_a_printer(&printer,2);
5673 return ERROR_ACCESS_DENIED;
5676 /* you must be a printer admin to add a new printer */
5677 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5678 free_a_printer(&printer,2);
5679 return ERROR_ACCESS_DENIED;
5683 * Do sanity check on the requested changes for Samba.
5686 if (!check_printer_ok(printer->info_2, snum)) {
5687 free_a_printer(&printer,2);
5688 return ERROR_INVALID_PARAMETER;
5691 /* write the ASCII on disk */
5692 if (add_a_printer(*printer, 2) != 0) {
5693 free_a_printer(&printer,2);
5694 return ERROR_ACCESS_DENIED;
5697 if (!open_printer_hnd(p, handle, name)) {
5698 /* Handle open failed - remove addition. */
5699 del_a_printer(printer->info_2->sharename);
5700 free_a_printer(&printer,2);
5701 return ERROR_ACCESS_DENIED;
5704 free_a_printer(&printer,2);
5706 srv_spoolss_sendnotify(p, handle);
5708 return NT_STATUS_NO_PROBLEMO;
5711 /****************************************************************************
5712 ****************************************************************************/
5714 uint32 _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5716 UNISTR2 *uni_srv_name = &q_u->server_name;
5717 uint32 level = q_u->level;
5718 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5719 uint32 unk0 = q_u->unk0;
5720 uint32 unk1 = q_u->unk1;
5721 uint32 unk2 = q_u->unk2;
5722 uint32 unk3 = q_u->unk3;
5723 uint32 user_switch = q_u->user_switch;
5724 SPOOL_USER_CTR *user = &q_u->user_ctr;
5725 POLICY_HND *handle = &r_u->handle;
5729 /* we don't handle yet */
5730 /* but I know what to do ... */
5731 return ERROR_INVALID_LEVEL;
5733 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5734 unk0, unk1, unk2, unk3,
5735 user_switch, user, handle);
5737 return ERROR_INVALID_LEVEL;
5741 /****************************************************************************
5742 ****************************************************************************/
5744 uint32 _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5746 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5747 uint32 level = q_u->level;
5748 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5750 uint32 err = NT_STATUS_NO_PROBLEMO;
5751 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5752 struct current_user user;
5754 ZERO_STRUCT(driver);
5756 get_current_user(&user, p);
5758 convert_printer_driver_info(info, &driver, level);
5760 DEBUG(5,("Cleaning driver's information\n"));
5761 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5764 DEBUG(5,("Moving driver to final destination\n"));
5765 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5767 err = ERROR_ACCESS_DENIED;
5771 if (add_a_printer_driver(driver, level)!=0) {
5772 err = ERROR_ACCESS_DENIED;
5777 free_a_printer_driver(driver, level);
5781 /****************************************************************************
5782 ****************************************************************************/
5783 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5785 init_unistr(&info->name, name);
5788 /****************************************************************************
5789 ****************************************************************************/
5790 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5794 pstring short_archi;
5795 DRIVER_DIRECTORY_1 *info=NULL;
5797 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5799 if (get_short_archi(short_archi, long_archi)==FALSE)
5800 return ERROR_INVALID_ENVIRONMENT;
5802 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5803 return ERROR_NOT_ENOUGH_MEMORY;
5805 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5807 DEBUG(4,("printer driver directory: [%s]\n", path));
5809 fill_driverdir_1(info, path);
5811 *needed += spoolss_size_driverdir_info_1(info);
5813 if (!alloc_buffer_size(buffer, *needed)) {
5815 return ERROR_INSUFFICIENT_BUFFER;
5818 smb_io_driverdir_1("", buffer, info, 0);
5822 if (*needed > offered)
5823 return ERROR_INSUFFICIENT_BUFFER;
5825 return NT_STATUS_NO_PROBLEMO;
5828 /****************************************************************************
5829 ****************************************************************************/
5831 uint32 _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
5833 UNISTR2 *name = &q_u->name;
5834 UNISTR2 *uni_environment = &q_u->environment;
5835 uint32 level = q_u->level;
5836 NEW_BUFFER *buffer = NULL;
5837 uint32 offered = q_u->offered;
5838 uint32 *needed = &r_u->needed;
5840 /* that's an [in out] buffer */
5841 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5842 buffer = r_u->buffer;
5844 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5850 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5852 return ERROR_INVALID_LEVEL;
5856 /****************************************************************************
5857 ****************************************************************************/
5859 uint32 _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
5861 POLICY_HND *handle = &q_u->handle;
5862 uint32 idx = q_u->index;
5863 uint32 in_value_len = q_u->valuesize;
5864 uint32 in_data_len = q_u->datasize;
5865 uint32 *out_max_value_len = &r_u->valuesize;
5866 uint16 **out_value = &r_u->value;
5867 uint32 *out_value_len = &r_u->realvaluesize;
5868 uint32 *out_type = &r_u->type;
5869 uint32 *out_max_data_len = &r_u->datasize;
5870 uint8 **data_out = &r_u->data;
5871 uint32 *out_data_len = &r_u->realdatasize;
5873 NT_PRINTER_INFO_LEVEL *printer = NULL;
5878 uint32 biggest_valuesize;
5879 uint32 biggest_datasize;
5881 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5886 ZERO_STRUCT(printer);
5888 *out_max_value_len=0;
5894 *out_max_data_len=0;
5898 DEBUG(5,("spoolss_enumprinterdata\n"));
5901 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5902 return ERROR_INVALID_HANDLE;
5905 if (!get_printer_snum(p,handle, &snum))
5906 return ERROR_INVALID_HANDLE;
5908 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5909 return ERROR_INVALID_HANDLE;
5912 * The NT machine wants to know the biggest size of value and data
5914 * cf: MSDN EnumPrinterData remark section
5916 if ( (in_value_len==0) && (in_data_len==0) ) {
5917 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5921 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5922 * if this parameter size doesn't exist.
5923 * Ok - my opinion here is that the client is not asking for the greatest
5924 * possible size of all the parameters, but is asking specifically for the size needed
5925 * for this specific parameter. In that case we can remove the loop below and
5926 * simplify this lookup code considerably. JF - comments welcome. JRA.
5929 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5931 free_a_printer(&printer, 2);
5932 return ERROR_NO_MORE_ITEMS;
5940 biggest_valuesize=0;
5943 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5944 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5945 if (data_len > biggest_datasize) biggest_datasize=data_len;
5947 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5955 * I think this is correct, it doesn't break APW and
5956 * allows Gerald's Win32 test programs to work correctly,
5957 * but may need altering.... JRA.
5960 if (param_index == 0) {
5961 /* No parameters found. */
5962 free_a_printer(&printer, 2);
5963 return ERROR_NO_MORE_ITEMS;
5966 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5967 *out_value_len=2*(1+biggest_valuesize);
5968 *out_data_len=biggest_datasize;
5970 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5972 free_a_printer(&printer, 2);
5973 return NT_STATUS_NO_PROBLEMO;
5977 * the value len is wrong in NT sp3
5978 * that's the number of bytes not the number of unicode chars
5981 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5983 free_a_printer(&printer, 2);
5984 return ERROR_NO_MORE_ITEMS;
5987 free_a_printer(&printer, 2);
5991 * - counted in bytes in the request
5992 * - counted in UNICODE chars in the max reply
5993 * - counted in bytes in the real size
5995 * take a pause *before* coding not *during* coding
5998 *out_max_value_len=(in_value_len/sizeof(uint16));
5999 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6001 return ERROR_NOT_ENOUGH_MEMORY;
6004 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
6008 /* the data is counted in bytes */
6009 *out_max_data_len=in_data_len;
6010 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6012 return ERROR_NOT_ENOUGH_MEMORY;
6015 memcpy(*data_out, data, (size_t)data_len);
6016 *out_data_len=data_len;
6020 return NT_STATUS_NO_PROBLEMO;
6023 /****************************************************************************
6024 ****************************************************************************/
6026 uint32 _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6028 POLICY_HND *handle = &q_u->handle;
6029 UNISTR2 *value = &q_u->value;
6030 uint32 type = q_u->type;
6031 /* uint32 max_len = q_u->max_len; - notused. */
6032 uint8 *data = q_u->data;
6033 uint32 real_len = q_u->real_len;
6034 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6036 NT_PRINTER_INFO_LEVEL *printer = NULL;
6037 NT_PRINTER_PARAM *param = NULL, old_param;
6039 uint32 status = 0x0;
6040 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6042 DEBUG(5,("spoolss_setprinterdata\n"));
6045 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6046 return ERROR_INVALID_HANDLE;
6049 if (!get_printer_snum(p,handle, &snum))
6050 return ERROR_INVALID_HANDLE;
6052 status = get_a_printer(&printer, 2, lp_servicename(snum));
6054 return ERROR_INVALID_NAME;
6056 convert_specific_param(¶m, value , type, data, real_len);
6058 /* Check if we are making any changes or not. Return true if
6059 nothing is actually changing. */
6061 ZERO_STRUCT(old_param);
6063 if (get_specific_param(*printer, 2, param->value, &old_param.data,
6064 &old_param.type, (unsigned int *)&old_param.data_len)) {
6066 if (param->type == old_param.type &&
6067 param->data_len == old_param.data_len &&
6068 memcmp(param->data, old_param.data,
6069 old_param.data_len) == 0) {
6071 DEBUG(3, ("setprinterdata hasn't changed\n"));
6072 status = NT_STATUS_NO_PROBLEMO;
6079 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6080 DEBUG(3, ("security descriptor change denied by existing "
6081 "security descriptor\n"));
6082 status = ERROR_ACCESS_DENIED;
6086 unlink_specific_param_if_exist(printer->info_2, param);
6088 add_a_specific_param(printer->info_2, ¶m);
6089 status = mod_a_printer(*printer, 2);
6092 free_a_printer(&printer, 2);
6094 free_nt_printer_param(¶m);
6095 safe_free(old_param.data);
6100 /****************************************************************************
6101 ****************************************************************************/
6103 uint32 _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6105 POLICY_HND *handle = &q_u->handle;
6106 UNISTR2 *value = &q_u->valuename;
6108 NT_PRINTER_INFO_LEVEL *printer = NULL;
6109 NT_PRINTER_PARAM param;
6111 uint32 status = 0x0;
6112 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6114 DEBUG(5,("spoolss_deleteprinterdata\n"));
6117 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6118 return ERROR_INVALID_HANDLE;
6121 if (!get_printer_snum(p, handle, &snum))
6122 return ERROR_INVALID_HANDLE;
6124 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6125 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6126 "change denied by existing security descriptor\n"));
6127 return ERROR_ACCESS_DENIED;
6130 status = get_a_printer(&printer, 2, lp_servicename(snum));
6132 return ERROR_INVALID_NAME;
6134 ZERO_STRUCTP(¶m);
6135 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6137 if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
6138 status = ERROR_INVALID_PARAMETER;
6140 status = mod_a_printer(*printer, 2);
6142 free_a_printer(&printer, 2);
6146 /****************************************************************************
6147 ****************************************************************************/
6149 uint32 _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6151 POLICY_HND *handle = &q_u->handle;
6152 /* uint32 level = q_u->level; - notused. */
6153 FORM *form = &q_u->form;
6154 nt_forms_struct tmpForm;
6157 nt_forms_struct *list=NULL;
6158 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6160 DEBUG(5,("spoolss_addform\n"));
6163 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6164 return ERROR_INVALID_HANDLE;
6167 /* can't add if builtin */
6168 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6169 return ERROR_INVALID_PARAMETER;
6172 count=get_ntforms(&list);
6173 if(!add_a_form(&list, form, &count))
6174 return ERROR_NOT_ENOUGH_MEMORY;
6175 write_ntforms(&list, count);
6182 /****************************************************************************
6183 ****************************************************************************/
6185 uint32 _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6187 POLICY_HND *handle = &q_u->handle;
6188 UNISTR2 *form_name = &q_u->name;
6189 nt_forms_struct tmpForm;
6192 nt_forms_struct *list=NULL;
6193 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6195 DEBUG(5,("spoolss_deleteform\n"));
6198 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6199 return ERROR_INVALID_HANDLE;
6202 /* can't delete if builtin */
6203 if (get_a_builtin_ntform(form_name,&tmpForm)) {
6204 return ERROR_INVALID_PARAMETER;
6207 count = get_ntforms(&list);
6208 if(!delete_a_form(&list, form_name, &count, &ret))
6209 return ERROR_INVALID_PARAMETER;
6216 /****************************************************************************
6217 ****************************************************************************/
6219 uint32 _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6221 POLICY_HND *handle = &q_u->handle;
6222 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6223 /* uint32 level = q_u->level; - notused. */
6224 FORM *form = &q_u->form;
6225 nt_forms_struct tmpForm;
6228 nt_forms_struct *list=NULL;
6229 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6231 DEBUG(5,("spoolss_setform\n"));
6234 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6235 return ERROR_INVALID_HANDLE;
6237 /* can't set if builtin */
6238 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6239 return ERROR_INVALID_PARAMETER;
6242 count=get_ntforms(&list);
6243 update_a_form(&list, form, count);
6244 write_ntforms(&list, count);
6251 /****************************************************************************
6252 enumprintprocessors level 1.
6253 ****************************************************************************/
6254 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6256 PRINTPROCESSOR_1 *info_1=NULL;
6258 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6259 return ERROR_NOT_ENOUGH_MEMORY;
6263 init_unistr(&info_1->name, "winprint");
6265 *needed += spoolss_size_printprocessor_info_1(info_1);
6267 if (!alloc_buffer_size(buffer, *needed))
6268 return ERROR_INSUFFICIENT_BUFFER;
6270 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6274 if (*needed > offered) {
6276 return ERROR_INSUFFICIENT_BUFFER;
6279 return NT_STATUS_NO_PROBLEMO;
6282 /****************************************************************************
6283 ****************************************************************************/
6285 uint32 _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6287 /* UNISTR2 *name = &q_u->name; - notused. */
6288 /* UNISTR2 *environment = &q_u->environment; - notused. */
6289 uint32 level = q_u->level;
6290 NEW_BUFFER *buffer = NULL;
6291 uint32 offered = q_u->offered;
6292 uint32 *needed = &r_u->needed;
6293 uint32 *returned = &r_u->returned;
6295 /* that's an [in out] buffer */
6296 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6297 buffer = r_u->buffer;
6299 DEBUG(5,("spoolss_enumprintprocessors\n"));
6302 * Enumerate the print processors ...
6304 * Just reply with "winprint", to keep NT happy
6305 * and I can use my nice printer checker.
6313 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6315 return ERROR_INVALID_LEVEL;
6319 /****************************************************************************
6320 enumprintprocdatatypes level 1.
6321 ****************************************************************************/
6322 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6324 PRINTPROCDATATYPE_1 *info_1=NULL;
6326 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6327 return ERROR_NOT_ENOUGH_MEMORY;
6331 init_unistr(&info_1->name, "RAW");
6333 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6335 if (!alloc_buffer_size(buffer, *needed))
6336 return ERROR_INSUFFICIENT_BUFFER;
6338 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6342 if (*needed > offered) {
6344 return ERROR_INSUFFICIENT_BUFFER;
6347 return NT_STATUS_NO_PROBLEMO;
6350 /****************************************************************************
6351 ****************************************************************************/
6353 uint32 _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6355 /* UNISTR2 *name = &q_u->name; - notused. */
6356 /* UNISTR2 *processor = &q_u->processor; - notused. */
6357 uint32 level = q_u->level;
6358 NEW_BUFFER *buffer = NULL;
6359 uint32 offered = q_u->offered;
6360 uint32 *needed = &r_u->needed;
6361 uint32 *returned = &r_u->returned;
6363 /* that's an [in out] buffer */
6364 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6365 buffer = r_u->buffer;
6367 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6374 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6376 return ERROR_INVALID_LEVEL;
6380 /****************************************************************************
6381 enumprintmonitors level 1.
6382 ****************************************************************************/
6384 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6386 PRINTMONITOR_1 *info_1=NULL;
6388 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6389 return ERROR_NOT_ENOUGH_MEMORY;
6393 init_unistr(&info_1->name, "Local Port");
6395 *needed += spoolss_size_printmonitor_info_1(info_1);
6397 if (!alloc_buffer_size(buffer, *needed))
6398 return ERROR_INSUFFICIENT_BUFFER;
6400 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6404 if (*needed > offered) {
6406 return ERROR_INSUFFICIENT_BUFFER;
6409 return NT_STATUS_NO_PROBLEMO;
6412 /****************************************************************************
6413 enumprintmonitors level 2.
6414 ****************************************************************************/
6415 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6417 PRINTMONITOR_2 *info_2=NULL;
6419 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6420 return ERROR_NOT_ENOUGH_MEMORY;
6424 init_unistr(&info_2->name, "Local Port");
6425 init_unistr(&info_2->environment, "Windows NT X86");
6426 init_unistr(&info_2->dll_name, "localmon.dll");
6428 *needed += spoolss_size_printmonitor_info_2(info_2);
6430 if (!alloc_buffer_size(buffer, *needed))
6431 return ERROR_INSUFFICIENT_BUFFER;
6433 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6437 if (*needed > offered) {
6439 return ERROR_INSUFFICIENT_BUFFER;
6442 return NT_STATUS_NO_PROBLEMO;
6445 /****************************************************************************
6446 ****************************************************************************/
6448 uint32 _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6450 /* UNISTR2 *name = &q_u->name; - notused. */
6451 uint32 level = q_u->level;
6452 NEW_BUFFER *buffer = NULL;
6453 uint32 offered = q_u->offered;
6454 uint32 *needed = &r_u->needed;
6455 uint32 *returned = &r_u->returned;
6457 /* that's an [in out] buffer */
6458 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6459 buffer = r_u->buffer;
6461 DEBUG(5,("spoolss_enumprintmonitors\n"));
6464 * Enumerate the print monitors ...
6466 * Just reply with "Local Port", to keep NT happy
6467 * and I can use my nice printer checker.
6475 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6477 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6479 return ERROR_INVALID_LEVEL;
6483 /****************************************************************************
6484 ****************************************************************************/
6485 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6489 JOB_INFO_1 *info_1=NULL;
6491 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6493 if (info_1 == NULL) {
6495 return ERROR_NOT_ENOUGH_MEMORY;
6498 for (i=0; i<count && found==False; i++) {
6499 if (queue[i].job==(int)jobid)
6506 /* I shoud reply something else ... I can't find the good one */
6507 return NT_STATUS_NO_PROBLEMO;
6510 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6514 *needed += spoolss_size_job_info_1(info_1);
6516 if (!alloc_buffer_size(buffer, *needed)) {
6518 return ERROR_INSUFFICIENT_BUFFER;
6521 smb_io_job_info_1("", buffer, info_1, 0);
6525 if (*needed > offered)
6526 return ERROR_INSUFFICIENT_BUFFER;
6528 return NT_STATUS_NO_PROBLEMO;
6532 /****************************************************************************
6533 ****************************************************************************/
6534 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6539 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6541 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6543 ZERO_STRUCTP(info_2);
6545 if (info_2 == NULL) {
6547 return ERROR_NOT_ENOUGH_MEMORY;
6550 for (i=0; i<count && found==False; i++) {
6551 if (queue[i].job==(int)jobid)
6558 /* I shoud reply something else ... I can't find the good one */
6559 return NT_STATUS_NO_PROBLEMO;
6562 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6564 return ERROR_NOT_ENOUGH_MEMORY;
6567 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6569 free_a_printer(&ntprinter, 2);
6572 *needed += spoolss_size_job_info_2(info_2);
6574 if (!alloc_buffer_size(buffer, *needed)) {
6576 return ERROR_INSUFFICIENT_BUFFER;
6579 smb_io_job_info_2("", buffer, info_2, 0);
6581 free_job_info_2(info_2);
6584 if (*needed > offered)
6585 return ERROR_INSUFFICIENT_BUFFER;
6587 return NT_STATUS_NO_PROBLEMO;
6590 /****************************************************************************
6591 ****************************************************************************/
6593 uint32 _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6595 POLICY_HND *handle = &q_u->handle;
6596 uint32 jobid = q_u->jobid;
6597 uint32 level = q_u->level;
6598 NEW_BUFFER *buffer = NULL;
6599 uint32 offered = q_u->offered;
6600 uint32 *needed = &r_u->needed;
6604 print_queue_struct *queue=NULL;
6605 print_status_struct prt_status;
6607 /* that's an [in out] buffer */
6608 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6609 buffer = r_u->buffer;
6611 DEBUG(5,("spoolss_getjob\n"));
6613 memset(&prt_status, 0, sizeof(prt_status));
6617 if (!get_printer_snum(p, handle, &snum))
6618 return ERROR_INVALID_HANDLE;
6620 count = print_queue_status(snum, &queue, &prt_status);
6622 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6623 count, prt_status.status, prt_status.message));
6627 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6629 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6632 return ERROR_INVALID_LEVEL;