SGI compiler fixes.
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob3fcb08891df757b3cf3dd0fb9093443f63090934
1 /*
2 * Unix SMB/Netbios implementation.
3 * Version 1.9.
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.
25 #include "includes.h"
27 extern int DEBUGLEVEL;
28 extern pstring global_myname;
30 #ifndef MAX_OPEN_PRINTER_EXS
31 #define MAX_OPEN_PRINTER_EXS 50
32 #endif
34 #define PRINTER_HANDLE_IS_PRINTER 0
35 #define PRINTER_HANDLE_IS_PRINTSERVER 1
37 struct table_node {
38 char *long_archi;
39 char *short_archi;
40 int version;
44 /* structure to store the printer handles */
45 /* and a reference to what it's pointing to */
46 /* and the notify info asked about */
47 /* that's the central struct */
48 typedef struct _Printer{
49 BOOL document_started;
50 BOOL page_started;
51 int jobid; /* jobid in printing backend */
52 BOOL printer_type;
53 union {
54 fstring handlename;
55 fstring printerservername;
56 } dev;
57 uint32 type;
58 uint32 access;
59 struct {
60 uint32 flags;
61 uint32 options;
62 fstring localmachine;
63 uint32 printerlocal;
64 SPOOL_NOTIFY_OPTION *option;
65 POLICY_HND client_hnd;
66 uint32 client_connected;
67 } notify;
68 struct {
69 fstring machine;
70 fstring user;
71 } client;
72 } Printer_entry;
74 typedef struct _counter_printer_0 {
75 ubi_dlNode Next;
76 ubi_dlNode Prev;
78 int snum;
79 uint32 counter;
80 } counter_printer_0;
82 static ubi_dlList counter_list;
84 static struct cli_state cli;
85 static uint32 smb_connections=0;
87 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
92 switch (v) {
93 case LPQ_QUEUED:
94 return 0;
95 case LPQ_PAUSED:
96 return JOB_STATUS_PAUSED;
97 case LPQ_SPOOLING:
98 return JOB_STATUS_SPOOLING;
99 case LPQ_PRINTING:
100 return JOB_STATUS_PRINTING;
101 case LPQ_ERROR:
102 return JOB_STATUS_ERROR;
103 case LPQ_DELETING:
104 return JOB_STATUS_DELETING;
105 case LPQ_OFFLINE:
106 return JOB_STATUS_OFFLINE;
107 case LPQ_PAPEROUT:
108 return JOB_STATUS_PAPEROUT;
109 case LPQ_PRINTED:
110 return JOB_STATUS_PRINTED;
111 case LPQ_DELETED:
112 return JOB_STATUS_DELETED;
113 case LPQ_BLOCKED:
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
118 return 0;
121 static int nt_printq_status(int v)
123 switch (v) {
124 case LPQ_PAUSED:
125 return PRINTER_STATUS_PAUSED;
126 case LPQ_QUEUED:
127 case LPQ_SPOOLING:
128 case LPQ_PRINTING:
129 return 0;
131 return 0;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
140 SPOOL_NOTIFY_OPTION *sp = *pp;
142 *pp = NULL;
144 if (!sp)
145 return;
147 if (sp->ctr.type)
148 safe_free(sp->ctr.type);
150 free(sp);
153 /***************************************************************************
154 Disconnect from the client
155 ****************************************************************************/
157 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
159 uint32 status;
161 /* weird if the test succeds !!! */
162 if (smb_connections==0) {
163 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
164 return;
167 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
168 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
170 /* if it's the last connection, deconnect the IPC$ share */
171 if (smb_connections==1) {
172 if(!spoolss_disconnect_from_client(&cli))
173 return;
175 message_deregister(MSG_PRINTER_NOTIFY);
178 smb_connections--;
181 /****************************************************************************
182 Functions to free a printer entry datastruct.
183 ****************************************************************************/
185 static void free_printer_entry(void *ptr)
187 Printer_entry *Printer = (Printer_entry *)ptr;
189 if (Printer->notify.client_connected==True)
190 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
192 Printer->notify.flags=0;
193 Printer->notify.options=0;
194 Printer->notify.localmachine[0]='\0';
195 Printer->notify.printerlocal=0;
196 free_spool_notify_option(&Printer->notify.option);
197 Printer->notify.option=NULL;
198 Printer->notify.client_connected=False;
200 safe_free(Printer);
203 /****************************************************************************
204 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
205 ****************************************************************************/
207 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
209 SPOOL_NOTIFY_OPTION *new_sp = NULL;
211 if (!sp)
212 return NULL;
214 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
215 if (!new_sp)
216 return NULL;
218 *new_sp = *sp;
220 if (sp->ctr.count) {
221 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
223 if (!new_sp->ctr.type) {
224 safe_free(new_sp);
225 return NULL;
229 return new_sp;
232 /****************************************************************************
233 find printer index by handle
234 ****************************************************************************/
236 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
238 Printer_entry *find_printer = NULL;
240 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
241 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
242 return NULL;
245 return find_printer;
248 /****************************************************************************
249 close printer index by handle
250 ****************************************************************************/
252 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
254 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
256 if (!Printer) {
257 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
258 return False;
261 close_policy_hnd(p, hnd);
263 return True;
266 /****************************************************************************
267 delete a printer given a handle
268 ****************************************************************************/
269 static uint32 delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
271 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
273 if (!Printer) {
274 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
275 return ERROR_INVALID_HANDLE;
278 if (del_a_printer(Printer->dev.handlename) != 0) {
279 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
280 return ERROR_INVALID_HANDLE;
283 /* Check calling user has permission to delete printer. Note that
284 since we set the snum parameter to -1 only administrators can
285 delete the printer. This stops people with the Full Control
286 permission from deleting the printer. */
288 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
289 DEBUG(3, ("printer delete denied by security descriptor\n"));
290 return ERROR_ACCESS_DENIED;
293 if (*lp_deleteprinter_cmd()) {
295 char *cmd = lp_deleteprinter_cmd();
296 pstring command;
297 int ret;
298 int i;
300 /* Printer->dev.handlename equals portname equals sharename */
301 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
302 Printer->dev.handlename);
303 dos_to_unix(command, True); /* Convert printername to unix-codepage */
305 DEBUG(10,("Running [%s]\n", command));
306 ret = smbrun(command, NULL);
307 if (ret != 0) {
308 return ERROR_INVALID_HANDLE; /* What to return here? */
310 DEBUGADD(10,("returned [%d]\n", ret));
312 /* Send SIGHUP to process group... is there a better way? */
313 kill(0, SIGHUP);
315 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
316 lp_killservice( i );
317 return ERROR_SUCCESS;
318 } else
319 return ERROR_ACCESS_DENIED;
322 return ERROR_SUCCESS;
325 /****************************************************************************
326 return the snum of a printer corresponding to an handle
327 ****************************************************************************/
328 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
330 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
332 if (!Printer) {
333 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
334 return False;
337 switch (Printer->printer_type) {
338 case PRINTER_HANDLE_IS_PRINTER:
339 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
340 *number = print_queue_snum(Printer->dev.handlename);
341 return (*number != -1);
342 case PRINTER_HANDLE_IS_PRINTSERVER:
343 return False;
344 default:
345 return False;
349 /****************************************************************************
350 set printer handle type.
351 ****************************************************************************/
352 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
354 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
356 if (!Printer) {
357 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
358 return False;
361 DEBUG(4,("Setting printer access=%x\n", access_required));
362 Printer->access = access_required;
363 return True;
366 /****************************************************************************
367 Set printer handle type.
368 Check if it's \\server or \\server\printer
369 ****************************************************************************/
371 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
373 DEBUG(3,("Setting printer type=%s\n", handlename));
375 if ( strlen(handlename) < 3 ) {
376 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
377 return False;
380 /* it's a print server */
381 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr(handlename+2, '\\')) {
382 DEBUGADD(4,("Printer is a print server\n"));
383 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
385 /* it's a printer */
386 else {
387 DEBUGADD(4,("Printer is a printer\n"));
388 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
391 return True;
394 /****************************************************************************
395 Set printer handle name.
396 ****************************************************************************/
398 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
400 NT_PRINTER_INFO_LEVEL *printer = NULL;
401 int snum;
402 int n_services=lp_numservices();
403 char *aprinter;
404 BOOL found=False;
406 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
408 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
409 ZERO_STRUCT(Printer->dev.printerservername);
410 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
411 return True;
414 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
415 return False;
417 if (*handlename=='\\') {
418 aprinter=strchr(handlename+2, '\\');
419 aprinter++;
421 else {
422 aprinter=handlename;
425 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
428 * store the Samba share name in it
429 * in back we have the long printer name
430 * need to iterate all the snum and do a
431 * get_a_printer each time to find the printer
432 * faster to do it here than later.
435 for (snum=0;snum<n_services && found==False;snum++) {
436 char *printername;
438 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
439 continue;
441 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
443 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
444 continue;
446 printername=strchr(printer->info_2->printername+2, '\\');
447 printername++;
449 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
450 printer->info_2->printername, aprinter ));
452 if ( strlen(printername) != strlen(aprinter) ) {
453 free_a_printer(&printer, 2);
454 continue;
457 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
458 free_a_printer(&printer, 2);
459 continue;
462 found=True;
466 * if we haven't found a printer with the given handlename
467 * then it can be a share name as you can open both \\server\printer and
468 * \\server\share
472 * we still check if the printer description file exists as NT won't be happy
473 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
476 if (found==False) {
477 DEBUGADD(5,("Printer not found, checking for share now\n"));
479 for (snum=0;snum<n_services && found==False;snum++) {
481 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
482 continue;
484 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
486 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
487 continue;
489 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
490 printer->info_2->printername, aprinter ));
492 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
493 free_a_printer(&printer, 2);
494 continue;
497 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
498 free_a_printer(&printer, 2);
499 continue;
502 found=True;
506 if (found==False) {
507 DEBUGADD(4,("Printer not found\n"));
508 return False;
511 snum--;
512 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
513 printer->info_2->printername, lp_servicename(snum),snum));
515 ZERO_STRUCT(Printer->dev.handlename);
516 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
518 free_a_printer(&printer, 2);
520 return True;
523 /****************************************************************************
524 find first available printer slot. creates a printer handle for you.
525 ****************************************************************************/
527 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
529 Printer_entry *new_printer;
531 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
533 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
534 return False;
536 ZERO_STRUCTP(new_printer);
538 new_printer->notify.option=NULL;
540 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
541 safe_free(new_printer);
542 return False;
545 if (!set_printer_hnd_printertype(new_printer, name)) {
546 close_printer_handle(p, hnd);
547 return False;
550 if (!set_printer_hnd_name(new_printer, name)) {
551 close_printer_handle(p, hnd);
552 return False;
555 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
557 return True;
560 /********************************************************************
561 Return True is the handle is a print server.
562 ********************************************************************/
564 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
566 Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
568 if (!Printer)
569 return False;
571 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
572 return False;
574 return True;
577 /****************************************************************************
578 allocate more memory for a BUFFER.
579 ****************************************************************************/
580 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
582 prs_struct *ps;
583 uint32 extra_space;
584 uint32 old_offset;
586 ps= &buffer->prs;
588 /* damn, I'm doing the reverse operation of prs_grow() :) */
589 if (buffer_size < prs_data_size(ps))
590 extra_space=0;
591 else
592 extra_space = buffer_size - prs_data_size(ps);
595 * save the offset and move to the end of the buffer
596 * prs_grow() checks the extra_space against the offset
598 old_offset=prs_offset(ps);
599 prs_set_offset(ps, prs_data_size(ps));
601 if (!prs_grow(ps, extra_space))
602 return False;
604 prs_set_offset(ps, old_offset);
606 buffer->string_at_end=prs_data_size(ps);
608 return True;
611 /***************************************************************************
612 receive the notify message
613 ****************************************************************************/
615 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
617 fstring printer;
618 uint32 status;
619 struct pipes_struct *p;
620 struct policy *pol;
621 struct handle_list *hl;
623 *printer = '\0';
624 fstrcpy(printer,buf);
626 if (len == 0) {
627 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
628 return;
631 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
634 * We need to enumerate all printers. The handle list is shared
635 * across pipes of the same name, so just find the first open
636 * spoolss pipe.
639 hl = NULL;
640 for ( p = get_first_pipe(); p; get_next_pipe(p)) {
641 if (strequal(p->name, "spoolss")) {
642 hl = p->pipe_handles;
643 break;
647 if (!hl) {
648 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
649 return;
652 /* Iterate the printer list on this pipe. */
653 for (pol = hl->Policy; pol; pol = pol->next ) {
654 Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
656 if (!find_printer)
657 continue;
660 * if the entry is the given printer or if it's a printerserver
661 * we send the message
664 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
665 if (strcmp(find_printer->dev.handlename, printer))
666 continue;
668 if (find_printer->notify.client_connected==True)
669 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
673 /***************************************************************************
674 send a notify event
675 ****************************************************************************/
676 static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle)
678 fstring printer;
680 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
682 if (!Printer) {
683 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
684 return False;
687 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
688 fstrcpy(printer, Printer->dev.handlename);
689 else
690 fstrcpy(printer, "");
692 /*srv_spoolss_receive_message(printer);*/
693 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
695 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
697 return True;
700 /********************************************************************
701 * spoolss_open_printer
703 * called from the spoolss dispatcher
704 ********************************************************************/
706 uint32 _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
708 #if 0
709 uint32 result = NT_STATUS_NO_PROBLEMO;
710 #endif
712 UNISTR2 *printername = NULL;
713 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
714 /* uint32 user_switch = q_u->user_switch; - notused */
715 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
716 POLICY_HND *handle = &r_u->handle;
718 fstring name;
719 int snum;
720 struct current_user user;
722 if (q_u->printername_ptr != 0)
723 printername = &q_u->printername;
725 if (printername == NULL)
726 return ERROR_INVALID_PRINTER_NAME;
728 /* some sanity check because you can open a printer or a print server */
729 /* aka: \\server\printer or \\server */
730 unistr2_to_ascii(name, printername, sizeof(name)-1);
732 DEBUGADD(3,("checking name: %s\n",name));
734 if (!open_printer_hnd(p, handle, name))
735 return ERROR_INVALID_PRINTER_NAME;
738 if (printer_default->datatype_ptr != NULL)
740 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
741 set_printer_hnd_datatype(handle, datatype);
743 else
744 set_printer_hnd_datatype(handle, "");
747 if (!set_printer_hnd_accesstype(p, handle, printer_default->access_required)) {
748 close_printer_handle(p, handle);
749 return ERROR_ACCESS_DENIED;
753 First case: the user is opening the print server:
755 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
756 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
758 Then both Win2k and WinNT clients try an OpenPrinterEx with
759 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
760 or if the user is listed in the smb.conf printer admin parameter.
762 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
763 client view printer folder, but does not show the MSAPW.
765 Note: this test needs code to check access rights here too. Jeremy
766 could you look at this?
769 Second case: the user is opening a printer:
770 NT doesn't let us connect to a printer if the connecting user
771 doesn't have print permission.
775 get_current_user(&user, p);
777 if (handle_is_printserver(p, handle)) {
778 if (printer_default->access_required == 0) {
779 return NT_STATUS_NO_PROBLEMO;
781 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
783 /* Printserver handles use global struct... */
784 snum = -1;
786 if (!lp_ms_add_printer_wizard()) {
787 close_printer_handle(p, handle);
788 return ERROR_ACCESS_DENIED;
790 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
791 return NT_STATUS_NO_PROBLEMO;
793 else {
794 close_printer_handle(p, handle);
795 return ERROR_ACCESS_DENIED;
799 else
801 /* NT doesn't let us connect to a printer if the connecting user
802 doesn't have print permission. */
804 if (!get_printer_snum(p, handle, &snum))
805 return ERROR_INVALID_HANDLE;
807 /* map an empty access mask to the minimum access mask */
808 if (printer_default->access_required == 0x0)
809 printer_default->access_required = PRINTER_ACCESS_USE;
811 if (!print_access_check(&user, snum, printer_default->access_required)) {
812 DEBUG(3, ("access DENIED for printer open\n"));
813 close_printer_handle(p, handle);
814 return ERROR_ACCESS_DENIED;
818 * If we have a default device pointer in the
819 * printer_default struct, then we need to get
820 * the printer info from the tdb and if there is
821 * no default devicemode there then we do a *SET*
822 * here ! This is insanity.... JRA.
826 * If the openprinterex rpc call contains a devmode,
827 * it's a per-user one. This per-user devmode is derivated
828 * from the global devmode. Openprinterex() contains a per-user
829 * devmode for when you do EMF printing and spooling.
830 * In the EMF case, the NT workstation is only doing half the job
831 * of rendering the page. The other half is done by running the printer
832 * driver on the server.
833 * The EMF file doesn't contain the page description (paper size, orientation, ...).
834 * The EMF file only contains what is to be printed on the page.
835 * So in order for the server to know how to print, the NT client sends
836 * a devicemode attached to the openprinterex call.
837 * But this devicemode is short lived, it's only valid for the current print job.
839 * If Samba would have supported EMF spooling, this devicemode would
840 * have been attached to the handle, to sent it to the driver to correctly
841 * rasterize the EMF file.
843 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
844 * we just act as a pass-thru between windows and the printer.
846 * In order to know that Samba supports only RAW spooling, NT has to call
847 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
848 * and until NT sends a RAW job, we refuse it.
850 * But to call getprinter() or startdoc(), you first need a valid handle,
851 * and to get an handle you have to call openprintex(). Hence why you have
852 * a devicemode in the openprinterex() call.
855 * Differences between NT4 and NT 2000.
856 * NT4:
857 * ---
858 * On NT4, you only have a global devicemode. This global devicemode can be changed
859 * by the administrator (or by a user with enough privs). Everytime a user
860 * wants to print, the devicemode is resetted to the default. In Word, everytime
861 * you print, the printer's characteristics are always reset to the global devicemode.
863 * NT 2000:
864 * -------
865 * In W2K, there is the notion of per-user devicemode. The first time you use
866 * a printer, a per-user devicemode is build from the global devicemode.
867 * If you change your per-user devicemode, it is saved in the registry, under the
868 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
869 * printer preferences available.
871 * To change the per-user devicemode: it's the "Printing Preferences ..." button
872 * on the General Tab of the printer properties windows.
874 * To change the global devicemode: it's the "Printing Defaults..." button
875 * on the Advanced Tab of the printer properties window.
877 * JFM.
882 #if 0
883 if (printer_default->devmode_cont.devmode != NULL) {
884 result = printer_write_default_dev( snum, printer_default);
885 if (result != 0) {
886 close_printer_handle(p, handle);
887 return result;
890 #endif
893 return NT_STATUS_NO_PROBLEMO;
896 /****************************************************************************
897 ****************************************************************************/
898 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
899 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
901 switch (level) {
902 case 2:
903 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
904 break;
905 default:
906 break;
909 return True;
912 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
913 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
915 switch (level) {
916 case 3:
917 printer->info_3=NULL;
918 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
919 break;
920 case 6:
921 printer->info_6=NULL;
922 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
923 break;
924 default:
925 break;
928 return True;
931 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
932 NT_DEVICEMODE **pp_nt_devmode)
934 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
937 * Ensure nt_devmode is a valid pointer
938 * as we will be overwriting it.
941 if (nt_devmode == NULL) {
942 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
943 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
944 return False;
947 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
948 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
950 nt_devmode->specversion=devmode->specversion;
951 nt_devmode->driverversion=devmode->driverversion;
952 nt_devmode->size=devmode->size;
953 nt_devmode->fields=devmode->fields;
954 nt_devmode->orientation=devmode->orientation;
955 nt_devmode->papersize=devmode->papersize;
956 nt_devmode->paperlength=devmode->paperlength;
957 nt_devmode->paperwidth=devmode->paperwidth;
958 nt_devmode->scale=devmode->scale;
959 nt_devmode->copies=devmode->copies;
960 nt_devmode->defaultsource=devmode->defaultsource;
961 nt_devmode->printquality=devmode->printquality;
962 nt_devmode->color=devmode->color;
963 nt_devmode->duplex=devmode->duplex;
964 nt_devmode->yresolution=devmode->yresolution;
965 nt_devmode->ttoption=devmode->ttoption;
966 nt_devmode->collate=devmode->collate;
968 nt_devmode->logpixels=devmode->logpixels;
969 nt_devmode->bitsperpel=devmode->bitsperpel;
970 nt_devmode->pelswidth=devmode->pelswidth;
971 nt_devmode->pelsheight=devmode->pelsheight;
972 nt_devmode->displayflags=devmode->displayflags;
973 nt_devmode->displayfrequency=devmode->displayfrequency;
974 nt_devmode->icmmethod=devmode->icmmethod;
975 nt_devmode->icmintent=devmode->icmintent;
976 nt_devmode->mediatype=devmode->mediatype;
977 nt_devmode->dithertype=devmode->dithertype;
978 nt_devmode->reserved1=devmode->reserved1;
979 nt_devmode->reserved2=devmode->reserved2;
980 nt_devmode->panningwidth=devmode->panningwidth;
981 nt_devmode->panningheight=devmode->panningheight;
984 * Only change private and driverextra if the incoming devmode
985 * has a new one. JRA.
988 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
989 safe_free(nt_devmode->private);
990 nt_devmode->driverextra=devmode->driverextra;
991 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
992 return False;
993 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
996 *pp_nt_devmode = nt_devmode;
998 return True;
1001 /********************************************************************
1002 * _spoolss_enddocprinter_internal.
1003 ********************************************************************/
1005 static uint32 _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1007 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1009 if (!Printer) {
1010 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1011 return ERROR_INVALID_HANDLE;
1014 Printer->document_started=False;
1015 print_job_end(Printer->jobid,True);
1016 /* error codes unhandled so far ... */
1018 return 0x0;
1021 /********************************************************************
1022 * api_spoolss_closeprinter
1023 ********************************************************************/
1025 uint32 _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1027 POLICY_HND *handle = &q_u->handle;
1029 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1031 if (Printer && Printer->document_started)
1032 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1034 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1036 if (!close_printer_handle(p, handle))
1037 return ERROR_INVALID_HANDLE;
1039 return NT_STATUS_NO_PROBLEMO;
1042 /********************************************************************
1043 * api_spoolss_deleteprinter
1045 ********************************************************************/
1047 uint32 _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1049 POLICY_HND *handle = &q_u->handle;
1051 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1052 uint32 result;
1054 if (Printer && Printer->document_started)
1055 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1057 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1059 result = delete_printer_handle(p, handle);
1061 if (result == ERROR_SUCCESS) {
1062 srv_spoolss_sendnotify(p, handle);
1065 return result;
1068 /*******************************************************************
1069 * static function to lookup the version id corresponding to an
1070 * long architecture string
1071 ******************************************************************/
1072 static int get_version_id (char * arch)
1074 int i;
1075 struct table_node archi_table[]= {
1077 {"Windows 4.0", "WIN40", 0 },
1078 {"Windows NT x86", "W32X86", 2 },
1079 {"Windows NT R4000", "W32MIPS", 2 },
1080 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1081 {"Windows NT PowerPC", "W32PPC", 2 },
1082 {NULL, "", -1 }
1085 for (i=0; archi_table[i].long_archi != NULL; i++)
1087 if (strcmp(arch, archi_table[i].long_archi) == 0)
1088 return (archi_table[i].version);
1091 return -1;
1094 /********************************************************************
1095 * _spoolss_deleteprinterdriver
1097 * We currently delete the driver for the architecture only.
1098 * This can leave the driver for other archtectures. However,
1099 * since every printer associates a "Windows NT x86" driver name
1100 * and we cannot delete that one while it is in use, **and** since
1101 * it is impossible to assign a driver to a Samba printer without
1102 * having the "Windows NT x86" driver installed,...
1104 * ....we should not get into trouble here.
1106 * --jerry
1107 ********************************************************************/
1109 uint32 _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
1110 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1112 fstring driver;
1113 fstring arch;
1114 NT_PRINTER_DRIVER_INFO_LEVEL info;
1115 int version;
1117 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1118 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1120 /* check that we have a valid driver name first */
1121 if ((version=get_version_id(arch)) == -1) {
1122 /* this is what NT returns */
1123 return ERROR_INVALID_ENVIRONMENT;
1126 ZERO_STRUCT(info);
1127 if (get_a_printer_driver (&info, 3, driver, arch, version) != 0) {
1128 /* this is what NT returns */
1129 return ERROR_UNKNOWN_PRINTER_DRIVER;
1133 if (printer_driver_in_use(arch, driver))
1135 /* this is what NT returns */
1136 return ERROR_PRINTER_DRIVER_IN_USE;
1139 return delete_printer_driver(info.info_3);
1143 /********************************************************************
1144 GetPrinterData on a printer server Handle.
1145 ********************************************************************/
1146 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1148 int i;
1150 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1152 if (!strcmp(value, "BeepEnabled")) {
1153 *type = 0x4;
1154 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1155 return False;
1156 SIVAL(*data, 0, 0x01);
1157 *needed = 0x4;
1158 return True;
1161 if (!strcmp(value, "EventLog")) {
1162 *type = 0x4;
1163 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1164 return False;
1165 SIVAL(*data, 0, 0x1B);
1166 *needed = 0x4;
1167 return True;
1170 if (!strcmp(value, "NetPopup")) {
1171 *type = 0x4;
1172 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1173 return False;
1174 SIVAL(*data, 0, 0x01);
1175 *needed = 0x4;
1176 return True;
1179 if (!strcmp(value, "MajorVersion")) {
1180 *type = 0x4;
1181 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1182 return False;
1183 SIVAL(*data, 0, 0x02);
1184 *needed = 0x4;
1185 return True;
1188 if (!strcmp(value, "DefaultSpoolDirectory")) {
1189 pstring string="You are using a Samba server";
1190 *type = 0x1;
1191 *needed = 2*(strlen(string)+1);
1192 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1193 return False;
1194 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1196 /* it's done by hand ready to go on the wire */
1197 for (i=0; i<strlen(string); i++) {
1198 (*data)[2*i]=string[i];
1199 (*data)[2*i+1]='\0';
1201 return True;
1204 if (!strcmp(value, "Architecture")) {
1205 pstring string="Windows NT x86";
1206 *type = 0x1;
1207 *needed = 2*(strlen(string)+1);
1208 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1209 return False;
1210 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1211 for (i=0; i<strlen(string); i++) {
1212 (*data)[2*i]=string[i];
1213 (*data)[2*i+1]='\0';
1215 return True;
1218 return False;
1221 /********************************************************************
1222 GetPrinterData on a printer Handle.
1223 ********************************************************************/
1224 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1225 fstring value, uint32 *type,
1226 uint8 **data, uint32 *needed, uint32 in_size )
1228 NT_PRINTER_INFO_LEVEL *printer = NULL;
1229 int snum=0;
1230 uint8 *idata=NULL;
1231 uint32 len;
1232 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1234 DEBUG(5,("getprinterdata_printer\n"));
1236 if (!Printer) {
1237 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1238 return False;
1241 if(!get_printer_snum(p, handle, &snum))
1242 return False;
1244 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1245 return False;
1247 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1248 free_a_printer(&printer, 2);
1249 return False;
1252 free_a_printer(&printer, 2);
1254 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1256 if (in_size) {
1257 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1258 return False;
1261 memset(*data, 0, in_size *sizeof(uint8));
1262 /* copy the min(in_size, len) */
1263 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1264 } else {
1265 *data = NULL;
1268 *needed = len;
1270 DEBUG(5,("getprinterdata_printer:copy done\n"));
1272 safe_free(idata);
1274 return True;
1277 /********************************************************************
1278 * spoolss_getprinterdata
1279 ********************************************************************/
1281 uint32 _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1283 POLICY_HND *handle = &q_u->handle;
1284 UNISTR2 *valuename = &q_u->valuename;
1285 uint32 in_size = q_u->size;
1286 uint32 *type = &r_u->type;
1287 uint32 *out_size = &r_u->size;
1288 uint8 **data = &r_u->data;
1289 uint32 *needed = &r_u->needed;
1291 fstring value;
1292 BOOL found=False;
1293 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1296 * Reminder: when it's a string, the length is in BYTES
1297 * even if UNICODE is negociated.
1299 * JFM, 4/19/1999
1302 *out_size=in_size;
1304 /* in case of problem, return some default values */
1305 *needed=0;
1306 *type=0;
1308 DEBUG(4,("_spoolss_getprinterdata\n"));
1310 if (!Printer) {
1311 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1312 return ERROR_NOT_ENOUGH_MEMORY;
1313 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1314 return ERROR_INVALID_HANDLE;
1317 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1319 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1320 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1321 else
1322 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1324 if (found==False) {
1325 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1326 /* reply this param doesn't exist */
1327 if (*out_size) {
1328 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1329 return ERROR_NOT_ENOUGH_MEMORY;
1330 } else {
1331 *data = NULL;
1334 return ERROR_INVALID_PARAMETER;
1337 if (*needed > *out_size)
1338 return ERROR_MORE_DATA;
1339 else {
1340 return NT_STATUS_NO_PROBLEMO;
1344 /***************************************************************************
1345 connect to the client
1346 ****************************************************************************/
1347 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1349 uint32 status;
1352 * If it's the first connection, contact the client
1353 * and connect to the IPC$ share anonumously
1355 if (smb_connections==0) {
1356 fstring unix_printer;
1358 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1359 dos_to_unix(unix_printer, True);
1361 if(!spoolss_connect_to_client(&cli, unix_printer))
1362 return False;
1363 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1367 smb_connections++;
1369 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1370 return False;
1372 return True;
1375 /********************************************************************
1376 * _spoolss_rffpcnex
1377 * ReplyFindFirstPrinterChangeNotifyEx
1379 * jfmxxxx: before replying OK: status=0
1380 * should do a rpc call to the workstation asking ReplyOpenPrinter
1381 * have to code it, later.
1383 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1384 * called from api_spoolss_rffpcnex
1385 ********************************************************************/
1387 uint32 _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1389 POLICY_HND *handle = &q_u->handle;
1390 uint32 flags = q_u->flags;
1391 uint32 options = q_u->options;
1392 UNISTR2 *localmachine = &q_u->localmachine;
1393 uint32 printerlocal = q_u->printerlocal;
1394 SPOOL_NOTIFY_OPTION *option = q_u->option;
1396 /* store the notify value in the printer struct */
1398 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1400 if (!Printer) {
1401 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1402 return ERROR_INVALID_HANDLE;
1405 Printer->notify.flags=flags;
1406 Printer->notify.options=options;
1407 Printer->notify.printerlocal=printerlocal;
1409 if (Printer->notify.option)
1410 free_spool_notify_option(&Printer->notify.option);
1412 Printer->notify.option=dup_spool_notify_option(option);
1414 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1416 /* connect to the client machine and send a ReplyOpenPrinter */
1417 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1418 Printer->notify.printerlocal, 1,
1419 &Printer->notify.client_hnd))
1420 Printer->notify.client_connected=True;
1422 return NT_STATUS_NO_PROBLEMO;
1425 /*******************************************************************
1426 * fill a notify_info_data with the servername
1427 ********************************************************************/
1429 static void spoolss_notify_server_name(int snum,
1430 SPOOL_NOTIFY_INFO_DATA *data,
1431 print_queue_struct *queue,
1432 NT_PRINTER_INFO_LEVEL *printer,
1433 TALLOC_CTX *mem_ctx)
1435 pstring temp_name, temp;
1436 uint32 len;
1438 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1440 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1442 data->notify_data.data.length = len / 2 - 1;
1443 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1445 if (!data->notify_data.data.string) {
1446 data->notify_data.data.length = 0;
1447 return;
1450 memcpy(data->notify_data.data.string, temp, len);
1453 /*******************************************************************
1454 * fill a notify_info_data with the printername (not including the servername).
1455 ********************************************************************/
1456 static void spoolss_notify_printer_name(int snum,
1457 SPOOL_NOTIFY_INFO_DATA *data,
1458 print_queue_struct *queue,
1459 NT_PRINTER_INFO_LEVEL *printer,
1460 TALLOC_CTX *mem_ctx)
1462 pstring temp;
1463 uint32 len;
1465 /* the notify name should not contain the \\server\ part */
1466 char *p = strrchr(printer->info_2->printername, '\\');
1468 if (!p) {
1469 p = printer->info_2->printername;
1470 } else {
1471 p++;
1474 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1476 data->notify_data.data.length = len / 2 - 1;
1477 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1479 if (!data->notify_data.data.string) {
1480 data->notify_data.data.length = 0;
1481 return;
1484 memcpy(data->notify_data.data.string, temp, len);
1487 /*******************************************************************
1488 * fill a notify_info_data with the servicename
1489 ********************************************************************/
1490 static void spoolss_notify_share_name(int snum,
1491 SPOOL_NOTIFY_INFO_DATA *data,
1492 print_queue_struct *queue,
1493 NT_PRINTER_INFO_LEVEL *printer,
1494 TALLOC_CTX *mem_ctx)
1496 pstring temp;
1497 uint32 len;
1499 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1500 sizeof(temp) - 2, True);
1502 data->notify_data.data.length = len / 2 - 1;
1503 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1505 if (!data->notify_data.data.string) {
1506 data->notify_data.data.length = 0;
1507 return;
1510 memcpy(data->notify_data.data.string, temp, len);
1513 /*******************************************************************
1514 * fill a notify_info_data with the port name
1515 ********************************************************************/
1516 static void spoolss_notify_port_name(int snum,
1517 SPOOL_NOTIFY_INFO_DATA *data,
1518 print_queue_struct *queue,
1519 NT_PRINTER_INFO_LEVEL *printer,
1520 TALLOC_CTX *mem_ctx)
1522 pstring temp;
1523 uint32 len;
1525 /* even if it's strange, that's consistant in all the code */
1527 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1528 sizeof(temp) - 2, True);
1530 data->notify_data.data.length = len / 2 - 1;
1531 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1533 if (!data->notify_data.data.string) {
1534 data->notify_data.data.length = 0;
1535 return;
1538 memcpy(data->notify_data.data.string, temp, len);
1541 /*******************************************************************
1542 * fill a notify_info_data with the printername
1543 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1544 * but it doesn't exist, have to see what to do
1545 ********************************************************************/
1546 static void spoolss_notify_driver_name(int snum,
1547 SPOOL_NOTIFY_INFO_DATA *data,
1548 print_queue_struct *queue,
1549 NT_PRINTER_INFO_LEVEL *printer,
1550 TALLOC_CTX *mem_ctx)
1552 pstring temp;
1553 uint32 len;
1555 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1556 sizeof(temp) - 2, True);
1558 data->notify_data.data.length = len / 2 - 1;
1559 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1561 if (!data->notify_data.data.string) {
1562 data->notify_data.data.length = 0;
1563 return;
1566 memcpy(data->notify_data.data.string, temp, len);
1569 /*******************************************************************
1570 * fill a notify_info_data with the comment
1571 ********************************************************************/
1572 static void spoolss_notify_comment(int snum,
1573 SPOOL_NOTIFY_INFO_DATA *data,
1574 print_queue_struct *queue,
1575 NT_PRINTER_INFO_LEVEL *printer,
1576 TALLOC_CTX *mem_ctx)
1578 pstring temp;
1579 uint32 len;
1581 if (*printer->info_2->comment == '\0')
1582 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1583 sizeof(temp) - 2, True);
1584 else
1585 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1586 sizeof(temp) - 2, True);
1588 data->notify_data.data.length = len / 2 - 1;
1589 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1591 if (!data->notify_data.data.string) {
1592 data->notify_data.data.length = 0;
1593 return;
1596 memcpy(data->notify_data.data.string, temp, len);
1599 /*******************************************************************
1600 * fill a notify_info_data with the comment
1601 * jfm:xxxx incorrect, have to create a new smb.conf option
1602 * location = "Room 1, floor 2, building 3"
1603 ********************************************************************/
1604 static void spoolss_notify_location(int snum,
1605 SPOOL_NOTIFY_INFO_DATA *data,
1606 print_queue_struct *queue,
1607 NT_PRINTER_INFO_LEVEL *printer,
1608 TALLOC_CTX *mem_ctx)
1610 pstring temp;
1611 uint32 len;
1613 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1614 sizeof(temp) - 2, True);
1616 data->notify_data.data.length = len / 2 - 1;
1617 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1619 if (!data->notify_data.data.string) {
1620 data->notify_data.data.length = 0;
1621 return;
1624 memcpy(data->notify_data.data.string, temp, len);
1627 /*******************************************************************
1628 * fill a notify_info_data with the device mode
1629 * jfm:xxxx don't to it for know but that's a real problem !!!
1630 ********************************************************************/
1631 static void spoolss_notify_devmode(int snum,
1632 SPOOL_NOTIFY_INFO_DATA *data,
1633 print_queue_struct *queue,
1634 NT_PRINTER_INFO_LEVEL *printer,
1635 TALLOC_CTX *mem_ctx)
1639 /*******************************************************************
1640 * fill a notify_info_data with the separator file name
1641 * jfm:xxxx just return no file could add an option to smb.conf
1642 * separator file = "separator.txt"
1643 ********************************************************************/
1644 static void spoolss_notify_sepfile(int snum,
1645 SPOOL_NOTIFY_INFO_DATA *data,
1646 print_queue_struct *queue,
1647 NT_PRINTER_INFO_LEVEL *printer,
1648 TALLOC_CTX *mem_ctx)
1650 pstring temp;
1651 uint32 len;
1653 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1654 sizeof(temp) - 2, True);
1656 data->notify_data.data.length = len / 2 - 1;
1657 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1659 if (!data->notify_data.data.string) {
1660 data->notify_data.data.length = 0;
1661 return;
1664 memcpy(data->notify_data.data.string, temp, len);
1667 /*******************************************************************
1668 * fill a notify_info_data with the print processor
1669 * jfm:xxxx return always winprint to indicate we don't do anything to it
1670 ********************************************************************/
1671 static void spoolss_notify_print_processor(int snum,
1672 SPOOL_NOTIFY_INFO_DATA *data,
1673 print_queue_struct *queue,
1674 NT_PRINTER_INFO_LEVEL *printer,
1675 TALLOC_CTX *mem_ctx)
1677 pstring temp;
1678 uint32 len;
1680 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
1681 sizeof(temp) - 2, True);
1683 data->notify_data.data.length = len / 2 - 1;
1684 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1686 if (!data->notify_data.data.string) {
1687 data->notify_data.data.length = 0;
1688 return;
1691 memcpy(data->notify_data.data.string, temp, len);
1694 /*******************************************************************
1695 * fill a notify_info_data with the print processor options
1696 * jfm:xxxx send an empty string
1697 ********************************************************************/
1698 static void spoolss_notify_parameters(int snum,
1699 SPOOL_NOTIFY_INFO_DATA *data,
1700 print_queue_struct *queue,
1701 NT_PRINTER_INFO_LEVEL *printer,
1702 TALLOC_CTX *mem_ctx)
1704 pstring temp;
1705 uint32 len;
1707 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1708 sizeof(temp) - 2, True);
1710 data->notify_data.data.length = len / 2 - 1;
1711 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1713 if (!data->notify_data.data.string) {
1714 data->notify_data.data.length = 0;
1715 return;
1718 memcpy(data->notify_data.data.string, temp, len);
1721 /*******************************************************************
1722 * fill a notify_info_data with the data type
1723 * jfm:xxxx always send RAW as data type
1724 ********************************************************************/
1725 static void spoolss_notify_datatype(int snum,
1726 SPOOL_NOTIFY_INFO_DATA *data,
1727 print_queue_struct *queue,
1728 NT_PRINTER_INFO_LEVEL *printer,
1729 TALLOC_CTX *mem_ctx)
1731 pstring temp;
1732 uint32 len;
1734 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1735 sizeof(pstring) - 2, True);
1737 data->notify_data.data.length = len / 2 - 1;
1738 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1740 if (!data->notify_data.data.string) {
1741 data->notify_data.data.length = 0;
1742 return;
1745 memcpy(data->notify_data.data.string, temp, len);
1748 /*******************************************************************
1749 * fill a notify_info_data with the security descriptor
1750 * jfm:xxxx send an null pointer to say no security desc
1751 * have to implement security before !
1752 ********************************************************************/
1753 static void spoolss_notify_security_desc(int snum,
1754 SPOOL_NOTIFY_INFO_DATA *data,
1755 print_queue_struct *queue,
1756 NT_PRINTER_INFO_LEVEL *printer,
1757 TALLOC_CTX *mem_ctx)
1759 data->notify_data.data.length=0;
1760 data->notify_data.data.string = NULL;
1763 /*******************************************************************
1764 * fill a notify_info_data with the attributes
1765 * jfm:xxxx a samba printer is always shared
1766 ********************************************************************/
1767 static void spoolss_notify_attributes(int snum,
1768 SPOOL_NOTIFY_INFO_DATA *data,
1769 print_queue_struct *queue,
1770 NT_PRINTER_INFO_LEVEL *printer,
1771 TALLOC_CTX *mem_ctx)
1773 data->notify_data.value[0] = printer->info_2->attributes;
1776 /*******************************************************************
1777 * fill a notify_info_data with the priority
1778 ********************************************************************/
1779 static void spoolss_notify_priority(int snum,
1780 SPOOL_NOTIFY_INFO_DATA *data,
1781 print_queue_struct *queue,
1782 NT_PRINTER_INFO_LEVEL *printer,
1783 TALLOC_CTX *mem_ctx)
1785 data->notify_data.value[0] = printer->info_2->priority;
1788 /*******************************************************************
1789 * fill a notify_info_data with the default priority
1790 ********************************************************************/
1791 static void spoolss_notify_default_priority(int snum,
1792 SPOOL_NOTIFY_INFO_DATA *data,
1793 print_queue_struct *queue,
1794 NT_PRINTER_INFO_LEVEL *printer,
1795 TALLOC_CTX *mem_ctx)
1797 data->notify_data.value[0] = printer->info_2->default_priority;
1800 /*******************************************************************
1801 * fill a notify_info_data with the start time
1802 ********************************************************************/
1803 static void spoolss_notify_start_time(int snum,
1804 SPOOL_NOTIFY_INFO_DATA *data,
1805 print_queue_struct *queue,
1806 NT_PRINTER_INFO_LEVEL *printer,
1807 TALLOC_CTX *mem_ctx)
1809 data->notify_data.value[0] = printer->info_2->starttime;
1812 /*******************************************************************
1813 * fill a notify_info_data with the until time
1814 ********************************************************************/
1815 static void spoolss_notify_until_time(int snum,
1816 SPOOL_NOTIFY_INFO_DATA *data,
1817 print_queue_struct *queue,
1818 NT_PRINTER_INFO_LEVEL *printer,
1819 TALLOC_CTX *mem_ctx)
1821 data->notify_data.value[0] = printer->info_2->untiltime;
1824 /*******************************************************************
1825 * fill a notify_info_data with the status
1826 ********************************************************************/
1827 static void spoolss_notify_status(int snum,
1828 SPOOL_NOTIFY_INFO_DATA *data,
1829 print_queue_struct *queue,
1830 NT_PRINTER_INFO_LEVEL *printer,
1831 TALLOC_CTX *mem_ctx)
1833 print_queue_struct *q=NULL;
1834 print_status_struct status;
1836 memset(&status, 0, sizeof(status));
1837 print_queue_status(snum, &q, &status);
1838 data->notify_data.value[0]=(uint32) status.status;
1839 safe_free(q);
1842 /*******************************************************************
1843 * fill a notify_info_data with the number of jobs queued
1844 ********************************************************************/
1845 static void spoolss_notify_cjobs(int snum,
1846 SPOOL_NOTIFY_INFO_DATA *data,
1847 print_queue_struct *queue,
1848 NT_PRINTER_INFO_LEVEL *printer,
1849 TALLOC_CTX *mem_ctx)
1851 print_queue_struct *q=NULL;
1852 print_status_struct status;
1854 memset(&status, 0, sizeof(status));
1855 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1856 safe_free(q);
1859 /*******************************************************************
1860 * fill a notify_info_data with the average ppm
1861 ********************************************************************/
1862 static void spoolss_notify_average_ppm(int snum,
1863 SPOOL_NOTIFY_INFO_DATA *data,
1864 print_queue_struct *queue,
1865 NT_PRINTER_INFO_LEVEL *printer,
1866 TALLOC_CTX *mem_ctx)
1868 /* always respond 8 pages per minutes */
1869 /* a little hard ! */
1870 data->notify_data.value[0] = printer->info_2->averageppm;
1873 /*******************************************************************
1874 * fill a notify_info_data with username
1875 ********************************************************************/
1876 static void spoolss_notify_username(int snum,
1877 SPOOL_NOTIFY_INFO_DATA *data,
1878 print_queue_struct *queue,
1879 NT_PRINTER_INFO_LEVEL *printer,
1880 TALLOC_CTX *mem_ctx)
1882 pstring temp;
1883 uint32 len;
1885 len = (uint32)dos_PutUniCode(temp, queue->user,
1886 sizeof(temp) - 2, True);
1888 data->notify_data.data.length = len / 2 - 1;
1889 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1891 if (!data->notify_data.data.string) {
1892 data->notify_data.data.length = 0;
1893 return;
1896 memcpy(data->notify_data.data.string, temp, len);
1899 /*******************************************************************
1900 * fill a notify_info_data with job status
1901 ********************************************************************/
1902 static void spoolss_notify_job_status(int snum,
1903 SPOOL_NOTIFY_INFO_DATA *data,
1904 print_queue_struct *queue,
1905 NT_PRINTER_INFO_LEVEL *printer,
1906 TALLOC_CTX *mem_ctx)
1908 data->notify_data.value[0]=nt_printj_status(queue->status);
1911 /*******************************************************************
1912 * fill a notify_info_data with job name
1913 ********************************************************************/
1914 static void spoolss_notify_job_name(int snum,
1915 SPOOL_NOTIFY_INFO_DATA *data,
1916 print_queue_struct *queue,
1917 NT_PRINTER_INFO_LEVEL *printer,
1918 TALLOC_CTX *mem_ctx)
1920 pstring temp;
1921 uint32 len;
1923 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1924 True);
1926 data->notify_data.data.length = len / 2 - 1;
1927 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1929 if (!data->notify_data.data.string) {
1930 data->notify_data.data.length = 0;
1931 return;
1934 memcpy(data->notify_data.data.string, temp, len);
1937 /*******************************************************************
1938 * fill a notify_info_data with job status
1939 ********************************************************************/
1940 static void spoolss_notify_job_status_string(int snum,
1941 SPOOL_NOTIFY_INFO_DATA *data,
1942 print_queue_struct *queue,
1943 NT_PRINTER_INFO_LEVEL *printer,
1944 TALLOC_CTX *mem_ctx)
1947 * Now we're returning job status codes we just return a "" here. JRA.
1950 char *p = "";
1951 pstring temp;
1952 uint32 len;
1954 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1955 p = "unknown";
1957 switch (queue->status) {
1958 case LPQ_QUEUED:
1959 p = "Queued";
1960 break;
1961 case LPQ_PAUSED:
1962 p = ""; /* NT provides the paused string */
1963 break;
1964 case LPQ_SPOOLING:
1965 p = "Spooling";
1966 break;
1967 case LPQ_PRINTING:
1968 p = "Printing";
1969 break;
1971 #endif /* NO LONGER NEEDED. */
1973 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1975 data->notify_data.data.length = len / 2 - 1;
1976 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1978 if (!data->notify_data.data.string) {
1979 data->notify_data.data.length = 0;
1980 return;
1983 memcpy(data->notify_data.data.string, temp, len);
1986 /*******************************************************************
1987 * fill a notify_info_data with job time
1988 ********************************************************************/
1989 static void spoolss_notify_job_time(int snum,
1990 SPOOL_NOTIFY_INFO_DATA *data,
1991 print_queue_struct *queue,
1992 NT_PRINTER_INFO_LEVEL *printer,
1993 TALLOC_CTX *mem_ctx)
1995 data->notify_data.value[0]=0x0;
1998 /*******************************************************************
1999 * fill a notify_info_data with job size
2000 ********************************************************************/
2001 static void spoolss_notify_job_size(int snum,
2002 SPOOL_NOTIFY_INFO_DATA *data,
2003 print_queue_struct *queue,
2004 NT_PRINTER_INFO_LEVEL *printer,
2005 TALLOC_CTX *mem_ctx)
2007 data->notify_data.value[0]=queue->size;
2010 /*******************************************************************
2011 * fill a notify_info_data with job position
2012 ********************************************************************/
2013 static void spoolss_notify_job_position(int snum,
2014 SPOOL_NOTIFY_INFO_DATA *data,
2015 print_queue_struct *queue,
2016 NT_PRINTER_INFO_LEVEL *printer,
2017 TALLOC_CTX *mem_ctx)
2019 data->notify_data.value[0]=queue->job;
2022 /*******************************************************************
2023 * fill a notify_info_data with submitted time
2024 ********************************************************************/
2025 static void spoolss_notify_submitted_time(int snum,
2026 SPOOL_NOTIFY_INFO_DATA *data,
2027 print_queue_struct *queue,
2028 NT_PRINTER_INFO_LEVEL *printer,
2029 TALLOC_CTX *mem_ctx)
2031 struct tm *t;
2032 uint32 len;
2033 SYSTEMTIME st;
2035 t=gmtime(&queue->time);
2037 len = sizeof(SYSTEMTIME);
2039 data->notify_data.data.length = len/2 - 1;
2040 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2042 if (!data->notify_data.data.string) {
2043 data->notify_data.data.length = 0;
2044 return;
2047 make_systemtime(&st, t);
2048 memcpy(data->notify_data.data.string,&st,len);
2051 #define END 65535
2053 struct s_notify_info_data_table
2055 uint16 type;
2056 uint16 field;
2057 char *name;
2058 uint32 size;
2059 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2060 print_queue_struct *queue,
2061 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2064 struct s_notify_info_data_table notify_info_data_table[] =
2066 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2067 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2090 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2091 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2092 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2093 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2094 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2095 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2096 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2097 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2098 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2099 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2100 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2101 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2102 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2103 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2104 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2105 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2106 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2107 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2108 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2109 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2110 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2111 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2112 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2113 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2114 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2115 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2116 { END, END, "", END, NULL }
2119 /*******************************************************************
2120 return the size of info_data structure
2121 ********************************************************************/
2122 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2124 int i=0;
2126 while (notify_info_data_table[i].type != END)
2128 if ( (notify_info_data_table[i].type == type ) &&
2129 (notify_info_data_table[i].field == field ) )
2131 return (notify_info_data_table[i].size);
2133 i++;
2135 return (65535);
2138 /*******************************************************************
2139 return the type of notify_info_data
2140 ********************************************************************/
2141 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2143 int i=0;
2145 while (notify_info_data_table[i].type != END)
2147 if ( (notify_info_data_table[i].type == type ) &&
2148 (notify_info_data_table[i].field == field ) )
2150 if (notify_info_data_table[i].size == POINTER)
2152 return (False);
2154 else
2156 return (True);
2159 i++;
2161 return (False);
2164 /****************************************************************************
2165 ****************************************************************************/
2166 static int search_notify(uint16 type, uint16 field, int *value)
2168 int j;
2169 BOOL found;
2171 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2173 if ( (notify_info_data_table[j].type == type ) &&
2174 (notify_info_data_table[j].field == field ) )
2175 found=True;
2177 *value=--j;
2179 if ( found && (notify_info_data_table[j].fn != NULL) )
2180 return True;
2181 else
2182 return False;
2185 /****************************************************************************
2186 ****************************************************************************/
2187 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2189 info_data->type = type;
2190 info_data->field = field;
2191 info_data->reserved = 0;
2192 info_data->id = id;
2193 info_data->size = size_of_notify_info_data(type, field);
2194 info_data->enc_type = type_of_notify_info_data(type, field);
2198 /*******************************************************************
2200 * fill a notify_info struct with info asked
2202 ********************************************************************/
2203 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2204 snum, SPOOL_NOTIFY_OPTION_TYPE
2205 *option_type, uint32 id,
2206 TALLOC_CTX *mem_ctx)
2208 int field_num,j;
2209 uint16 type;
2210 uint16 field;
2212 SPOOL_NOTIFY_INFO_DATA *current_data;
2213 NT_PRINTER_INFO_LEVEL *printer = NULL;
2214 print_queue_struct *queue=NULL;
2216 type=option_type->type;
2218 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2219 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2220 option_type->count, lp_servicename(snum)));
2222 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2223 return False;
2225 for(field_num=0; field_num<option_type->count; field_num++) {
2226 field = option_type->fields[field_num];
2227 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2229 if (!search_notify(type, field, &j) )
2230 continue;
2232 if((info->data=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2233 return False;
2235 current_data=&info->data[info->count];
2237 construct_info_data(current_data, type, field, id);
2239 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2240 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2242 notify_info_data_table[j].fn(snum, current_data, queue,
2243 printer, mem_ctx);
2245 info->count++;
2248 free_a_printer(&printer, 2);
2249 return True;
2252 /*******************************************************************
2254 * fill a notify_info struct with info asked
2256 ********************************************************************/
2257 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2258 SPOOL_NOTIFY_INFO *info,
2259 NT_PRINTER_INFO_LEVEL *printer,
2260 int snum, SPOOL_NOTIFY_OPTION_TYPE
2261 *option_type, uint32 id,
2262 TALLOC_CTX *mem_ctx)
2264 int field_num,j;
2265 uint16 type;
2266 uint16 field;
2268 SPOOL_NOTIFY_INFO_DATA *current_data;
2270 DEBUG(4,("construct_notify_jobs_info\n"));
2272 type = option_type->type;
2274 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2275 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2276 option_type->count));
2278 for(field_num=0; field_num<option_type->count; field_num++) {
2279 field = option_type->fields[field_num];
2281 if (!search_notify(type, field, &j) )
2282 continue;
2284 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2285 return False;
2288 current_data=&(info->data[info->count]);
2290 construct_info_data(current_data, type, field, id);
2291 notify_info_data_table[j].fn(snum, current_data, queue,
2292 printer, mem_ctx);
2293 info->count++;
2296 return True;
2300 * JFM: The enumeration is not that simple, it's even non obvious.
2302 * let's take an example: I want to monitor the PRINTER SERVER for
2303 * the printer's name and the number of jobs currently queued.
2304 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2305 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2307 * I have 3 printers on the back of my server.
2309 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2310 * structures.
2311 * Number Data Id
2312 * 1 printer 1 name 1
2313 * 2 printer 1 cjob 1
2314 * 3 printer 2 name 2
2315 * 4 printer 2 cjob 2
2316 * 5 printer 3 name 3
2317 * 6 printer 3 name 3
2319 * that's the print server case, the printer case is even worse.
2322 /*******************************************************************
2324 * enumerate all printers on the printserver
2325 * fill a notify_info struct with info asked
2327 ********************************************************************/
2329 static uint32 printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2330 SPOOL_NOTIFY_INFO *info,
2331 TALLOC_CTX *mem_ctx)
2333 int snum;
2334 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2335 int n_services=lp_numservices();
2336 int i;
2337 uint32 id;
2338 SPOOL_NOTIFY_OPTION *option;
2339 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2341 DEBUG(4,("printserver_notify_info\n"));
2343 option=Printer->notify.option;
2344 id=1;
2345 info->version=2;
2346 info->data=NULL;
2347 info->count=0;
2349 for (i=0; i<option->count; i++) {
2350 option_type=&(option->ctr.type[i]);
2352 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2353 continue;
2355 for (snum=0; snum<n_services; snum++)
2356 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2357 if (construct_notify_printer_info
2358 (info, snum, option_type, id, mem_ctx))
2359 id++;
2363 * Debugging information, don't delete.
2366 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2367 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2368 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2370 for (i=0; i<info->count; i++) {
2371 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2372 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2373 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2377 return NT_STATUS_NO_PROBLEMO;
2380 /*******************************************************************
2382 * fill a notify_info struct with info asked
2384 ********************************************************************/
2385 static uint32 printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2386 TALLOC_CTX *mem_ctx)
2388 int snum;
2389 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2390 int i;
2391 uint32 id;
2392 SPOOL_NOTIFY_OPTION *option;
2393 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2394 int count,j;
2395 print_queue_struct *queue=NULL;
2396 print_status_struct status;
2398 DEBUG(4,("printer_notify_info\n"));
2400 option=Printer->notify.option;
2401 id=0xffffffff;
2402 info->version=2;
2403 info->data=NULL;
2404 info->count=0;
2406 get_printer_snum(p, hnd, &snum);
2408 for (i=0; i<option->count; i++) {
2409 option_type=&option->ctr.type[i];
2411 switch ( option_type->type ) {
2412 case PRINTER_NOTIFY_TYPE:
2413 if(construct_notify_printer_info(info, snum,
2414 option_type, id,
2415 mem_ctx))
2416 id--;
2417 break;
2419 case JOB_NOTIFY_TYPE: {
2420 NT_PRINTER_INFO_LEVEL *printer = NULL;
2422 memset(&status, 0, sizeof(status));
2423 count = print_queue_status(snum, &queue, &status);
2425 if (get_a_printer(&printer, 2,
2426 lp_servicename(snum)) != 0)
2427 goto done;
2429 for (j=0; j<count; j++) {
2430 construct_notify_jobs_info(&queue[j], info,
2431 printer, snum,
2432 option_type,
2433 queue[j].job,
2434 mem_ctx);
2437 free_a_printer(&printer, 2);
2439 done:
2440 safe_free(queue);
2441 break;
2447 * Debugging information, don't delete.
2450 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2451 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2452 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2454 for (i=0; i<info->count; i++) {
2455 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2456 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2457 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2460 return NT_STATUS_NO_PROBLEMO;
2463 /********************************************************************
2464 * spoolss_rfnpcnex
2465 ********************************************************************/
2467 uint32 _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2469 POLICY_HND *handle = &q_u->handle;
2470 /* uint32 change = q_u->change; - notused. */
2471 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2472 SPOOL_NOTIFY_INFO *info = &r_u->info;
2474 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2475 uint32 result = ERROR_INVALID_HANDLE;
2477 /* we always have a NOTIFY_INFO struct */
2478 r_u->info_ptr=0x1;
2480 if (!Printer) {
2481 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2482 OUR_HANDLE(handle)));
2483 goto done;
2486 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2488 /* jfm: the change value isn't used right now.
2489 * we will honour it when
2490 * a) we'll be able to send notification to the client
2491 * b) we'll have a way to communicate between the spoolss process.
2493 * same thing for option->flags
2494 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2495 * I don't have a global notification system, I'm sending back all the
2496 * informations even when _NOTHING_ has changed.
2499 /* just ignore the SPOOL_NOTIFY_OPTION */
2501 switch (Printer->printer_type) {
2502 case PRINTER_HANDLE_IS_PRINTSERVER:
2503 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2504 break;
2506 case PRINTER_HANDLE_IS_PRINTER:
2507 result = printer_notify_info(p, handle, info, p->mem_ctx);
2508 break;
2511 done:
2512 return result;
2515 /********************************************************************
2516 * construct_printer_info_0
2517 * fill a printer_info_0 struct
2518 ********************************************************************/
2519 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2521 pstring chaine;
2522 int count;
2523 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2524 counter_printer_0 *session_counter;
2525 uint32 global_counter;
2526 struct tm *t;
2527 time_t setuptime;
2529 print_queue_struct *queue=NULL;
2530 print_status_struct status;
2532 memset(&status, 0, sizeof(status));
2534 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2535 return False;
2537 count = print_queue_status(snum, &queue, &status);
2539 /* check if we already have a counter for this printer */
2540 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2542 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2543 if (session_counter->snum == snum)
2544 break;
2547 /* it's the first time, add it to the list */
2548 if (session_counter==NULL) {
2549 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2550 free_a_printer(&ntprinter, 2);
2551 return False;
2553 ZERO_STRUCTP(session_counter);
2554 session_counter->snum=snum;
2555 session_counter->counter=0;
2556 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2559 /* increment it */
2560 session_counter->counter++;
2562 /* JFM:
2563 * the global_counter should be stored in a TDB as it's common to all the clients
2564 * and should be zeroed on samba startup
2566 global_counter=session_counter->counter;
2568 pstrcpy(chaine,ntprinter->info_2->printername);
2570 init_unistr(&printer->printername, chaine);
2572 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2573 init_unistr(&printer->servername, chaine);
2575 printer->cjobs = count;
2576 printer->total_jobs = 0;
2577 printer->total_bytes = 0;
2579 setuptime = (time_t)ntprinter->info_2->setuptime;
2580 t=gmtime(&setuptime);
2582 printer->year = t->tm_year+1900;
2583 printer->month = t->tm_mon+1;
2584 printer->dayofweek = t->tm_wday;
2585 printer->day = t->tm_mday;
2586 printer->hour = t->tm_hour;
2587 printer->minute = t->tm_min;
2588 printer->second = t->tm_sec;
2589 printer->milliseconds = 0;
2591 printer->global_counter = global_counter;
2592 printer->total_pages = 0;
2593 printer->major_version = 0x0004; /* NT 4 */
2594 printer->build_version = 0x0565; /* build 1381 */
2595 printer->unknown7 = 0x1;
2596 printer->unknown8 = 0x0;
2597 printer->unknown9 = 0x0;
2598 printer->session_counter = session_counter->counter;
2599 printer->unknown11 = 0x0;
2600 printer->printer_errors = 0x0; /* number of print failure */
2601 printer->unknown13 = 0x0;
2602 printer->unknown14 = 0x1;
2603 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2604 printer->unknown16 = 0x0;
2605 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2606 printer->unknown18 = 0x0;
2607 printer->status = nt_printq_status(status.status);
2608 printer->unknown20 = 0x0;
2609 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2610 printer->unknown22 = 0x0;
2611 printer->unknown23 = 0x6; /* 6 ???*/
2612 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2613 printer->unknown25 = 0;
2614 printer->unknown26 = 0;
2615 printer->unknown27 = 0;
2616 printer->unknown28 = 0;
2617 printer->unknown29 = 0;
2619 safe_free(queue);
2620 free_a_printer(&ntprinter,2);
2621 return (True);
2624 /********************************************************************
2625 * construct_printer_info_1
2626 * fill a printer_info_1 struct
2627 ********************************************************************/
2628 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2630 pstring chaine;
2631 pstring chaine2;
2632 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2634 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2635 return False;
2637 printer->flags=flags;
2639 if (*ntprinter->info_2->comment == '\0') {
2640 init_unistr(&printer->comment, lp_comment(snum));
2641 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2642 ntprinter->info_2->drivername, lp_comment(snum));
2644 else {
2645 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2646 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2647 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2650 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2652 init_unistr(&printer->description, chaine);
2653 init_unistr(&printer->name, chaine2);
2655 free_a_printer(&ntprinter,2);
2657 return True;
2660 /****************************************************************************
2661 Free a DEVMODE struct.
2662 ****************************************************************************/
2664 static void free_dev_mode(DEVICEMODE *dev)
2666 if (dev == NULL)
2667 return;
2669 if (dev->private)
2670 safe_free(dev->private);
2672 safe_free(dev);
2675 /****************************************************************************
2676 Create a DEVMODE struct. Returns malloced memory.
2677 ****************************************************************************/
2679 static DEVICEMODE *construct_dev_mode(int snum)
2681 char adevice[32];
2682 char aform[32];
2683 NT_PRINTER_INFO_LEVEL *printer = NULL;
2684 NT_DEVICEMODE *ntdevmode = NULL;
2685 DEVICEMODE *devmode = NULL;
2687 DEBUG(7,("construct_dev_mode\n"));
2689 DEBUGADD(8,("getting printer characteristics\n"));
2691 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2692 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2693 return NULL;
2696 ZERO_STRUCTP(devmode);
2698 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2699 goto fail;
2701 if (printer->info_2->devmode)
2702 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2704 if (ntdevmode == NULL)
2705 goto fail;
2707 DEBUGADD(8,("loading DEVICEMODE\n"));
2709 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2710 init_unistr(&devmode->devicename, adevice);
2712 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2713 init_unistr(&devmode->formname, aform);
2715 devmode->specversion = ntdevmode->specversion;
2716 devmode->driverversion = ntdevmode->driverversion;
2717 devmode->size = ntdevmode->size;
2718 devmode->driverextra = ntdevmode->driverextra;
2719 devmode->fields = ntdevmode->fields;
2721 devmode->orientation = ntdevmode->orientation;
2722 devmode->papersize = ntdevmode->papersize;
2723 devmode->paperlength = ntdevmode->paperlength;
2724 devmode->paperwidth = ntdevmode->paperwidth;
2725 devmode->scale = ntdevmode->scale;
2726 devmode->copies = ntdevmode->copies;
2727 devmode->defaultsource = ntdevmode->defaultsource;
2728 devmode->printquality = ntdevmode->printquality;
2729 devmode->color = ntdevmode->color;
2730 devmode->duplex = ntdevmode->duplex;
2731 devmode->yresolution = ntdevmode->yresolution;
2732 devmode->ttoption = ntdevmode->ttoption;
2733 devmode->collate = ntdevmode->collate;
2734 devmode->icmmethod = ntdevmode->icmmethod;
2735 devmode->icmintent = ntdevmode->icmintent;
2736 devmode->mediatype = ntdevmode->mediatype;
2737 devmode->dithertype = ntdevmode->dithertype;
2739 if (ntdevmode->private != NULL) {
2740 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2741 goto fail;
2744 free_nt_devicemode(&ntdevmode);
2745 free_a_printer(&printer,2);
2747 return devmode;
2749 fail:
2751 if (ntdevmode)
2752 free_nt_devicemode(&ntdevmode);
2753 if (printer)
2754 free_a_printer(&printer,2);
2755 free_dev_mode(devmode);
2757 return NULL;
2760 /********************************************************************
2761 * construct_printer_info_2
2762 * fill a printer_info_2 struct
2763 ********************************************************************/
2765 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2767 int count;
2768 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2770 print_queue_struct *queue=NULL;
2771 print_status_struct status;
2772 memset(&status, 0, sizeof(status));
2774 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2775 return False;
2777 memset(&status, 0, sizeof(status));
2778 count = print_queue_status(snum, &queue, &status);
2780 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2781 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2782 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2783 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2784 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2786 if (*ntprinter->info_2->comment == '\0')
2787 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2788 else
2789 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2791 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2792 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2793 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2794 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2795 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2797 printer->attributes = ntprinter->info_2->attributes;
2799 printer->priority = ntprinter->info_2->priority; /* priority */
2800 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2801 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2802 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2803 printer->status = nt_printq_status(status.status); /* status */
2804 printer->cjobs = count; /* jobs */
2805 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2807 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2808 DEBUG(8, ("Returning NULL Devicemode!\n"));
2811 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2812 /* steal the printer info sec_desc structure. [badly done]. */
2813 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2814 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2815 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2816 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2818 else {
2819 printer->secdesc = NULL;
2822 free_a_printer(&ntprinter, 2);
2823 safe_free(queue);
2824 return True;
2827 /********************************************************************
2828 * construct_printer_info_3
2829 * fill a printer_info_3 struct
2830 ********************************************************************/
2831 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2833 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2834 PRINTER_INFO_3 *printer = NULL;
2836 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2837 return False;
2839 *pp_printer = NULL;
2840 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2841 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2842 return False;
2845 ZERO_STRUCTP(printer);
2847 printer->flags = 4; /* These are the components of the SD we are returning. */
2848 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2849 /* steal the printer info sec_desc structure. [badly done]. */
2850 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2852 #if 0
2854 * Set the flags for the components we are returning.
2857 if (printer->secdesc->owner_sid)
2858 printer->flags |= OWNER_SECURITY_INFORMATION;
2860 if (printer->secdesc->grp_sid)
2861 printer->flags |= GROUP_SECURITY_INFORMATION;
2863 if (printer->secdesc->dacl)
2864 printer->flags |= DACL_SECURITY_INFORMATION;
2866 if (printer->secdesc->sacl)
2867 printer->flags |= SACL_SECURITY_INFORMATION;
2868 #endif
2870 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2871 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2872 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2875 free_a_printer(&ntprinter, 2);
2877 *pp_printer = printer;
2878 return True;
2881 /********************************************************************
2882 Spoolss_enumprinters.
2883 ********************************************************************/
2884 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2886 int snum;
2887 int i;
2888 int n_services=lp_numservices();
2889 PRINTER_INFO_1 *printers=NULL;
2890 PRINTER_INFO_1 current_prt;
2892 DEBUG(4,("enum_all_printers_info_1\n"));
2894 for (snum=0; snum<n_services; snum++) {
2895 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2896 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2898 if (construct_printer_info_1(flags, &current_prt, snum)) {
2899 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2900 *returned=0;
2901 return ERROR_NOT_ENOUGH_MEMORY;
2903 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2904 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
2905 (*returned)++;
2910 /* check the required size. */
2911 for (i=0; i<*returned; i++)
2912 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2914 if (!alloc_buffer_size(buffer, *needed))
2915 return ERROR_INSUFFICIENT_BUFFER;
2917 /* fill the buffer with the structures */
2918 for (i=0; i<*returned; i++)
2919 smb_io_printer_info_1("", buffer, &printers[i], 0);
2921 /* clear memory */
2922 safe_free(printers);
2924 if (*needed > offered) {
2925 *returned=0;
2926 return ERROR_INSUFFICIENT_BUFFER;
2928 else
2929 return NT_STATUS_NO_PROBLEMO;
2932 /********************************************************************
2933 enum_all_printers_info_1_local.
2934 *********************************************************************/
2935 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2937 DEBUG(4,("enum_all_printers_info_1_local\n"));
2939 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2942 /********************************************************************
2943 enum_all_printers_info_1_name.
2944 *********************************************************************/
2945 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2947 fstring temp;
2948 DEBUG(4,("enum_all_printers_info_1_name\n"));
2950 fstrcpy(temp, "\\\\");
2951 fstrcat(temp, global_myname);
2953 if (strequal(name, temp)) {
2954 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2956 else
2957 return ERROR_INVALID_NAME;
2960 /********************************************************************
2961 enum_all_printers_info_1_remote.
2962 *********************************************************************/
2963 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2965 PRINTER_INFO_1 *printer;
2966 fstring printername;
2967 fstring desc;
2968 fstring comment;
2969 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2971 /* JFM: currently it's more a place holder than anything else.
2972 * In the spooler world there is a notion of server registration.
2973 * the print servers are registring (sp ?) on the PDC (in the same domain)
2975 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2978 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2979 return ERROR_NOT_ENOUGH_MEMORY;
2981 *returned=1;
2983 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2984 slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2985 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2987 init_unistr(&printer->description, desc);
2988 init_unistr(&printer->name, printername);
2989 init_unistr(&printer->comment, comment);
2990 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2992 /* check the required size. */
2993 *needed += spoolss_size_printer_info_1(printer);
2995 if (!alloc_buffer_size(buffer, *needed)) {
2996 safe_free(printer);
2997 return ERROR_INSUFFICIENT_BUFFER;
3000 /* fill the buffer with the structures */
3001 smb_io_printer_info_1("", buffer, printer, 0);
3003 /* clear memory */
3004 safe_free(printer);
3006 if (*needed > offered) {
3007 *returned=0;
3008 return ERROR_INSUFFICIENT_BUFFER;
3010 else
3011 return NT_STATUS_NO_PROBLEMO;
3014 /********************************************************************
3015 enum_all_printers_info_1_network.
3016 *********************************************************************/
3018 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3020 DEBUG(4,("enum_all_printers_info_1_network\n"));
3022 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3025 /********************************************************************
3026 * api_spoolss_enumprinters
3028 * called from api_spoolss_enumprinters (see this to understand)
3029 ********************************************************************/
3031 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3033 int snum;
3034 int i;
3035 int n_services=lp_numservices();
3036 PRINTER_INFO_2 *printers=NULL;
3037 PRINTER_INFO_2 current_prt;
3039 for (snum=0; snum<n_services; snum++) {
3040 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3041 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3043 if (construct_printer_info_2(&current_prt, snum)) {
3044 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
3045 return ERROR_NOT_ENOUGH_MEMORY;
3046 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3047 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3048 (*returned)++;
3053 /* check the required size. */
3054 for (i=0; i<*returned; i++)
3055 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3057 if (!alloc_buffer_size(buffer, *needed)) {
3058 for (i=0; i<*returned; i++) {
3059 free_devmode(printers[i].devmode);
3061 safe_free(printers);
3062 return ERROR_INSUFFICIENT_BUFFER;
3065 /* fill the buffer with the structures */
3066 for (i=0; i<*returned; i++)
3067 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3069 /* clear memory */
3070 for (i=0; i<*returned; i++) {
3071 free_devmode(printers[i].devmode);
3073 safe_free(printers);
3075 if (*needed > offered) {
3076 *returned=0;
3077 return ERROR_INSUFFICIENT_BUFFER;
3079 else
3080 return NT_STATUS_NO_PROBLEMO;
3083 /********************************************************************
3084 * handle enumeration of printers at level 1
3085 ********************************************************************/
3086 static uint32 enumprinters_level1( uint32 flags, fstring name,
3087 NEW_BUFFER *buffer, uint32 offered,
3088 uint32 *needed, uint32 *returned)
3090 /* Not all the flags are equals */
3092 if (flags & PRINTER_ENUM_LOCAL)
3093 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3095 if (flags & PRINTER_ENUM_NAME)
3096 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3098 if (flags & PRINTER_ENUM_REMOTE)
3099 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3101 if (flags & PRINTER_ENUM_NETWORK)
3102 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3104 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
3107 /********************************************************************
3108 * handle enumeration of printers at level 2
3109 ********************************************************************/
3110 static uint32 enumprinters_level2( uint32 flags, fstring servername,
3111 NEW_BUFFER *buffer, uint32 offered,
3112 uint32 *needed, uint32 *returned)
3114 fstring temp;
3116 fstrcpy(temp, "\\\\");
3117 fstrcat(temp, global_myname);
3119 if (flags & PRINTER_ENUM_LOCAL) {
3120 if (strequal(servername, temp))
3121 return enum_all_printers_info_2(buffer, offered, needed, returned);
3122 else
3123 return enum_all_printers_info_2(buffer, offered, needed, returned);
3126 if (flags & PRINTER_ENUM_NAME) {
3127 if (strequal(servername, temp))
3128 return enum_all_printers_info_2(buffer, offered, needed, returned);
3129 else
3130 return ERROR_INVALID_NAME;
3133 if (flags & PRINTER_ENUM_REMOTE)
3134 return ERROR_INVALID_LEVEL;
3136 return NT_STATUS_NO_PROBLEMO;
3139 /********************************************************************
3140 * handle enumeration of printers at level 5
3141 ********************************************************************/
3142 static uint32 enumprinters_level5( uint32 flags, fstring servername,
3143 NEW_BUFFER *buffer, uint32 offered,
3144 uint32 *needed, uint32 *returned)
3146 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3147 return NT_STATUS_NO_PROBLEMO;
3150 /********************************************************************
3151 * api_spoolss_enumprinters
3153 * called from api_spoolss_enumprinters (see this to understand)
3154 ********************************************************************/
3156 uint32 _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3158 uint32 flags = q_u->flags;
3159 UNISTR2 *servername = &q_u->servername;
3160 uint32 level = q_u->level;
3161 NEW_BUFFER *buffer = NULL;
3162 uint32 offered = q_u->offered;
3163 uint32 *needed = &r_u->needed;
3164 uint32 *returned = &r_u->returned;
3166 fstring name;
3168 /* that's an [in out] buffer */
3169 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3170 buffer = r_u->buffer;
3172 DEBUG(4,("_spoolss_enumprinters\n"));
3174 *needed=0;
3175 *returned=0;
3178 * Level 1:
3179 * flags==PRINTER_ENUM_NAME
3180 * if name=="" then enumerates all printers
3181 * if name!="" then enumerate the printer
3182 * flags==PRINTER_ENUM_REMOTE
3183 * name is NULL, enumerate printers
3184 * Level 2: name!="" enumerates printers, name can't be NULL
3185 * Level 3: doesn't exist
3186 * Level 4: does a local registry lookup
3187 * Level 5: same as Level 2
3190 unistr2_to_ascii(name, servername, sizeof(name)-1);
3191 strupper(name);
3193 switch (level) {
3194 case 1:
3195 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3196 case 2:
3197 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3198 case 5:
3199 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3200 case 3:
3201 case 4:
3202 default:
3203 return ERROR_INVALID_LEVEL;
3207 /****************************************************************************
3208 ****************************************************************************/
3209 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3211 PRINTER_INFO_0 *printer=NULL;
3213 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3214 return ERROR_NOT_ENOUGH_MEMORY;
3216 construct_printer_info_0(printer, snum);
3218 /* check the required size. */
3219 *needed += spoolss_size_printer_info_0(printer);
3221 if (!alloc_buffer_size(buffer, *needed)) {
3222 safe_free(printer);
3223 return ERROR_INSUFFICIENT_BUFFER;
3226 /* fill the buffer with the structures */
3227 smb_io_printer_info_0("", buffer, printer, 0);
3229 /* clear memory */
3230 safe_free(printer);
3232 if (*needed > offered) {
3233 return ERROR_INSUFFICIENT_BUFFER;
3235 else
3236 return NT_STATUS_NO_PROBLEMO;
3239 /****************************************************************************
3240 ****************************************************************************/
3241 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3243 PRINTER_INFO_1 *printer=NULL;
3245 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3246 return ERROR_NOT_ENOUGH_MEMORY;
3248 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3250 /* check the required size. */
3251 *needed += spoolss_size_printer_info_1(printer);
3253 if (!alloc_buffer_size(buffer, *needed)) {
3254 safe_free(printer);
3255 return ERROR_INSUFFICIENT_BUFFER;
3258 /* fill the buffer with the structures */
3259 smb_io_printer_info_1("", buffer, printer, 0);
3261 /* clear memory */
3262 safe_free(printer);
3264 if (*needed > offered) {
3265 return ERROR_INSUFFICIENT_BUFFER;
3267 else
3268 return NT_STATUS_NO_PROBLEMO;
3271 /****************************************************************************
3272 ****************************************************************************/
3273 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3275 PRINTER_INFO_2 *printer=NULL;
3277 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3278 return ERROR_NOT_ENOUGH_MEMORY;
3280 construct_printer_info_2(printer, snum);
3282 /* check the required size. */
3283 *needed += spoolss_size_printer_info_2(printer);
3285 if (!alloc_buffer_size(buffer, *needed)) {
3286 free_printer_info_2(printer);
3287 return ERROR_INSUFFICIENT_BUFFER;
3290 /* fill the buffer with the structures */
3291 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3292 free_printer_info_2(printer);
3293 return ERROR_NOT_ENOUGH_MEMORY;
3296 /* clear memory */
3297 free_printer_info_2(printer);
3299 if (*needed > offered) {
3300 return ERROR_INSUFFICIENT_BUFFER;
3302 else
3303 return NT_STATUS_NO_PROBLEMO;
3306 /****************************************************************************
3307 ****************************************************************************/
3308 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3310 PRINTER_INFO_3 *printer=NULL;
3312 if (!construct_printer_info_3(&printer, snum))
3313 return ERROR_NOT_ENOUGH_MEMORY;
3315 /* check the required size. */
3316 *needed += spoolss_size_printer_info_3(printer);
3318 if (!alloc_buffer_size(buffer, *needed)) {
3319 free_printer_info_3(printer);
3320 return ERROR_INSUFFICIENT_BUFFER;
3323 /* fill the buffer with the structures */
3324 smb_io_printer_info_3("", buffer, printer, 0);
3326 /* clear memory */
3327 free_printer_info_3(printer);
3329 if (*needed > offered) {
3330 return ERROR_INSUFFICIENT_BUFFER;
3332 else
3333 return NT_STATUS_NO_PROBLEMO;
3336 /****************************************************************************
3337 ****************************************************************************/
3339 uint32 _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3341 POLICY_HND *handle = &q_u->handle;
3342 uint32 level = q_u->level;
3343 NEW_BUFFER *buffer = NULL;
3344 uint32 offered = q_u->offered;
3345 uint32 *needed = &r_u->needed;
3347 int snum;
3349 /* that's an [in out] buffer */
3350 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3351 buffer = r_u->buffer;
3353 *needed=0;
3355 if (!get_printer_snum(p, handle, &snum))
3356 return ERROR_INVALID_HANDLE;
3358 switch (level) {
3359 case 0:
3360 return getprinter_level_0(snum, buffer, offered, needed);
3361 case 1:
3362 return getprinter_level_1(snum, buffer, offered, needed);
3363 case 2:
3364 return getprinter_level_2(snum, buffer, offered, needed);
3365 case 3:
3366 return getprinter_level_3(snum, buffer, offered, needed);
3367 default:
3368 return ERROR_INVALID_LEVEL;
3372 /********************************************************************
3373 * fill a DRIVER_INFO_1 struct
3374 ********************************************************************/
3375 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3377 init_unistr( &info->name, driver.info_3->name);
3380 /********************************************************************
3381 * construct_printer_driver_info_1
3382 ********************************************************************/
3383 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3385 NT_PRINTER_INFO_LEVEL *printer = NULL;
3386 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3388 ZERO_STRUCT(driver);
3390 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3391 return ERROR_INVALID_PRINTER_NAME;
3393 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3394 return ERROR_UNKNOWN_PRINTER_DRIVER;
3396 fill_printer_driver_info_1(info, driver, servername, architecture);
3398 free_a_printer(&printer,2);
3400 return NT_STATUS_NO_PROBLEMO;
3403 /********************************************************************
3404 * construct_printer_driver_info_2
3405 * fill a printer_info_2 struct
3406 ********************************************************************/
3407 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3409 pstring temp;
3411 info->version=driver.info_3->cversion;
3413 init_unistr( &info->name, driver.info_3->name );
3414 init_unistr( &info->architecture, driver.info_3->environment );
3417 if (strlen(driver.info_3->driverpath)) {
3418 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3419 init_unistr( &info->driverpath, temp );
3420 } else
3421 init_unistr( &info->driverpath, "" );
3423 if (strlen(driver.info_3->datafile)) {
3424 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3425 init_unistr( &info->datafile, temp );
3426 } else
3427 init_unistr( &info->datafile, "" );
3429 if (strlen(driver.info_3->configfile)) {
3430 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3431 init_unistr( &info->configfile, temp );
3432 } else
3433 init_unistr( &info->configfile, "" );
3436 /********************************************************************
3437 * construct_printer_driver_info_2
3438 * fill a printer_info_2 struct
3439 ********************************************************************/
3440 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3442 NT_PRINTER_INFO_LEVEL *printer = NULL;
3443 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3445 ZERO_STRUCT(printer);
3446 ZERO_STRUCT(driver);
3448 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3449 return ERROR_INVALID_PRINTER_NAME;
3451 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3452 return ERROR_UNKNOWN_PRINTER_DRIVER;
3454 fill_printer_driver_info_2(info, driver, servername);
3456 free_a_printer(&printer,2);
3458 return NT_STATUS_NO_PROBLEMO;
3461 /********************************************************************
3462 * copy a strings array and convert to UNICODE
3464 * convert an array of ascii string to a UNICODE string
3465 ********************************************************************/
3466 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3468 int i=0;
3469 int j=0;
3470 char *v;
3471 pstring line;
3473 DEBUG(6,("init_unistr_array\n"));
3474 *uni_array=NULL;
3476 while (1) {
3477 if (char_array == NULL)
3478 v = "";
3479 else {
3480 v = char_array[i];
3481 if (!v) v = ""; /* hack to handle null lists */
3483 if (strlen(v) == 0) break;
3484 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3485 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3486 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3487 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3488 return;
3490 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3491 i++;
3494 if (*uni_array) {
3495 (*uni_array)[j]=0x0000;
3498 DEBUGADD(6,("last one:done\n"));
3501 /********************************************************************
3502 * construct_printer_info_3
3503 * fill a printer_info_3 struct
3504 ********************************************************************/
3505 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3507 pstring temp;
3509 ZERO_STRUCTP(info);
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 );
3519 } else
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 );
3525 } else
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 );
3531 } else
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 );
3537 } else
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);
3547 /********************************************************************
3548 * construct_printer_info_3
3549 * fill a printer_info_3 struct
3550 ********************************************************************/
3551 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3553 NT_PRINTER_INFO_LEVEL *printer = NULL;
3554 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3555 uint32 status=0;
3556 ZERO_STRUCT(driver);
3558 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3559 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3560 if (status != 0)
3561 return ERROR_INVALID_PRINTER_NAME;
3563 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3564 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3565 if (status != 0) {
3566 free_a_printer(&printer,2);
3567 return ERROR_UNKNOWN_PRINTER_DRIVER;
3570 fill_printer_driver_info_3(info, driver, servername);
3572 free_a_printer(&printer,2);
3574 return NT_STATUS_NO_PROBLEMO;
3577 /********************************************************************
3578 * construct_printer_info_6
3579 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3580 ********************************************************************/
3582 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3584 pstring temp;
3585 fstring nullstr;
3587 ZERO_STRUCTP(info);
3588 memset(&nullstr, '\0', sizeof(fstring));
3590 info->version=driver.info_3->cversion;
3592 init_unistr( &info->name, driver.info_3->name );
3593 init_unistr( &info->architecture, driver.info_3->environment );
3595 if (strlen(driver.info_3->driverpath)) {
3596 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3597 init_unistr( &info->driverpath, temp );
3598 } else
3599 init_unistr( &info->driverpath, "" );
3601 if (strlen(driver.info_3->datafile)) {
3602 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3603 init_unistr( &info->datafile, temp );
3604 } else
3605 init_unistr( &info->datafile, "" );
3607 if (strlen(driver.info_3->configfile)) {
3608 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3609 init_unistr( &info->configfile, temp );
3610 } else
3611 init_unistr( &info->configfile, "" );
3613 if (strlen(driver.info_3->helpfile)) {
3614 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3615 init_unistr( &info->helpfile, temp );
3616 } else
3617 init_unistr( &info->helpfile, "" );
3619 init_unistr( &info->monitorname, driver.info_3->monitorname );
3620 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3622 info->dependentfiles=NULL;
3623 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3625 info->previousdrivernames=NULL;
3626 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3628 info->driver_date.low=0;
3629 info->driver_date.high=0;
3631 info->padding=0;
3632 info->driver_version_low=0;
3633 info->driver_version_high=0;
3635 init_unistr( &info->mfgname, "");
3636 init_unistr( &info->oem_url, "");
3637 init_unistr( &info->hardware_id, "");
3638 init_unistr( &info->provider, "");
3641 /********************************************************************
3642 * construct_printer_info_6
3643 * fill a printer_info_6 struct
3644 ********************************************************************/
3645 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3647 NT_PRINTER_INFO_LEVEL *printer = NULL;
3648 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3649 uint32 status=0;
3650 ZERO_STRUCT(driver);
3652 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3653 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3654 if (status != 0)
3655 return ERROR_INVALID_PRINTER_NAME;
3657 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3658 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3659 if (status != 0) {
3661 * Is this a W2k client ?
3664 if (version < 3) {
3665 free_a_printer(&printer,2);
3666 return ERROR_UNKNOWN_PRINTER_DRIVER;
3669 /* Yes - try again with a WinNT driver. */
3670 version = 2;
3671 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3672 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3673 if (status != 0) {
3674 free_a_printer(&printer,2);
3675 return ERROR_UNKNOWN_PRINTER_DRIVER;
3679 fill_printer_driver_info_6(info, driver, servername);
3681 free_a_printer(&printer,2);
3683 return NT_STATUS_NO_PROBLEMO;
3686 /****************************************************************************
3687 ****************************************************************************/
3689 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3691 safe_free(info->dependentfiles);
3694 /****************************************************************************
3695 ****************************************************************************/
3697 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3699 safe_free(info->dependentfiles);
3703 /****************************************************************************
3704 ****************************************************************************/
3705 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3707 DRIVER_INFO_1 *info=NULL;
3708 uint32 status;
3710 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3711 return ERROR_NOT_ENOUGH_MEMORY;
3713 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3714 if (status != NT_STATUS_NO_PROBLEMO) {
3715 safe_free(info);
3716 return status;
3719 /* check the required size. */
3720 *needed += spoolss_size_printer_driver_info_1(info);
3722 if (!alloc_buffer_size(buffer, *needed)) {
3723 safe_free(info);
3724 return ERROR_INSUFFICIENT_BUFFER;
3727 /* fill the buffer with the structures */
3728 smb_io_printer_driver_info_1("", buffer, info, 0);
3730 /* clear memory */
3731 safe_free(info);
3733 if (*needed > offered)
3734 return ERROR_INSUFFICIENT_BUFFER;
3735 else
3736 return NT_STATUS_NO_PROBLEMO;
3739 /****************************************************************************
3740 ****************************************************************************/
3741 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3743 DRIVER_INFO_2 *info=NULL;
3744 uint32 status;
3746 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3747 return ERROR_NOT_ENOUGH_MEMORY;
3749 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3750 if (status != NT_STATUS_NO_PROBLEMO) {
3751 safe_free(info);
3752 return status;
3755 /* check the required size. */
3756 *needed += spoolss_size_printer_driver_info_2(info);
3758 if (!alloc_buffer_size(buffer, *needed)) {
3759 safe_free(info);
3760 return ERROR_INSUFFICIENT_BUFFER;
3763 /* fill the buffer with the structures */
3764 smb_io_printer_driver_info_2("", buffer, info, 0);
3766 /* clear memory */
3767 safe_free(info);
3769 if (*needed > offered)
3770 return ERROR_INSUFFICIENT_BUFFER;
3771 else
3772 return NT_STATUS_NO_PROBLEMO;
3775 /****************************************************************************
3776 ****************************************************************************/
3777 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3779 DRIVER_INFO_3 info;
3780 uint32 status;
3782 ZERO_STRUCT(info);
3784 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3785 if (status != NT_STATUS_NO_PROBLEMO) {
3786 return status;
3789 /* check the required size. */
3790 *needed += spoolss_size_printer_driver_info_3(&info);
3792 if (!alloc_buffer_size(buffer, *needed)) {
3793 free_printer_driver_info_3(&info);
3794 return ERROR_INSUFFICIENT_BUFFER;
3797 /* fill the buffer with the structures */
3798 smb_io_printer_driver_info_3("", buffer, &info, 0);
3800 free_printer_driver_info_3(&info);
3802 if (*needed > offered)
3803 return ERROR_INSUFFICIENT_BUFFER;
3804 else
3805 return NT_STATUS_NO_PROBLEMO;
3808 /****************************************************************************
3809 ****************************************************************************/
3810 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3812 DRIVER_INFO_6 info;
3813 uint32 status;
3815 ZERO_STRUCT(info);
3817 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3818 if (status != NT_STATUS_NO_PROBLEMO) {
3819 return status;
3822 /* check the required size. */
3823 *needed += spoolss_size_printer_driver_info_6(&info);
3825 if (!alloc_buffer_size(buffer, *needed)) {
3826 free_printer_driver_info_6(&info);
3827 return ERROR_INSUFFICIENT_BUFFER;
3830 /* fill the buffer with the structures */
3831 smb_io_printer_driver_info_6("", buffer, &info, 0);
3833 free_printer_driver_info_6(&info);
3835 if (*needed > offered)
3836 return ERROR_INSUFFICIENT_BUFFER;
3837 else
3838 return NT_STATUS_NO_PROBLEMO;
3841 /****************************************************************************
3842 ****************************************************************************/
3844 uint32 _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3846 POLICY_HND *handle = &q_u->handle;
3847 UNISTR2 *uni_arch = &q_u->architecture;
3848 uint32 level = q_u->level;
3849 uint32 clientmajorversion = q_u->clientmajorversion;
3850 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3851 NEW_BUFFER *buffer = NULL;
3852 uint32 offered = q_u->offered;
3853 uint32 *needed = &r_u->needed;
3854 uint32 *servermajorversion = &r_u->servermajorversion;
3855 uint32 *serverminorversion = &r_u->serverminorversion;
3857 fstring servername;
3858 fstring architecture;
3859 int snum;
3861 /* that's an [in out] buffer */
3862 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3863 buffer = r_u->buffer;
3865 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3867 *needed=0;
3868 *servermajorversion=0;
3869 *serverminorversion=0;
3871 pstrcpy(servername, global_myname);
3872 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3874 if (!get_printer_snum(p, handle, &snum))
3875 return ERROR_INVALID_HANDLE;
3877 switch (level) {
3878 case 1:
3879 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3880 case 2:
3881 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3882 case 3:
3883 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3884 case 6:
3885 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3886 default:
3887 return ERROR_INVALID_LEVEL;
3891 /****************************************************************************
3892 ****************************************************************************/
3894 uint32 _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
3896 POLICY_HND *handle = &q_u->handle;
3898 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3900 if (Printer) {
3901 Printer->page_started=True;
3902 return 0x0;
3905 DEBUG(3,("Error in startpageprinter printer handle\n"));
3906 return ERROR_INVALID_HANDLE;
3909 /****************************************************************************
3910 ****************************************************************************/
3912 uint32 _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
3914 POLICY_HND *handle = &q_u->handle;
3916 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3918 if (!Printer) {
3919 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3920 return ERROR_INVALID_HANDLE;
3923 Printer->page_started=False;
3925 return NT_STATUS_NO_PROBLEMO;
3928 /********************************************************************
3929 * api_spoolss_getprinter
3930 * called from the spoolss dispatcher
3932 ********************************************************************/
3934 uint32 _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
3936 POLICY_HND *handle = &q_u->handle;
3937 /* uint32 level = q_u->doc_info_container.level; - notused. */
3938 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
3939 uint32 *jobid = &r_u->jobid;
3941 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3942 int snum;
3943 pstring jobname;
3944 fstring datatype;
3945 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3946 struct current_user user;
3948 if (!Printer) {
3949 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3950 return ERROR_INVALID_HANDLE;
3953 get_current_user(&user, p);
3956 * a nice thing with NT is it doesn't listen to what you tell it.
3957 * when asked to send _only_ RAW datas, it tries to send datas
3958 * in EMF format.
3960 * So I add checks like in NT Server ...
3962 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3963 * there's a bug in NT client-side code, so we'll fix it in the
3964 * server-side code. *nnnnnggggh!*
3967 if (info_1->p_datatype != 0) {
3968 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3969 if (strcmp(datatype, "RAW") != 0) {
3970 (*jobid)=0;
3971 return ERROR_INVALID_DATATYPE;
3975 /* get the share number of the printer */
3976 if (!get_printer_snum(p, handle, &snum)) {
3977 return ERROR_INVALID_HANDLE;
3980 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3982 Printer->jobid = print_job_start(&user, snum, jobname);
3984 /* An error occured in print_job_start() so return an appropriate
3985 NT error code. */
3987 if (Printer->jobid == -1) {
3988 return map_nt_error_from_unix(errno);
3991 Printer->document_started=True;
3992 (*jobid) = Printer->jobid;
3994 return 0x0;
3997 /********************************************************************
3998 * api_spoolss_getprinter
3999 * called from the spoolss dispatcher
4001 ********************************************************************/
4003 uint32 _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4005 POLICY_HND *handle = &q_u->handle;
4007 return _spoolss_enddocprinter_internal(p, handle);
4010 /****************************************************************************
4011 ****************************************************************************/
4013 uint32 _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4015 POLICY_HND *handle = &q_u->handle;
4016 uint32 buffer_size = q_u->buffer_size;
4017 uint8 *buffer = q_u->buffer;
4018 uint32 *buffer_written = &q_u->buffer_size2;
4020 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4022 if (!Printer) {
4023 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
4024 r_u->buffer_written = q_u->buffer_size2;
4025 return ERROR_INVALID_HANDLE;
4028 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4031 r_u->buffer_written = q_u->buffer_size2;
4033 return 0x0;
4036 /********************************************************************
4037 * api_spoolss_getprinter
4038 * called from the spoolss dispatcher
4040 ********************************************************************/
4041 static uint32 control_printer(POLICY_HND *handle, uint32 command,
4042 pipes_struct *p)
4044 struct current_user user;
4045 int snum, errcode = ERROR_INVALID_FUNCTION;
4046 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4048 get_current_user(&user, p);
4050 if (!Printer) {
4051 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4052 return ERROR_INVALID_HANDLE;
4055 if (!get_printer_snum(p, handle, &snum))
4056 return ERROR_INVALID_HANDLE;
4058 switch (command) {
4059 case PRINTER_CONTROL_PAUSE:
4060 if (print_queue_pause(&user, snum, &errcode)) {
4061 errcode = 0;
4063 break;
4064 case PRINTER_CONTROL_RESUME:
4065 case PRINTER_CONTROL_UNPAUSE:
4066 if (print_queue_resume(&user, snum, &errcode)) {
4067 errcode = 0;
4069 break;
4070 case PRINTER_CONTROL_PURGE:
4071 if (print_queue_purge(&user, snum, &errcode)) {
4072 errcode = 0;
4074 break;
4075 default:
4076 return ERROR_INVALID_LEVEL;
4079 return errcode;
4082 /********************************************************************
4083 * api_spoolss_abortprinter
4084 ********************************************************************/
4086 uint32 _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4088 POLICY_HND *handle = &q_u->handle;
4090 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4093 /********************************************************************
4094 * called by spoolss_api_setprinter
4095 * when updating a printer description
4096 ********************************************************************/
4097 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
4098 const SPOOL_PRINTER_INFO_LEVEL *info,
4099 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4101 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4102 struct current_user user;
4103 uint32 result;
4104 int snum;
4106 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4108 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4109 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4110 OUR_HANDLE(handle)));
4112 result = ERROR_INVALID_HANDLE;
4113 goto done;
4116 /* NT seems to like setting the security descriptor even though
4117 nothing may have actually changed. This causes annoying
4118 dialog boxes when the user doesn't have permission to change
4119 the security descriptor. */
4121 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4123 if (DEBUGLEVEL >= 10) {
4124 SEC_ACL *the_acl;
4125 int i;
4127 the_acl = old_secdesc_ctr->sec->dacl;
4128 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4129 PRINTERNAME(snum), the_acl->num_aces));
4131 for (i = 0; i < the_acl->num_aces; i++) {
4132 fstring sid_str;
4134 sid_to_string(sid_str, &the_acl->ace[i].sid);
4136 DEBUG(10, ("%s 0x%08x\n", sid_str,
4137 the_acl->ace[i].info.mask));
4140 the_acl = secdesc_ctr->sec->dacl;
4142 if (the_acl) {
4143 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4144 PRINTERNAME(snum), the_acl->num_aces));
4146 for (i = 0; i < the_acl->num_aces; i++) {
4147 fstring sid_str;
4149 sid_to_string(sid_str, &the_acl->ace[i].sid);
4151 DEBUG(10, ("%s 0x%08x\n", sid_str,
4152 the_acl->ace[i].info.mask));
4154 } else {
4155 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4159 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4161 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4162 result = NT_STATUS_NO_PROBLEMO;
4163 goto done;
4166 /* Work out which user is performing the operation */
4168 get_current_user(&user, p);
4170 /* Check the user has permissions to change the security
4171 descriptor. By experimentation with two NT machines, the user
4172 requires Full Access to the printer to change security
4173 information. */
4175 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4176 result = ERROR_ACCESS_DENIED;
4177 goto done;
4180 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4182 done:
4184 return result;
4187 /********************************************************************
4188 Do Samba sanity checks on a printer info struct.
4189 this has changed purpose: it now "canonicalises" printer
4190 info from a client rather than just checking it is correct
4191 ********************************************************************/
4193 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4195 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4196 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4198 /* we force some elements to "correct" values */
4199 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4200 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4201 global_myname, lp_servicename(snum));
4202 fstrcpy(info->sharename, lp_servicename(snum));
4203 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4204 | PRINTER_ATTRIBUTE_LOCAL \
4205 | PRINTER_ATTRIBUTE_RAW_ONLY \
4206 | PRINTER_ATTRIBUTE_QUEUED ;
4208 return True;
4211 /****************************************************************************
4212 ****************************************************************************/
4213 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4215 char *cmd = lp_addprinter_cmd();
4216 char **qlines;
4217 pstring command;
4218 pstring driverlocation;
4219 int numlines;
4220 int ret;
4221 int fd;
4223 /* build driver path... only 9X architecture is needed for legacy reasons */
4224 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4225 global_myname);
4226 /* change \ to \\ for the shell */
4227 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4229 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4230 cmd, printer->info_2->printername, printer->info_2->sharename,
4231 printer->info_2->portname, printer->info_2->drivername,
4232 printer->info_2->location, driverlocation);
4234 /* Convert script args to unix-codepage */
4235 dos_to_unix(command, True);
4236 DEBUG(10,("Running [%s]\n", command));
4237 ret = smbrun(command, &fd);
4238 DEBUGADD(10,("returned [%d]\n", ret));
4240 if ( ret != 0 ) {
4241 if (fd != -1)
4242 close(fd);
4243 return False;
4246 numlines = 0;
4247 /* Get lines and convert them back to dos-codepage */
4248 qlines = fd_lines_load(fd, &numlines, True);
4249 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4250 close(fd);
4252 if(numlines) {
4253 /* Set the portname to what the script says the portname should be. */
4254 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4255 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4257 /* Send SIGHUP to process group... is there a better way? */
4258 kill(0, SIGHUP);
4259 add_all_printers();
4262 file_lines_free(qlines);
4263 return True;
4266 /* Return true if two devicemodes are equal */
4268 #define DEVMODE_CHECK_INT(field) \
4269 if (d1->field != d2->field) { \
4270 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4271 d1->field, d2->field)); \
4272 return False; \
4275 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4277 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4279 if (!d1 ^ !d2) {
4280 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4281 return False; /* if either is exclusively NULL are not equal */
4284 if (!strequal(d1->devicename, d2->devicename)) {
4285 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4286 return False;
4289 if (!strequal(d1->formname, d2->formname)) {
4290 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4291 return False;
4294 DEVMODE_CHECK_INT(specversion);
4295 DEVMODE_CHECK_INT(driverversion);
4296 DEVMODE_CHECK_INT(driverextra);
4297 DEVMODE_CHECK_INT(orientation);
4298 DEVMODE_CHECK_INT(papersize);
4299 DEVMODE_CHECK_INT(paperlength);
4300 DEVMODE_CHECK_INT(paperwidth);
4301 DEVMODE_CHECK_INT(scale);
4302 DEVMODE_CHECK_INT(copies);
4303 DEVMODE_CHECK_INT(defaultsource);
4304 DEVMODE_CHECK_INT(printquality);
4305 DEVMODE_CHECK_INT(color);
4306 DEVMODE_CHECK_INT(duplex);
4307 DEVMODE_CHECK_INT(yresolution);
4308 DEVMODE_CHECK_INT(ttoption);
4309 DEVMODE_CHECK_INT(collate);
4310 DEVMODE_CHECK_INT(logpixels);
4312 DEVMODE_CHECK_INT(fields);
4313 DEVMODE_CHECK_INT(bitsperpel);
4314 DEVMODE_CHECK_INT(pelswidth);
4315 DEVMODE_CHECK_INT(pelsheight);
4316 DEVMODE_CHECK_INT(displayflags);
4317 DEVMODE_CHECK_INT(displayfrequency);
4318 DEVMODE_CHECK_INT(icmmethod);
4319 DEVMODE_CHECK_INT(icmintent);
4320 DEVMODE_CHECK_INT(mediatype);
4321 DEVMODE_CHECK_INT(dithertype);
4322 DEVMODE_CHECK_INT(reserved1);
4323 DEVMODE_CHECK_INT(reserved2);
4324 DEVMODE_CHECK_INT(panningwidth);
4325 DEVMODE_CHECK_INT(panningheight);
4327 /* compare the private data if it exists */
4328 if (!d1->driverextra && !d2->driverextra) goto equal;
4331 DEVMODE_CHECK_INT(driverextra);
4333 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4334 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4335 return False;
4338 equal:
4339 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4340 return True;
4343 /* Return true if two NT_PRINTER_PARAM structures are equal */
4345 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4346 NT_PRINTER_PARAM *p2)
4348 if (!p1 && !p2) goto equal;
4350 if ((!p1 && p2) || (p1 && !p2)) {
4351 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4352 return False;
4355 /* Compare lists of printer parameters */
4357 while (p1) {
4358 BOOL found = False;
4359 NT_PRINTER_PARAM *q = p1;
4361 /* Find the parameter in the second structure */
4363 while(q) {
4365 if (strequal(p1->value, q->value)) {
4367 if (p1->type != q->type) {
4368 DEBUG(10, ("nt_printer_param_equal():"
4369 "types for %s differ (%d != %d)\n",
4370 p1->value, p1->type,
4371 q->type));
4372 break;
4375 if (p1->data_len != q->data_len) {
4376 DEBUG(10, ("nt_printer_param_equal():"
4377 "len for %s differs (%d != %d)\n",
4378 p1->value, p1->data_len,
4379 q->data_len));
4380 break;
4383 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4384 found = True;
4385 } else {
4386 DEBUG(10, ("nt_printer_param_equal():"
4387 "data for %s differs\n", p1->value));
4390 break;
4393 q = q->next;
4396 if (!found) {
4397 DEBUG(10, ("nt_printer_param_equal(): param %s "
4398 "does not exist\n", p1->value));
4399 return False;
4402 p1 = p1->next;
4405 equal:
4407 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4408 return True;
4411 /********************************************************************
4412 * Called by update_printer when trying to work out whether to
4413 * actually update printer info.
4414 ********************************************************************/
4416 #define PI_CHECK_INT(field) \
4417 if (pi1->field != pi2->field) { \
4418 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4419 pi1->field, pi2->field)); \
4420 return False; \
4423 #define PI_CHECK_STR(field) \
4424 if (!strequal(pi1->field, pi2->field)) { \
4425 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4426 pi1->field, pi2->field)); \
4427 return False; \
4430 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4431 NT_PRINTER_INFO_LEVEL *p2)
4433 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4435 /* Trivial conditions */
4437 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4438 goto equal;
4441 if ((!p1 && p2) || (p1 && !p2) ||
4442 (!p1->info_2 && p2->info_2) ||
4443 (p1->info_2 && !p2->info_2)) {
4444 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4445 "differ\n"));
4446 return False;
4449 /* Compare two nt_printer_info_level structures. Don't compare
4450 status or cjobs as they seem to have something to do with the
4451 printer queue. */
4453 pi1 = p1->info_2;
4454 pi2 = p2->info_2;
4456 /* Don't check the attributes as we stomp on the value in
4457 check_printer_ok() anyway. */
4459 #if 0
4460 PI_CHECK_INT(attributes);
4461 #endif
4463 PI_CHECK_INT(priority);
4464 PI_CHECK_INT(default_priority);
4465 PI_CHECK_INT(starttime);
4466 PI_CHECK_INT(untiltime);
4467 PI_CHECK_INT(averageppm);
4469 /* Yuck - don't check the printername or servername as the
4470 add_a_printer() code plays games with them. You can't
4471 change the printername or the sharename through this interface
4472 in Samba. */
4474 PI_CHECK_STR(sharename);
4475 PI_CHECK_STR(portname);
4476 PI_CHECK_STR(drivername);
4477 PI_CHECK_STR(comment);
4478 PI_CHECK_STR(location);
4480 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4481 return False;
4484 PI_CHECK_STR(sepfile);
4485 PI_CHECK_STR(printprocessor);
4486 PI_CHECK_STR(datatype);
4487 PI_CHECK_STR(parameters);
4489 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4490 return False;
4493 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4494 return False;
4497 PI_CHECK_INT(changeid);
4498 PI_CHECK_INT(c_setprinter);
4499 PI_CHECK_INT(setuptime);
4501 equal:
4502 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4503 return True;
4506 /********************************************************************
4507 * called by spoolss_api_setprinter
4508 * when updating a printer description
4509 ********************************************************************/
4511 static uint32 update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4512 const SPOOL_PRINTER_INFO_LEVEL *info,
4513 DEVICEMODE *devmode)
4515 int snum;
4516 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4517 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4518 uint32 result;
4520 DEBUG(8,("update_printer\n"));
4522 result = NT_STATUS_NO_PROBLEMO;
4524 if (level!=2) {
4525 DEBUG(0,("Send a mail to samba@samba.org\n"));
4526 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4527 result = ERROR_INVALID_LEVEL;
4528 goto done;
4531 if (!Printer) {
4532 result = ERROR_INVALID_HANDLE;
4533 goto done;
4536 if (!get_printer_snum(p, handle, &snum)) {
4537 result = ERROR_INVALID_HANDLE;
4538 goto done;
4541 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4542 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4543 result = ERROR_INVALID_HANDLE;
4544 goto done;
4547 DEBUGADD(8,("Converting info_2 struct\n"));
4550 * convert_printer_info converts the incoming
4551 * info from the client and overwrites the info
4552 * just read from the tdb in the pointer 'printer'.
4555 convert_printer_info(info, printer, level);
4557 if (info->info_2->devmode_ptr != 0) {
4558 /* we have a valid devmode
4559 convert it and link it*/
4561 DEBUGADD(8,("Converting the devicemode struct\n"));
4562 if (!convert_devicemode(printer->info_2->printername, devmode,
4563 &printer->info_2->devmode)) {
4564 result = ERROR_NOT_ENOUGH_MEMORY;
4565 goto done;
4569 /* Do sanity check on the requested changes for Samba */
4571 if (!check_printer_ok(printer->info_2, snum)) {
4572 result = ERROR_INVALID_PARAMETER;
4573 goto done;
4576 /* NT likes to call this function even though nothing has actually
4577 changed. Check this so the user doesn't end up with an
4578 annoying permission denied dialog box. */
4580 if (nt_printer_info_level_equal(printer, old_printer)) {
4581 DEBUG(3, ("printer info has not changed\n"));
4582 result = NT_STATUS_NO_PROBLEMO;
4583 goto done;
4586 /* Check calling user has permission to update printer description */
4588 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4589 DEBUG(3, ("printer property change denied by security "
4590 "descriptor\n"));
4591 result = ERROR_ACCESS_DENIED;
4592 goto done;
4595 /* Call addprinter hook */
4597 if (*lp_addprinter_cmd() )
4598 if ( !add_printer_hook(printer) ) {
4599 result = ERROR_ACCESS_DENIED;
4600 goto done;
4603 /* Update printer info */
4605 if (add_a_printer(*printer, 2)!=0) {
4606 /* I don't really know what to return here !!! */
4607 result = ERROR_ACCESS_DENIED;
4608 goto done;
4611 done:
4612 free_a_printer(&printer, 2);
4613 free_a_printer(&old_printer, 2);
4615 srv_spoolss_sendnotify(p, handle);
4617 return result;
4620 /****************************************************************************
4621 ****************************************************************************/
4623 uint32 _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4625 POLICY_HND *handle = &q_u->handle;
4626 uint32 level = q_u->level;
4627 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4628 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4629 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4630 uint32 command = q_u->command;
4632 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4634 if (!Printer) {
4635 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4636 return ERROR_INVALID_HANDLE;
4639 /* check the level */
4640 switch (level) {
4641 case 0:
4642 return control_printer(handle, command, p);
4643 case 2:
4644 return update_printer(p, handle, level, info, devmode_ctr.devmode);
4645 case 3:
4646 return update_printer_sec(handle, level, info, p,
4647 secdesc_ctr);
4648 default:
4649 return ERROR_INVALID_LEVEL;
4653 /****************************************************************************
4654 ****************************************************************************/
4656 uint32 _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4658 POLICY_HND *handle = &q_u->handle;
4660 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4662 if (!Printer) {
4663 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4664 return ERROR_INVALID_HANDLE;
4667 if (Printer->notify.client_connected==True)
4668 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4670 Printer->notify.flags=0;
4671 Printer->notify.options=0;
4672 Printer->notify.localmachine[0]='\0';
4673 Printer->notify.printerlocal=0;
4674 if (Printer->notify.option)
4675 free_spool_notify_option(&Printer->notify.option);
4676 Printer->notify.client_connected=False;
4678 return NT_STATUS_NO_PROBLEMO;
4681 /****************************************************************************
4682 ****************************************************************************/
4684 uint32 _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4686 /* that's an [in out] buffer (despite appearences to the contrary) */
4687 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4689 r_u->needed = 0;
4690 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4691 returns for AddJob. AddJob
4692 must fail on non-local
4693 printers */
4696 /****************************************************************************
4697 ****************************************************************************/
4698 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4699 int position, int snum)
4701 pstring temp_name;
4703 struct tm *t;
4705 t=gmtime(&queue->time);
4706 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4708 job_info->jobid=queue->job;
4709 init_unistr(&job_info->printername, lp_servicename(snum));
4710 init_unistr(&job_info->machinename, temp_name);
4711 init_unistr(&job_info->username, queue->user);
4712 init_unistr(&job_info->document, queue->file);
4713 init_unistr(&job_info->datatype, "RAW");
4714 init_unistr(&job_info->text_status, "");
4715 job_info->status=nt_printj_status(queue->status);
4716 job_info->priority=queue->priority;
4717 job_info->position=position;
4718 job_info->totalpages=0;
4719 job_info->pagesprinted=0;
4721 make_systemtime(&job_info->submitted, t);
4724 /****************************************************************************
4725 ****************************************************************************/
4726 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4727 int position, int snum,
4728 NT_PRINTER_INFO_LEVEL *ntprinter)
4730 pstring temp_name;
4731 pstring chaine;
4732 struct tm *t;
4734 t=gmtime(&queue->time);
4735 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4737 job_info->jobid=queue->job;
4739 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4741 init_unistr(&job_info->printername, chaine);
4743 init_unistr(&job_info->machinename, temp_name);
4744 init_unistr(&job_info->username, queue->user);
4745 init_unistr(&job_info->document, queue->file);
4746 init_unistr(&job_info->notifyname, queue->user);
4747 init_unistr(&job_info->datatype, "RAW");
4748 init_unistr(&job_info->printprocessor, "winprint");
4749 init_unistr(&job_info->parameters, "");
4750 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4751 init_unistr(&job_info->text_status, "");
4753 /* and here the security descriptor */
4755 job_info->status=nt_printj_status(queue->status);
4756 job_info->priority=queue->priority;
4757 job_info->position=position;
4758 job_info->starttime=0;
4759 job_info->untiltime=0;
4760 job_info->totalpages=0;
4761 job_info->size=queue->size;
4762 make_systemtime(&(job_info->submitted), t);
4763 job_info->timeelapsed=0;
4764 job_info->pagesprinted=0;
4766 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4767 return False;
4770 return (True);
4773 /****************************************************************************
4774 Enumjobs at level 1.
4775 ****************************************************************************/
4776 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4777 NEW_BUFFER *buffer, uint32 offered,
4778 uint32 *needed, uint32 *returned)
4780 JOB_INFO_1 *info;
4781 int i;
4783 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4784 if (info==NULL) {
4785 safe_free(queue);
4786 *returned=0;
4787 return ERROR_NOT_ENOUGH_MEMORY;
4790 for (i=0; i<*returned; i++)
4791 fill_job_info_1(&info[i], &queue[i], i, snum);
4793 safe_free(queue);
4795 /* check the required size. */
4796 for (i=0; i<*returned; i++)
4797 (*needed) += spoolss_size_job_info_1(&info[i]);
4799 if (!alloc_buffer_size(buffer, *needed)) {
4800 safe_free(info);
4801 return ERROR_INSUFFICIENT_BUFFER;
4804 /* fill the buffer with the structures */
4805 for (i=0; i<*returned; i++)
4806 smb_io_job_info_1("", buffer, &info[i], 0);
4808 /* clear memory */
4809 safe_free(info);
4811 if (*needed > offered) {
4812 *returned=0;
4813 return ERROR_INSUFFICIENT_BUFFER;
4815 else
4816 return NT_STATUS_NO_PROBLEMO;
4819 /****************************************************************************
4820 Enumjobs at level 2.
4821 ****************************************************************************/
4822 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4823 NEW_BUFFER *buffer, uint32 offered,
4824 uint32 *needed, uint32 *returned)
4826 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4827 JOB_INFO_2 *info;
4828 int i;
4830 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4831 if (info==NULL) {
4832 *returned=0;
4833 return ERROR_NOT_ENOUGH_MEMORY;
4836 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4837 *returned = 0;
4838 return ERROR_NOT_ENOUGH_MEMORY;
4841 for (i=0; i<*returned; i++)
4842 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4844 free_a_printer(&ntprinter, 2);
4845 safe_free(queue);
4847 /* check the required size. */
4848 for (i=0; i<*returned; i++)
4849 (*needed) += spoolss_size_job_info_2(&info[i]);
4851 if (!alloc_buffer_size(buffer, *needed)) {
4852 safe_free(info);
4853 return ERROR_INSUFFICIENT_BUFFER;
4856 /* fill the buffer with the structures */
4857 for (i=0; i<*returned; i++)
4858 smb_io_job_info_2("", buffer, &info[i], 0);
4860 /* clear memory */
4861 for (i = 0; i < *returned; i++)
4862 free_job_info_2(&info[i]);
4864 free(info);
4866 if (*needed > offered) {
4867 *returned=0;
4868 return ERROR_INSUFFICIENT_BUFFER;
4870 else
4871 return NT_STATUS_NO_PROBLEMO;
4874 /****************************************************************************
4875 Enumjobs.
4876 ****************************************************************************/
4878 uint32 _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4880 POLICY_HND *handle = &q_u->handle;
4881 /* uint32 firstjob = q_u->firstjob; - notused. */
4882 /* uint32 numofjobs = q_u->numofjobs; - notused. */
4883 uint32 level = q_u->level;
4884 NEW_BUFFER *buffer = NULL;
4885 uint32 offered = q_u->offered;
4886 uint32 *needed = &r_u->needed;
4887 uint32 *returned = &r_u->returned;
4889 int snum;
4890 print_queue_struct *queue=NULL;
4891 print_status_struct prt_status;
4893 /* that's an [in out] buffer */
4894 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4895 buffer = r_u->buffer;
4897 DEBUG(4,("_spoolss_enumjobs\n"));
4899 ZERO_STRUCT(prt_status);
4901 *needed=0;
4902 *returned=0;
4904 if (!get_printer_snum(p, handle, &snum))
4905 return ERROR_INVALID_HANDLE;
4907 *returned = print_queue_status(snum, &queue, &prt_status);
4908 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4910 if (*returned == 0) {
4911 safe_free(queue);
4912 return NT_STATUS_NO_PROBLEMO;
4915 switch (level) {
4916 case 1:
4917 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4918 case 2:
4919 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4920 default:
4921 safe_free(queue);
4922 *returned=0;
4923 return ERROR_INVALID_LEVEL;
4927 /****************************************************************************
4928 ****************************************************************************/
4930 uint32 _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
4932 return 0x0;
4935 /****************************************************************************
4936 ****************************************************************************/
4938 uint32 _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
4940 POLICY_HND *handle = &q_u->handle;
4941 uint32 jobid = q_u->jobid;
4942 /* uint32 level = q_u->level; - notused. */
4943 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
4944 uint32 command = q_u->command;
4946 struct current_user user;
4947 print_status_struct prt_status;
4948 int snum, errcode = ERROR_INVALID_FUNCTION;
4950 memset(&prt_status, 0, sizeof(prt_status));
4952 if (!get_printer_snum(p, handle, &snum)) {
4953 return ERROR_INVALID_HANDLE;
4956 if (!print_job_exists(jobid)) {
4957 return ERROR_INVALID_PRINTER_NAME;
4960 get_current_user(&user, p);
4962 switch (command) {
4963 case JOB_CONTROL_CANCEL:
4964 case JOB_CONTROL_DELETE:
4965 if (print_job_delete(&user, jobid, &errcode)) {
4966 errcode = 0;
4968 break;
4969 case JOB_CONTROL_PAUSE:
4970 if (print_job_pause(&user, jobid, &errcode)) {
4971 errcode = 0;
4973 break;
4974 case JOB_CONTROL_RESTART:
4975 case JOB_CONTROL_RESUME:
4976 if (print_job_resume(&user, jobid, &errcode)) {
4977 errcode = 0;
4979 break;
4980 default:
4981 return ERROR_INVALID_LEVEL;
4984 return errcode;
4987 /****************************************************************************
4988 Enumerates all printer drivers at level 1.
4989 ****************************************************************************/
4990 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4992 int i;
4993 int ndrivers;
4994 uint32 version;
4995 fstring *list = NULL;
4997 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4998 DRIVER_INFO_1 *driver_info_1=NULL;
5000 *returned=0;
5002 #define MAX_VERSION 4
5004 for (version=0; version<MAX_VERSION; version++) {
5005 list=NULL;
5006 ndrivers=get_ntdrivers(&list, architecture, version);
5007 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5009 if(ndrivers == -1)
5010 return ERROR_NOT_ENOUGH_MEMORY;
5012 if(ndrivers != 0) {
5013 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5014 safe_free(list);
5015 return ERROR_NOT_ENOUGH_MEMORY;
5019 for (i=0; i<ndrivers; i++) {
5020 uint32 status;
5021 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5022 ZERO_STRUCT(driver);
5023 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5024 safe_free(list);
5025 return status;
5027 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5028 free_a_printer_driver(driver, 3);
5031 *returned+=ndrivers;
5032 safe_free(list);
5035 /* check the required size. */
5036 for (i=0; i<*returned; i++) {
5037 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5038 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5041 if (!alloc_buffer_size(buffer, *needed)) {
5042 safe_free(driver_info_1);
5043 return ERROR_INSUFFICIENT_BUFFER;
5046 /* fill the buffer with the driver structures */
5047 for (i=0; i<*returned; i++) {
5048 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5049 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5052 safe_free(driver_info_1);
5054 if (*needed > offered) {
5055 *returned=0;
5056 return ERROR_INSUFFICIENT_BUFFER;
5058 else
5059 return NT_STATUS_NO_PROBLEMO;
5062 /****************************************************************************
5063 Enumerates all printer drivers at level 2.
5064 ****************************************************************************/
5065 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5067 int i;
5068 int ndrivers;
5069 uint32 version;
5070 fstring *list = NULL;
5072 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5073 DRIVER_INFO_2 *driver_info_2=NULL;
5075 *returned=0;
5077 #define MAX_VERSION 4
5079 for (version=0; version<MAX_VERSION; version++) {
5080 list=NULL;
5081 ndrivers=get_ntdrivers(&list, architecture, version);
5082 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5084 if(ndrivers == -1)
5085 return ERROR_NOT_ENOUGH_MEMORY;
5087 if(ndrivers != 0) {
5088 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5089 safe_free(list);
5090 return ERROR_NOT_ENOUGH_MEMORY;
5094 for (i=0; i<ndrivers; i++) {
5095 uint32 status;
5097 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5098 ZERO_STRUCT(driver);
5099 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5100 safe_free(list);
5101 return status;
5103 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5104 free_a_printer_driver(driver, 3);
5107 *returned+=ndrivers;
5108 safe_free(list);
5111 /* check the required size. */
5112 for (i=0; i<*returned; i++) {
5113 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5114 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5117 if (!alloc_buffer_size(buffer, *needed)) {
5118 safe_free(driver_info_2);
5119 return ERROR_INSUFFICIENT_BUFFER;
5122 /* fill the buffer with the form structures */
5123 for (i=0; i<*returned; i++) {
5124 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5125 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5128 safe_free(driver_info_2);
5130 if (*needed > offered) {
5131 *returned=0;
5132 return ERROR_INSUFFICIENT_BUFFER;
5134 else
5135 return NT_STATUS_NO_PROBLEMO;
5138 /****************************************************************************
5139 Enumerates all printer drivers at level 3.
5140 ****************************************************************************/
5141 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5143 int i;
5144 int ndrivers;
5145 uint32 version;
5146 fstring *list = NULL;
5148 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5149 DRIVER_INFO_3 *driver_info_3=NULL;
5151 *returned=0;
5153 #define MAX_VERSION 4
5155 for (version=0; version<MAX_VERSION; version++) {
5156 list=NULL;
5157 ndrivers=get_ntdrivers(&list, architecture, version);
5158 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5160 if(ndrivers == -1)
5161 return ERROR_NOT_ENOUGH_MEMORY;
5163 if(ndrivers != 0) {
5164 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5165 safe_free(list);
5166 return ERROR_NOT_ENOUGH_MEMORY;
5170 for (i=0; i<ndrivers; i++) {
5171 uint32 status;
5173 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5174 ZERO_STRUCT(driver);
5175 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5176 safe_free(list);
5177 return status;
5179 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5180 free_a_printer_driver(driver, 3);
5183 *returned+=ndrivers;
5184 safe_free(list);
5187 /* check the required size. */
5188 for (i=0; i<*returned; i++) {
5189 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5190 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5193 if (!alloc_buffer_size(buffer, *needed)) {
5194 safe_free(driver_info_3);
5195 return ERROR_INSUFFICIENT_BUFFER;
5198 /* fill the buffer with the driver structures */
5199 for (i=0; i<*returned; i++) {
5200 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5201 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5204 for (i=0; i<*returned; i++)
5205 safe_free(driver_info_3[i].dependentfiles);
5207 safe_free(driver_info_3);
5209 if (*needed > offered) {
5210 *returned=0;
5211 return ERROR_INSUFFICIENT_BUFFER;
5213 else
5214 return NT_STATUS_NO_PROBLEMO;
5217 /****************************************************************************
5218 Enumerates all printer drivers.
5219 ****************************************************************************/
5221 uint32 _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5223 /* UNISTR2 *name = &q_u->name; - notused. */
5224 UNISTR2 *environment = &q_u->environment;
5225 uint32 level = q_u->level;
5226 NEW_BUFFER *buffer = NULL;
5227 uint32 offered = q_u->offered;
5228 uint32 *needed = &r_u->needed;
5229 uint32 *returned = &r_u->returned;
5231 fstring *list = NULL;
5232 fstring servername;
5233 fstring architecture;
5235 /* that's an [in out] buffer */
5236 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5237 buffer = r_u->buffer;
5239 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5240 fstrcpy(servername, global_myname);
5241 *needed=0;
5242 *returned=0;
5244 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5246 switch (level) {
5247 case 1:
5248 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5249 case 2:
5250 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5251 case 3:
5252 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5253 default:
5254 *returned=0;
5255 safe_free(list);
5256 return ERROR_INVALID_LEVEL;
5260 /****************************************************************************
5261 ****************************************************************************/
5263 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5265 form->flag=list->flag;
5266 init_unistr(&form->name, list->name);
5267 form->width=list->width;
5268 form->length=list->length;
5269 form->left=list->left;
5270 form->top=list->top;
5271 form->right=list->right;
5272 form->bottom=list->bottom;
5275 /****************************************************************************
5276 ****************************************************************************/
5278 uint32 _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5280 /* POLICY_HND *handle = &q_u->handle; - notused. */
5281 uint32 level = q_u->level;
5282 NEW_BUFFER *buffer = NULL;
5283 uint32 offered = q_u->offered;
5284 uint32 *needed = &r_u->needed;
5285 uint32 *numofforms = &r_u->numofforms;
5286 uint32 numbuiltinforms;
5288 nt_forms_struct *list=NULL;
5289 nt_forms_struct *builtinlist=NULL;
5290 FORM_1 *forms_1;
5291 int buffer_size=0;
5292 int i;
5294 /* that's an [in out] buffer */
5295 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5296 buffer = r_u->buffer;
5298 DEBUG(4,("_spoolss_enumforms\n"));
5299 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5300 DEBUGADD(5,("Info level [%d]\n", level));
5302 numbuiltinforms = get_builtin_ntforms(&builtinlist);
5303 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
5304 *numofforms = get_ntforms(&list);
5305 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
5306 *numofforms += numbuiltinforms;
5308 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
5310 switch (level) {
5311 case 1:
5312 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5313 *numofforms=0;
5314 return ERROR_NOT_ENOUGH_MEMORY;
5317 /* construct the list of form structures */
5318 for (i=0; i<numbuiltinforms; i++) {
5319 DEBUGADD(6,("Filling form number [%d]\n",i));
5320 fill_form_1(&forms_1[i], &builtinlist[i]);
5323 safe_free(builtinlist);
5325 for (; i<*numofforms; i++) {
5326 DEBUGADD(6,("Filling form number [%d]\n",i));
5327 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5330 safe_free(list);
5332 /* check the required size. */
5333 for (i=0; i<numbuiltinforms; i++) {
5334 DEBUGADD(6,("adding form [%d]'s size\n",i));
5335 buffer_size += spoolss_size_form_1(&forms_1[i]);
5337 for (; i<*numofforms; i++) {
5338 DEBUGADD(6,("adding form [%d]'s size\n",i));
5339 buffer_size += spoolss_size_form_1(&forms_1[i]);
5342 *needed=buffer_size;
5344 if (!alloc_buffer_size(buffer, buffer_size)){
5345 safe_free(forms_1);
5346 return ERROR_INSUFFICIENT_BUFFER;
5349 /* fill the buffer with the form structures */
5350 for (i=0; i<numbuiltinforms; i++) {
5351 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5352 smb_io_form_1("", buffer, &forms_1[i], 0);
5354 for (; i<*numofforms; i++) {
5355 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5356 smb_io_form_1("", buffer, &forms_1[i], 0);
5359 safe_free(forms_1);
5361 if (*needed > offered) {
5362 *numofforms=0;
5363 return ERROR_INSUFFICIENT_BUFFER;
5365 else
5366 return NT_STATUS_NO_PROBLEMO;
5368 default:
5369 safe_free(list);
5370 safe_free(builtinlist);
5371 return ERROR_INVALID_LEVEL;
5376 /****************************************************************************
5377 ****************************************************************************/
5379 uint32 _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5381 /* POLICY_HND *handle = &q_u->handle; - notused. */
5382 uint32 level = q_u->level;
5383 UNISTR2 *uni_formname = &q_u->formname;
5384 NEW_BUFFER *buffer = NULL;
5385 uint32 offered = q_u->offered;
5386 uint32 *needed = &r_u->needed;
5388 nt_forms_struct *list=NULL;
5389 nt_forms_struct builtin_form;
5390 BOOL foundBuiltin;
5391 FORM_1 form_1;
5392 fstring form_name;
5393 int buffer_size=0;
5394 int numofforms=0, i=0;
5396 /* that's an [in out] buffer */
5397 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5398 buffer = r_u->buffer;
5400 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5402 DEBUG(4,("_spoolss_getform\n"));
5403 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5404 DEBUGADD(5,("Info level [%d]\n", level));
5406 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5407 if (!foundBuiltin) {
5408 numofforms = get_ntforms(&list);
5409 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5411 if (numofforms == 0)
5412 return ERROR_INVALID_HANDLE;
5415 switch (level) {
5416 case 1:
5417 if (foundBuiltin) {
5418 fill_form_1(&form_1, &builtin_form);
5419 } else {
5421 /* Check if the requested name is in the list of form structures */
5422 for (i=0; i<numofforms; i++) {
5424 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5426 if (strequal(form_name, list[i].name)) {
5427 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5428 fill_form_1(&form_1, &list[i]);
5429 break;
5433 safe_free(list);
5434 if (i == numofforms) {
5435 return ERROR_INVALID_HANDLE;
5438 /* check the required size. */
5440 *needed=spoolss_size_form_1(&form_1);
5442 if (!alloc_buffer_size(buffer, buffer_size)){
5443 return ERROR_INSUFFICIENT_BUFFER;
5446 if (*needed > offered) {
5447 return ERROR_INSUFFICIENT_BUFFER;
5450 /* fill the buffer with the form structures */
5451 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5452 smb_io_form_1("", buffer, &form_1, 0);
5454 return NT_STATUS_NO_PROBLEMO;
5456 default:
5457 safe_free(list);
5458 return ERROR_INVALID_LEVEL;
5462 /****************************************************************************
5463 ****************************************************************************/
5464 static void fill_port_1(PORT_INFO_1 *port, char *name)
5466 init_unistr(&port->port_name, name);
5469 /****************************************************************************
5470 ****************************************************************************/
5471 static void fill_port_2(PORT_INFO_2 *port, char *name)
5473 init_unistr(&port->port_name, name);
5474 init_unistr(&port->monitor_name, "Local Monitor");
5475 init_unistr(&port->description, "Local Port");
5476 #define PORT_TYPE_WRITE 1
5477 port->port_type=PORT_TYPE_WRITE;
5478 port->reserved=0x0;
5481 /****************************************************************************
5482 enumports level 1.
5483 ****************************************************************************/
5484 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5486 PORT_INFO_1 *ports=NULL;
5487 int i=0;
5489 if (*lp_enumports_cmd()) {
5490 char *cmd = lp_enumports_cmd();
5491 char **qlines;
5492 pstring command;
5493 int numlines;
5494 int ret;
5495 int fd;
5497 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5499 DEBUG(10,("Running [%s]\n", command));
5500 ret = smbrun(command, &fd);
5501 DEBUG(10,("Returned [%d]\n", ret));
5502 if (ret != 0) {
5503 if (fd != -1)
5504 close(fd);
5505 /* Is this the best error to return here? */
5506 return ERROR_ACCESS_DENIED;
5509 numlines = 0;
5510 qlines = fd_lines_load(fd, &numlines,True);
5511 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5512 close(fd);
5514 if(numlines) {
5515 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5516 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5517 file_lines_free(qlines);
5518 return ERROR_NOT_ENOUGH_MEMORY;
5521 for (i=0; i<numlines; i++) {
5522 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5523 fill_port_1(&ports[i], qlines[i]);
5526 file_lines_free(qlines);
5529 *returned = numlines;
5531 } else {
5532 *returned = 1; /* Sole Samba port returned. */
5534 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5535 return ERROR_NOT_ENOUGH_MEMORY;
5537 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5539 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5542 /* check the required size. */
5543 for (i=0; i<*returned; i++) {
5544 DEBUGADD(6,("adding port [%d]'s size\n", i));
5545 *needed += spoolss_size_port_info_1(&ports[i]);
5548 if (!alloc_buffer_size(buffer, *needed)) {
5549 safe_free(ports);
5550 return ERROR_INSUFFICIENT_BUFFER;
5553 /* fill the buffer with the ports structures */
5554 for (i=0; i<*returned; i++) {
5555 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5556 smb_io_port_1("", buffer, &ports[i], 0);
5559 safe_free(ports);
5561 if (*needed > offered) {
5562 *returned=0;
5563 return ERROR_INSUFFICIENT_BUFFER;
5565 else
5566 return NT_STATUS_NO_PROBLEMO;
5569 /****************************************************************************
5570 enumports level 2.
5571 ****************************************************************************/
5573 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5575 PORT_INFO_2 *ports=NULL;
5576 int i=0;
5578 if (*lp_enumports_cmd()) {
5579 char *cmd = lp_enumports_cmd();
5580 char *path;
5581 char **qlines;
5582 pstring tmp_file;
5583 pstring command;
5584 int numlines;
5585 int ret;
5586 int fd;
5588 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5589 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5590 else
5591 path = lp_lockdir();
5593 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
5594 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5596 unlink(tmp_file);
5597 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5598 ret = smbrun(command, &fd);
5599 DEBUGADD(10,("returned [%d]\n", ret));
5600 if (ret != 0) {
5601 if (fd != -1)
5602 close(fd);
5603 /* Is this the best error to return here? */
5604 return ERROR_ACCESS_DENIED;
5607 numlines = 0;
5608 qlines = fd_lines_load(fd, &numlines,True);
5609 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5610 close(fd);
5612 if(numlines) {
5613 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5614 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5615 file_lines_free(qlines);
5616 return ERROR_NOT_ENOUGH_MEMORY;
5619 for (i=0; i<numlines; i++) {
5620 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5621 fill_port_2(&(ports[i]), qlines[i]);
5624 file_lines_free(qlines);
5627 *returned = numlines;
5629 } else {
5631 *returned = 1;
5633 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5634 return ERROR_NOT_ENOUGH_MEMORY;
5636 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5638 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5641 /* check the required size. */
5642 for (i=0; i<*returned; i++) {
5643 DEBUGADD(6,("adding port [%d]'s size\n", i));
5644 *needed += spoolss_size_port_info_2(&ports[i]);
5647 if (!alloc_buffer_size(buffer, *needed)) {
5648 safe_free(ports);
5649 return ERROR_INSUFFICIENT_BUFFER;
5652 /* fill the buffer with the ports structures */
5653 for (i=0; i<*returned; i++) {
5654 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5655 smb_io_port_2("", buffer, &ports[i], 0);
5658 safe_free(ports);
5660 if (*needed > offered) {
5661 *returned=0;
5662 return ERROR_INSUFFICIENT_BUFFER;
5664 else
5665 return NT_STATUS_NO_PROBLEMO;
5668 /****************************************************************************
5669 enumports.
5670 ****************************************************************************/
5672 uint32 _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5674 /* UNISTR2 *name = &q_u->name; - notused. */
5675 uint32 level = q_u->level;
5676 NEW_BUFFER *buffer = NULL;
5677 uint32 offered = q_u->offered;
5678 uint32 *needed = &r_u->needed;
5679 uint32 *returned = &r_u->returned;
5681 /* that's an [in out] buffer */
5682 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5683 buffer = r_u->buffer;
5685 DEBUG(4,("_spoolss_enumports\n"));
5687 *returned=0;
5688 *needed=0;
5690 switch (level) {
5691 case 1:
5692 return enumports_level_1(buffer, offered, needed, returned);
5693 case 2:
5694 return enumports_level_2(buffer, offered, needed, returned);
5695 default:
5696 return ERROR_INVALID_LEVEL;
5700 /****************************************************************************
5701 ****************************************************************************/
5702 static uint32 spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5703 const SPOOL_PRINTER_INFO_LEVEL *info,
5704 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5705 uint32 user_switch, const SPOOL_USER_CTR *user,
5706 POLICY_HND *handle)
5708 NT_PRINTER_INFO_LEVEL *printer = NULL;
5709 fstring name;
5710 int snum;
5712 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5713 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5714 return ERROR_NOT_ENOUGH_MEMORY;
5717 ZERO_STRUCTP(printer);
5719 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5720 convert_printer_info(info, printer, 2);
5722 if (*lp_addprinter_cmd() )
5723 if ( !add_printer_hook(printer) ) {
5724 free_a_printer(&printer,2);
5725 return ERROR_ACCESS_DENIED;
5728 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5729 printer->info_2->sharename);
5731 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5732 free_a_printer(&printer,2);
5733 return ERROR_ACCESS_DENIED;
5736 /* you must be a printer admin to add a new printer */
5737 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5738 free_a_printer(&printer,2);
5739 return ERROR_ACCESS_DENIED;
5743 * Do sanity check on the requested changes for Samba.
5746 if (!check_printer_ok(printer->info_2, snum)) {
5747 free_a_printer(&printer,2);
5748 return ERROR_INVALID_PARAMETER;
5751 /* write the ASCII on disk */
5752 if (add_a_printer(*printer, 2) != 0) {
5753 free_a_printer(&printer,2);
5754 return ERROR_ACCESS_DENIED;
5757 if (!open_printer_hnd(p, handle, name)) {
5758 /* Handle open failed - remove addition. */
5759 del_a_printer(printer->info_2->sharename);
5760 free_a_printer(&printer,2);
5761 return ERROR_ACCESS_DENIED;
5764 free_a_printer(&printer,2);
5766 srv_spoolss_sendnotify(p, handle);
5768 return NT_STATUS_NO_PROBLEMO;
5771 /****************************************************************************
5772 ****************************************************************************/
5774 uint32 _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5776 UNISTR2 *uni_srv_name = &q_u->server_name;
5777 uint32 level = q_u->level;
5778 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5779 uint32 unk0 = q_u->unk0;
5780 uint32 unk1 = q_u->unk1;
5781 uint32 unk2 = q_u->unk2;
5782 uint32 unk3 = q_u->unk3;
5783 uint32 user_switch = q_u->user_switch;
5784 SPOOL_USER_CTR *user = &q_u->user_ctr;
5785 POLICY_HND *handle = &r_u->handle;
5787 switch (level) {
5788 case 1:
5789 /* we don't handle yet */
5790 /* but I know what to do ... */
5791 return ERROR_INVALID_LEVEL;
5792 case 2:
5793 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5794 unk0, unk1, unk2, unk3,
5795 user_switch, user, handle);
5796 default:
5797 return ERROR_INVALID_LEVEL;
5801 /****************************************************************************
5802 ****************************************************************************/
5804 uint32 _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5806 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5807 uint32 level = q_u->level;
5808 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5810 uint32 err = NT_STATUS_NO_PROBLEMO;
5811 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5812 struct current_user user;
5814 ZERO_STRUCT(driver);
5816 get_current_user(&user, p);
5818 convert_printer_driver_info(info, &driver, level);
5820 DEBUG(5,("Cleaning driver's information\n"));
5821 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5822 goto done;
5824 DEBUG(5,("Moving driver to final destination\n"));
5825 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5826 if (err == 0)
5827 err = ERROR_ACCESS_DENIED;
5828 goto done;
5831 if (add_a_printer_driver(driver, level)!=0) {
5832 err = ERROR_ACCESS_DENIED;
5833 goto done;
5836 done:
5837 free_a_printer_driver(driver, level);
5838 return err;
5841 /****************************************************************************
5842 ****************************************************************************/
5843 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5845 init_unistr(&info->name, name);
5848 /****************************************************************************
5849 ****************************************************************************/
5850 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5852 pstring path;
5853 pstring long_archi;
5854 pstring short_archi;
5855 DRIVER_DIRECTORY_1 *info=NULL;
5857 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5859 if (get_short_archi(short_archi, long_archi)==FALSE)
5860 return ERROR_INVALID_ENVIRONMENT;
5862 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5863 return ERROR_NOT_ENOUGH_MEMORY;
5865 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5867 DEBUG(4,("printer driver directory: [%s]\n", path));
5869 fill_driverdir_1(info, path);
5871 *needed += spoolss_size_driverdir_info_1(info);
5873 if (!alloc_buffer_size(buffer, *needed)) {
5874 safe_free(info);
5875 return ERROR_INSUFFICIENT_BUFFER;
5878 smb_io_driverdir_1("", buffer, info, 0);
5880 safe_free(info);
5882 if (*needed > offered)
5883 return ERROR_INSUFFICIENT_BUFFER;
5884 else
5885 return NT_STATUS_NO_PROBLEMO;
5888 /****************************************************************************
5889 ****************************************************************************/
5891 uint32 _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
5893 UNISTR2 *name = &q_u->name;
5894 UNISTR2 *uni_environment = &q_u->environment;
5895 uint32 level = q_u->level;
5896 NEW_BUFFER *buffer = NULL;
5897 uint32 offered = q_u->offered;
5898 uint32 *needed = &r_u->needed;
5900 /* that's an [in out] buffer */
5901 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5902 buffer = r_u->buffer;
5904 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5906 *needed=0;
5908 switch(level) {
5909 case 1:
5910 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5911 default:
5912 return ERROR_INVALID_LEVEL;
5916 /****************************************************************************
5917 ****************************************************************************/
5919 uint32 _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
5921 POLICY_HND *handle = &q_u->handle;
5922 uint32 idx = q_u->index;
5923 uint32 in_value_len = q_u->valuesize;
5924 uint32 in_data_len = q_u->datasize;
5925 uint32 *out_max_value_len = &r_u->valuesize;
5926 uint16 **out_value = &r_u->value;
5927 uint32 *out_value_len = &r_u->realvaluesize;
5928 uint32 *out_type = &r_u->type;
5929 uint32 *out_max_data_len = &r_u->datasize;
5930 uint8 **data_out = &r_u->data;
5931 uint32 *out_data_len = &r_u->realdatasize;
5933 NT_PRINTER_INFO_LEVEL *printer = NULL;
5935 fstring value;
5937 uint32 param_index;
5938 uint32 biggest_valuesize;
5939 uint32 biggest_datasize;
5940 uint32 data_len;
5941 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5942 int snum;
5943 uint8 *data=NULL;
5944 uint32 type;
5946 ZERO_STRUCT(printer);
5948 *out_max_value_len=0;
5949 *out_value=NULL;
5950 *out_value_len=0;
5952 *out_type=0;
5954 *out_max_data_len=0;
5955 *data_out=NULL;
5956 *out_data_len=0;
5958 DEBUG(5,("spoolss_enumprinterdata\n"));
5960 if (!Printer) {
5961 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5962 return ERROR_INVALID_HANDLE;
5965 if (!get_printer_snum(p,handle, &snum))
5966 return ERROR_INVALID_HANDLE;
5968 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5969 return ERROR_INVALID_HANDLE;
5972 * The NT machine wants to know the biggest size of value and data
5974 * cf: MSDN EnumPrinterData remark section
5976 if ( (in_value_len==0) && (in_data_len==0) ) {
5977 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5979 #if 0
5981 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5982 * if this parameter size doesn't exist.
5983 * Ok - my opinion here is that the client is not asking for the greatest
5984 * possible size of all the parameters, but is asking specifically for the size needed
5985 * for this specific parameter. In that case we can remove the loop below and
5986 * simplify this lookup code considerably. JF - comments welcome. JRA.
5989 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5990 safe_free(data);
5991 free_a_printer(&printer, 2);
5992 return ERROR_NO_MORE_ITEMS;
5994 #endif
5996 safe_free(data);
5997 data = NULL;
5999 param_index=0;
6000 biggest_valuesize=0;
6001 biggest_datasize=0;
6003 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6004 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6005 if (data_len > biggest_datasize) biggest_datasize=data_len;
6007 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6009 safe_free(data);
6010 data = NULL;
6011 param_index++;
6015 * I think this is correct, it doesn't break APW and
6016 * allows Gerald's Win32 test programs to work correctly,
6017 * but may need altering.... JRA.
6020 if (param_index == 0) {
6021 /* No parameters found. */
6022 free_a_printer(&printer, 2);
6023 return ERROR_NO_MORE_ITEMS;
6026 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6027 *out_value_len=2*(1+biggest_valuesize);
6028 *out_data_len=biggest_datasize;
6030 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6032 free_a_printer(&printer, 2);
6033 return NT_STATUS_NO_PROBLEMO;
6037 * the value len is wrong in NT sp3
6038 * that's the number of bytes not the number of unicode chars
6041 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6042 safe_free(data);
6043 free_a_printer(&printer, 2);
6044 return ERROR_NO_MORE_ITEMS;
6047 free_a_printer(&printer, 2);
6050 * the value is:
6051 * - counted in bytes in the request
6052 * - counted in UNICODE chars in the max reply
6053 * - counted in bytes in the real size
6055 * take a pause *before* coding not *during* coding
6058 *out_max_value_len=(in_value_len/sizeof(uint16));
6059 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6060 safe_free(data);
6061 return ERROR_NOT_ENOUGH_MEMORY;
6064 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
6066 *out_type=type;
6068 /* the data is counted in bytes */
6069 *out_max_data_len=in_data_len;
6070 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6071 safe_free(data);
6072 return ERROR_NOT_ENOUGH_MEMORY;
6075 memcpy(*data_out, data, (size_t)data_len);
6076 *out_data_len=data_len;
6078 safe_free(data);
6080 return NT_STATUS_NO_PROBLEMO;
6083 /****************************************************************************
6084 ****************************************************************************/
6086 uint32 _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6088 POLICY_HND *handle = &q_u->handle;
6089 UNISTR2 *value = &q_u->value;
6090 uint32 type = q_u->type;
6091 /* uint32 max_len = q_u->max_len; - notused. */
6092 uint8 *data = q_u->data;
6093 uint32 real_len = q_u->real_len;
6094 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6096 NT_PRINTER_INFO_LEVEL *printer = NULL;
6097 NT_PRINTER_PARAM *param = NULL, old_param;
6098 int snum=0;
6099 uint32 status = 0x0;
6100 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6102 DEBUG(5,("spoolss_setprinterdata\n"));
6104 if (!Printer) {
6105 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6106 return ERROR_INVALID_HANDLE;
6109 if (!get_printer_snum(p,handle, &snum))
6110 return ERROR_INVALID_HANDLE;
6112 status = get_a_printer(&printer, 2, lp_servicename(snum));
6113 if (status != 0x0)
6114 return ERROR_INVALID_NAME;
6116 convert_specific_param(&param, value , type, data, real_len);
6118 /* Check if we are making any changes or not. Return true if
6119 nothing is actually changing. */
6121 ZERO_STRUCT(old_param);
6123 if (get_specific_param(*printer, 2, param->value, &old_param.data,
6124 &old_param.type, (uint32 *)&old_param.data_len)) {
6126 if (param->type == old_param.type &&
6127 param->data_len == old_param.data_len &&
6128 memcmp(param->data, old_param.data,
6129 old_param.data_len) == 0) {
6131 DEBUG(3, ("setprinterdata hasn't changed\n"));
6132 status = NT_STATUS_NO_PROBLEMO;
6133 goto done;
6137 /* Access check */
6139 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6140 DEBUG(3, ("security descriptor change denied by existing "
6141 "security descriptor\n"));
6142 status = ERROR_ACCESS_DENIED;
6143 goto done;
6146 unlink_specific_param_if_exist(printer->info_2, param);
6148 add_a_specific_param(printer->info_2, &param);
6149 status = mod_a_printer(*printer, 2);
6151 done:
6152 free_a_printer(&printer, 2);
6153 if (param)
6154 free_nt_printer_param(&param);
6155 safe_free(old_param.data);
6157 return status;
6160 /****************************************************************************
6161 ****************************************************************************/
6163 uint32 _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6165 POLICY_HND *handle = &q_u->handle;
6166 UNISTR2 *value = &q_u->valuename;
6168 NT_PRINTER_INFO_LEVEL *printer = NULL;
6169 NT_PRINTER_PARAM param;
6170 int snum=0;
6171 uint32 status = 0x0;
6172 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6174 DEBUG(5,("spoolss_deleteprinterdata\n"));
6176 if (!Printer) {
6177 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6178 return ERROR_INVALID_HANDLE;
6181 if (!get_printer_snum(p, handle, &snum))
6182 return ERROR_INVALID_HANDLE;
6184 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6185 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6186 "change denied by existing security descriptor\n"));
6187 return ERROR_ACCESS_DENIED;
6190 status = get_a_printer(&printer, 2, lp_servicename(snum));
6191 if (status != 0x0)
6192 return ERROR_INVALID_NAME;
6194 ZERO_STRUCTP(&param);
6195 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6197 if(!unlink_specific_param_if_exist(printer->info_2, &param))
6198 status = ERROR_INVALID_PARAMETER;
6199 else
6200 status = mod_a_printer(*printer, 2);
6202 free_a_printer(&printer, 2);
6203 return status;
6206 /****************************************************************************
6207 ****************************************************************************/
6209 uint32 _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6211 POLICY_HND *handle = &q_u->handle;
6212 /* uint32 level = q_u->level; - notused. */
6213 FORM *form = &q_u->form;
6214 nt_forms_struct tmpForm;
6216 int count=0;
6217 nt_forms_struct *list=NULL;
6218 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6220 DEBUG(5,("spoolss_addform\n"));
6222 if (!Printer) {
6223 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6224 return ERROR_INVALID_HANDLE;
6227 /* can't add if builtin */
6228 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6229 return ERROR_INVALID_PARAMETER;
6232 count=get_ntforms(&list);
6233 if(!add_a_form(&list, form, &count))
6234 return ERROR_NOT_ENOUGH_MEMORY;
6235 write_ntforms(&list, count);
6237 safe_free(list);
6239 return 0x0;
6242 /****************************************************************************
6243 ****************************************************************************/
6245 uint32 _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6247 POLICY_HND *handle = &q_u->handle;
6248 UNISTR2 *form_name = &q_u->name;
6249 nt_forms_struct tmpForm;
6250 int count=0;
6251 uint32 ret = 0;
6252 nt_forms_struct *list=NULL;
6253 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6255 DEBUG(5,("spoolss_deleteform\n"));
6257 if (!Printer) {
6258 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6259 return ERROR_INVALID_HANDLE;
6262 /* can't delete if builtin */
6263 if (get_a_builtin_ntform(form_name,&tmpForm)) {
6264 return ERROR_INVALID_PARAMETER;
6267 count = get_ntforms(&list);
6268 if(!delete_a_form(&list, form_name, &count, &ret))
6269 return ERROR_INVALID_PARAMETER;
6271 safe_free(list);
6273 return ret;
6276 /****************************************************************************
6277 ****************************************************************************/
6279 uint32 _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6281 POLICY_HND *handle = &q_u->handle;
6282 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6283 /* uint32 level = q_u->level; - notused. */
6284 FORM *form = &q_u->form;
6285 nt_forms_struct tmpForm;
6287 int count=0;
6288 nt_forms_struct *list=NULL;
6289 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6291 DEBUG(5,("spoolss_setform\n"));
6293 if (!Printer) {
6294 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6295 return ERROR_INVALID_HANDLE;
6297 /* can't set if builtin */
6298 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6299 return ERROR_INVALID_PARAMETER;
6302 count=get_ntforms(&list);
6303 update_a_form(&list, form, count);
6304 write_ntforms(&list, count);
6306 safe_free(list);
6308 return 0x0;
6311 /****************************************************************************
6312 enumprintprocessors level 1.
6313 ****************************************************************************/
6314 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6316 PRINTPROCESSOR_1 *info_1=NULL;
6318 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6319 return ERROR_NOT_ENOUGH_MEMORY;
6321 (*returned) = 0x1;
6323 init_unistr(&info_1->name, "winprint");
6325 *needed += spoolss_size_printprocessor_info_1(info_1);
6327 if (!alloc_buffer_size(buffer, *needed))
6328 return ERROR_INSUFFICIENT_BUFFER;
6330 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6332 safe_free(info_1);
6334 if (*needed > offered) {
6335 *returned=0;
6336 return ERROR_INSUFFICIENT_BUFFER;
6338 else
6339 return NT_STATUS_NO_PROBLEMO;
6342 /****************************************************************************
6343 ****************************************************************************/
6345 uint32 _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6347 /* UNISTR2 *name = &q_u->name; - notused. */
6348 /* UNISTR2 *environment = &q_u->environment; - notused. */
6349 uint32 level = q_u->level;
6350 NEW_BUFFER *buffer = NULL;
6351 uint32 offered = q_u->offered;
6352 uint32 *needed = &r_u->needed;
6353 uint32 *returned = &r_u->returned;
6355 /* that's an [in out] buffer */
6356 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6357 buffer = r_u->buffer;
6359 DEBUG(5,("spoolss_enumprintprocessors\n"));
6362 * Enumerate the print processors ...
6364 * Just reply with "winprint", to keep NT happy
6365 * and I can use my nice printer checker.
6368 *returned=0;
6369 *needed=0;
6371 switch (level) {
6372 case 1:
6373 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6374 default:
6375 return ERROR_INVALID_LEVEL;
6379 /****************************************************************************
6380 enumprintprocdatatypes level 1.
6381 ****************************************************************************/
6382 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6384 PRINTPROCDATATYPE_1 *info_1=NULL;
6386 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6387 return ERROR_NOT_ENOUGH_MEMORY;
6389 (*returned) = 0x1;
6391 init_unistr(&info_1->name, "RAW");
6393 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6395 if (!alloc_buffer_size(buffer, *needed))
6396 return ERROR_INSUFFICIENT_BUFFER;
6398 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6400 safe_free(info_1);
6402 if (*needed > offered) {
6403 *returned=0;
6404 return ERROR_INSUFFICIENT_BUFFER;
6406 else
6407 return NT_STATUS_NO_PROBLEMO;
6410 /****************************************************************************
6411 ****************************************************************************/
6413 uint32 _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6415 /* UNISTR2 *name = &q_u->name; - notused. */
6416 /* UNISTR2 *processor = &q_u->processor; - notused. */
6417 uint32 level = q_u->level;
6418 NEW_BUFFER *buffer = NULL;
6419 uint32 offered = q_u->offered;
6420 uint32 *needed = &r_u->needed;
6421 uint32 *returned = &r_u->returned;
6423 /* that's an [in out] buffer */
6424 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6425 buffer = r_u->buffer;
6427 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6429 *returned=0;
6430 *needed=0;
6432 switch (level) {
6433 case 1:
6434 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6435 default:
6436 return ERROR_INVALID_LEVEL;
6440 /****************************************************************************
6441 enumprintmonitors level 1.
6442 ****************************************************************************/
6444 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6446 PRINTMONITOR_1 *info_1=NULL;
6448 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6449 return ERROR_NOT_ENOUGH_MEMORY;
6451 (*returned) = 0x1;
6453 init_unistr(&info_1->name, "Local Port");
6455 *needed += spoolss_size_printmonitor_info_1(info_1);
6457 if (!alloc_buffer_size(buffer, *needed))
6458 return ERROR_INSUFFICIENT_BUFFER;
6460 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6462 safe_free(info_1);
6464 if (*needed > offered) {
6465 *returned=0;
6466 return ERROR_INSUFFICIENT_BUFFER;
6468 else
6469 return NT_STATUS_NO_PROBLEMO;
6472 /****************************************************************************
6473 enumprintmonitors level 2.
6474 ****************************************************************************/
6475 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6477 PRINTMONITOR_2 *info_2=NULL;
6479 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6480 return ERROR_NOT_ENOUGH_MEMORY;
6482 (*returned) = 0x1;
6484 init_unistr(&info_2->name, "Local Port");
6485 init_unistr(&info_2->environment, "Windows NT X86");
6486 init_unistr(&info_2->dll_name, "localmon.dll");
6488 *needed += spoolss_size_printmonitor_info_2(info_2);
6490 if (!alloc_buffer_size(buffer, *needed))
6491 return ERROR_INSUFFICIENT_BUFFER;
6493 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6495 safe_free(info_2);
6497 if (*needed > offered) {
6498 *returned=0;
6499 return ERROR_INSUFFICIENT_BUFFER;
6501 else
6502 return NT_STATUS_NO_PROBLEMO;
6505 /****************************************************************************
6506 ****************************************************************************/
6508 uint32 _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6510 /* UNISTR2 *name = &q_u->name; - notused. */
6511 uint32 level = q_u->level;
6512 NEW_BUFFER *buffer = NULL;
6513 uint32 offered = q_u->offered;
6514 uint32 *needed = &r_u->needed;
6515 uint32 *returned = &r_u->returned;
6517 /* that's an [in out] buffer */
6518 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6519 buffer = r_u->buffer;
6521 DEBUG(5,("spoolss_enumprintmonitors\n"));
6524 * Enumerate the print monitors ...
6526 * Just reply with "Local Port", to keep NT happy
6527 * and I can use my nice printer checker.
6530 *returned=0;
6531 *needed=0;
6533 switch (level) {
6534 case 1:
6535 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6536 case 2:
6537 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6538 default:
6539 return ERROR_INVALID_LEVEL;
6543 /****************************************************************************
6544 ****************************************************************************/
6545 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6547 int i=0;
6548 BOOL found=False;
6549 JOB_INFO_1 *info_1=NULL;
6551 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6553 if (info_1 == NULL) {
6554 safe_free(queue);
6555 return ERROR_NOT_ENOUGH_MEMORY;
6558 for (i=0; i<count && found==False; i++) {
6559 if (queue[i].job==(int)jobid)
6560 found=True;
6563 if (found==False) {
6564 safe_free(queue);
6565 safe_free(info_1);
6566 /* I shoud reply something else ... I can't find the good one */
6567 return NT_STATUS_NO_PROBLEMO;
6570 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6572 safe_free(queue);
6574 *needed += spoolss_size_job_info_1(info_1);
6576 if (!alloc_buffer_size(buffer, *needed)) {
6577 safe_free(info_1);
6578 return ERROR_INSUFFICIENT_BUFFER;
6581 smb_io_job_info_1("", buffer, info_1, 0);
6583 safe_free(info_1);
6585 if (*needed > offered)
6586 return ERROR_INSUFFICIENT_BUFFER;
6587 else
6588 return NT_STATUS_NO_PROBLEMO;
6592 /****************************************************************************
6593 ****************************************************************************/
6594 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6596 int i=0;
6597 BOOL found=False;
6598 JOB_INFO_2 *info_2;
6599 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6601 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6603 ZERO_STRUCTP(info_2);
6605 if (info_2 == NULL) {
6606 safe_free(queue);
6607 return ERROR_NOT_ENOUGH_MEMORY;
6610 for (i=0; i<count && found==False; i++) {
6611 if (queue[i].job==(int)jobid)
6612 found=True;
6615 if (found==False) {
6616 safe_free(queue);
6617 safe_free(info_2);
6618 /* I shoud reply something else ... I can't find the good one */
6619 return NT_STATUS_NO_PROBLEMO;
6622 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6623 safe_free(queue);
6624 return ERROR_NOT_ENOUGH_MEMORY;
6627 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6629 free_a_printer(&ntprinter, 2);
6630 safe_free(queue);
6632 *needed += spoolss_size_job_info_2(info_2);
6634 if (!alloc_buffer_size(buffer, *needed)) {
6635 safe_free(info_2);
6636 return ERROR_INSUFFICIENT_BUFFER;
6639 smb_io_job_info_2("", buffer, info_2, 0);
6641 free_job_info_2(info_2);
6642 free(info_2);
6644 if (*needed > offered)
6645 return ERROR_INSUFFICIENT_BUFFER;
6646 else
6647 return NT_STATUS_NO_PROBLEMO;
6650 /****************************************************************************
6651 ****************************************************************************/
6653 uint32 _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6655 POLICY_HND *handle = &q_u->handle;
6656 uint32 jobid = q_u->jobid;
6657 uint32 level = q_u->level;
6658 NEW_BUFFER *buffer = NULL;
6659 uint32 offered = q_u->offered;
6660 uint32 *needed = &r_u->needed;
6662 int snum;
6663 int count;
6664 print_queue_struct *queue=NULL;
6665 print_status_struct prt_status;
6667 /* that's an [in out] buffer */
6668 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6669 buffer = r_u->buffer;
6671 DEBUG(5,("spoolss_getjob\n"));
6673 memset(&prt_status, 0, sizeof(prt_status));
6675 *needed=0;
6677 if (!get_printer_snum(p, handle, &snum))
6678 return ERROR_INVALID_HANDLE;
6680 count = print_queue_status(snum, &queue, &prt_status);
6682 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6683 count, prt_status.status, prt_status.message));
6685 switch (level) {
6686 case 1:
6687 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6688 case 2:
6689 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6690 default:
6691 safe_free(queue);
6692 return ERROR_INVALID_LEVEL;