merge from 2.2 (deleteprinterdriver RPC)
[Samba/gbeck.git] / source / rpc_server / srv_spoolss_nt.c
blob1d1eced2ea5c53ccdd3da00b574a939291a828c5
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 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 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1357 return False;
1358 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1362 smb_connections++;
1364 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1365 return False;
1367 return True;
1370 /********************************************************************
1371 * _spoolss_rffpcnex
1372 * ReplyFindFirstPrinterChangeNotifyEx
1374 * jfmxxxx: before replying OK: status=0
1375 * should do a rpc call to the workstation asking ReplyOpenPrinter
1376 * have to code it, later.
1378 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1379 * called from api_spoolss_rffpcnex
1380 ********************************************************************/
1382 uint32 _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1384 POLICY_HND *handle = &q_u->handle;
1385 uint32 flags = q_u->flags;
1386 uint32 options = q_u->options;
1387 UNISTR2 *localmachine = &q_u->localmachine;
1388 uint32 printerlocal = q_u->printerlocal;
1389 SPOOL_NOTIFY_OPTION *option = q_u->option;
1391 /* store the notify value in the printer struct */
1393 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1395 if (!Printer) {
1396 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1397 return ERROR_INVALID_HANDLE;
1400 Printer->notify.flags=flags;
1401 Printer->notify.options=options;
1402 Printer->notify.printerlocal=printerlocal;
1404 if (Printer->notify.option)
1405 free_spool_notify_option(&Printer->notify.option);
1407 Printer->notify.option=dup_spool_notify_option(option);
1409 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1411 /* connect to the client machine and send a ReplyOpenPrinter */
1412 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1413 Printer->notify.printerlocal, 1,
1414 &Printer->notify.client_hnd))
1415 Printer->notify.client_connected=True;
1417 return NT_STATUS_NO_PROBLEMO;
1420 /*******************************************************************
1421 * fill a notify_info_data with the servername
1422 ********************************************************************/
1424 static void spoolss_notify_server_name(int snum,
1425 SPOOL_NOTIFY_INFO_DATA *data,
1426 print_queue_struct *queue,
1427 NT_PRINTER_INFO_LEVEL *printer,
1428 TALLOC_CTX *mem_ctx)
1430 pstring temp_name, temp;
1431 uint32 len;
1433 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1435 len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1437 data->notify_data.data.length = len / 2 - 1;
1438 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1440 if (!data->notify_data.data.string) {
1441 data->notify_data.data.length = 0;
1442 return;
1445 memcpy(data->notify_data.data.string, temp, len);
1448 /*******************************************************************
1449 * fill a notify_info_data with the printername (not including the servername).
1450 ********************************************************************/
1451 static void spoolss_notify_printer_name(int snum,
1452 SPOOL_NOTIFY_INFO_DATA *data,
1453 print_queue_struct *queue,
1454 NT_PRINTER_INFO_LEVEL *printer,
1455 TALLOC_CTX *mem_ctx)
1457 pstring temp;
1458 uint32 len;
1460 /* the notify name should not contain the \\server\ part */
1461 char *p = strrchr(printer->info_2->printername, '\\');
1463 if (!p) {
1464 p = printer->info_2->printername;
1465 } else {
1466 p++;
1469 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1471 data->notify_data.data.length = len / 2 - 1;
1472 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1474 if (!data->notify_data.data.string) {
1475 data->notify_data.data.length = 0;
1476 return;
1479 memcpy(data->notify_data.data.string, temp, len);
1482 /*******************************************************************
1483 * fill a notify_info_data with the servicename
1484 ********************************************************************/
1485 static void spoolss_notify_share_name(int snum,
1486 SPOOL_NOTIFY_INFO_DATA *data,
1487 print_queue_struct *queue,
1488 NT_PRINTER_INFO_LEVEL *printer,
1489 TALLOC_CTX *mem_ctx)
1491 pstring temp;
1492 uint32 len;
1494 len = (uint32)dos_PutUniCode(temp, lp_servicename(snum),
1495 sizeof(temp) - 2, True);
1497 data->notify_data.data.length = len / 2 - 1;
1498 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1500 if (!data->notify_data.data.string) {
1501 data->notify_data.data.length = 0;
1502 return;
1505 memcpy(data->notify_data.data.string, temp, len);
1508 /*******************************************************************
1509 * fill a notify_info_data with the port name
1510 ********************************************************************/
1511 static void spoolss_notify_port_name(int snum,
1512 SPOOL_NOTIFY_INFO_DATA *data,
1513 print_queue_struct *queue,
1514 NT_PRINTER_INFO_LEVEL *printer,
1515 TALLOC_CTX *mem_ctx)
1517 pstring temp;
1518 uint32 len;
1520 /* even if it's strange, that's consistant in all the code */
1522 len = (uint32)dos_PutUniCode(temp, printer->info_2->portname,
1523 sizeof(temp) - 2, True);
1525 data->notify_data.data.length = len / 2 - 1;
1526 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1528 if (!data->notify_data.data.string) {
1529 data->notify_data.data.length = 0;
1530 return;
1533 memcpy(data->notify_data.data.string, temp, len);
1536 /*******************************************************************
1537 * fill a notify_info_data with the printername
1538 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1539 * but it doesn't exist, have to see what to do
1540 ********************************************************************/
1541 static void spoolss_notify_driver_name(int snum,
1542 SPOOL_NOTIFY_INFO_DATA *data,
1543 print_queue_struct *queue,
1544 NT_PRINTER_INFO_LEVEL *printer,
1545 TALLOC_CTX *mem_ctx)
1547 pstring temp;
1548 uint32 len;
1550 len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername,
1551 sizeof(temp) - 2, True);
1553 data->notify_data.data.length = len / 2 - 1;
1554 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1556 if (!data->notify_data.data.string) {
1557 data->notify_data.data.length = 0;
1558 return;
1561 memcpy(data->notify_data.data.string, temp, len);
1564 /*******************************************************************
1565 * fill a notify_info_data with the comment
1566 ********************************************************************/
1567 static void spoolss_notify_comment(int snum,
1568 SPOOL_NOTIFY_INFO_DATA *data,
1569 print_queue_struct *queue,
1570 NT_PRINTER_INFO_LEVEL *printer,
1571 TALLOC_CTX *mem_ctx)
1573 pstring temp;
1574 uint32 len;
1576 if (*printer->info_2->comment == '\0')
1577 len = (uint32)dos_PutUniCode(temp, lp_comment(snum),
1578 sizeof(temp) - 2, True);
1579 else
1580 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment,
1581 sizeof(temp) - 2, True);
1583 data->notify_data.data.length = len / 2 - 1;
1584 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1586 if (!data->notify_data.data.string) {
1587 data->notify_data.data.length = 0;
1588 return;
1591 memcpy(data->notify_data.data.string, temp, len);
1594 /*******************************************************************
1595 * fill a notify_info_data with the comment
1596 * jfm:xxxx incorrect, have to create a new smb.conf option
1597 * location = "Room 1, floor 2, building 3"
1598 ********************************************************************/
1599 static void spoolss_notify_location(int snum,
1600 SPOOL_NOTIFY_INFO_DATA *data,
1601 print_queue_struct *queue,
1602 NT_PRINTER_INFO_LEVEL *printer,
1603 TALLOC_CTX *mem_ctx)
1605 pstring temp;
1606 uint32 len;
1608 len = (uint32)dos_PutUniCode(temp, printer->info_2->location,
1609 sizeof(temp) - 2, True);
1611 data->notify_data.data.length = len / 2 - 1;
1612 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1614 if (!data->notify_data.data.string) {
1615 data->notify_data.data.length = 0;
1616 return;
1619 memcpy(data->notify_data.data.string, temp, len);
1622 /*******************************************************************
1623 * fill a notify_info_data with the device mode
1624 * jfm:xxxx don't to it for know but that's a real problem !!!
1625 ********************************************************************/
1626 static void spoolss_notify_devmode(int snum,
1627 SPOOL_NOTIFY_INFO_DATA *data,
1628 print_queue_struct *queue,
1629 NT_PRINTER_INFO_LEVEL *printer,
1630 TALLOC_CTX *mem_ctx)
1634 /*******************************************************************
1635 * fill a notify_info_data with the separator file name
1636 * jfm:xxxx just return no file could add an option to smb.conf
1637 * separator file = "separator.txt"
1638 ********************************************************************/
1639 static void spoolss_notify_sepfile(int snum,
1640 SPOOL_NOTIFY_INFO_DATA *data,
1641 print_queue_struct *queue,
1642 NT_PRINTER_INFO_LEVEL *printer,
1643 TALLOC_CTX *mem_ctx)
1645 pstring temp;
1646 uint32 len;
1648 len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile,
1649 sizeof(temp) - 2, True);
1651 data->notify_data.data.length = len / 2 - 1;
1652 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1654 if (!data->notify_data.data.string) {
1655 data->notify_data.data.length = 0;
1656 return;
1659 memcpy(data->notify_data.data.string, temp, len);
1662 /*******************************************************************
1663 * fill a notify_info_data with the print processor
1664 * jfm:xxxx return always winprint to indicate we don't do anything to it
1665 ********************************************************************/
1666 static void spoolss_notify_print_processor(int snum,
1667 SPOOL_NOTIFY_INFO_DATA *data,
1668 print_queue_struct *queue,
1669 NT_PRINTER_INFO_LEVEL *printer,
1670 TALLOC_CTX *mem_ctx)
1672 pstring temp;
1673 uint32 len;
1675 len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor,
1676 sizeof(temp) - 2, True);
1678 data->notify_data.data.length = len / 2 - 1;
1679 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1681 if (!data->notify_data.data.string) {
1682 data->notify_data.data.length = 0;
1683 return;
1686 memcpy(data->notify_data.data.string, temp, len);
1689 /*******************************************************************
1690 * fill a notify_info_data with the print processor options
1691 * jfm:xxxx send an empty string
1692 ********************************************************************/
1693 static void spoolss_notify_parameters(int snum,
1694 SPOOL_NOTIFY_INFO_DATA *data,
1695 print_queue_struct *queue,
1696 NT_PRINTER_INFO_LEVEL *printer,
1697 TALLOC_CTX *mem_ctx)
1699 pstring temp;
1700 uint32 len;
1702 len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters,
1703 sizeof(temp) - 2, True);
1705 data->notify_data.data.length = len / 2 - 1;
1706 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1708 if (!data->notify_data.data.string) {
1709 data->notify_data.data.length = 0;
1710 return;
1713 memcpy(data->notify_data.data.string, temp, len);
1716 /*******************************************************************
1717 * fill a notify_info_data with the data type
1718 * jfm:xxxx always send RAW as data type
1719 ********************************************************************/
1720 static void spoolss_notify_datatype(int snum,
1721 SPOOL_NOTIFY_INFO_DATA *data,
1722 print_queue_struct *queue,
1723 NT_PRINTER_INFO_LEVEL *printer,
1724 TALLOC_CTX *mem_ctx)
1726 pstring temp;
1727 uint32 len;
1729 len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype,
1730 sizeof(pstring) - 2, True);
1732 data->notify_data.data.length = len / 2 - 1;
1733 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1735 if (!data->notify_data.data.string) {
1736 data->notify_data.data.length = 0;
1737 return;
1740 memcpy(data->notify_data.data.string, temp, len);
1743 /*******************************************************************
1744 * fill a notify_info_data with the security descriptor
1745 * jfm:xxxx send an null pointer to say no security desc
1746 * have to implement security before !
1747 ********************************************************************/
1748 static void spoolss_notify_security_desc(int snum,
1749 SPOOL_NOTIFY_INFO_DATA *data,
1750 print_queue_struct *queue,
1751 NT_PRINTER_INFO_LEVEL *printer,
1752 TALLOC_CTX *mem_ctx)
1754 data->notify_data.data.length=0;
1755 data->notify_data.data.string = NULL;
1758 /*******************************************************************
1759 * fill a notify_info_data with the attributes
1760 * jfm:xxxx a samba printer is always shared
1761 ********************************************************************/
1762 static void spoolss_notify_attributes(int snum,
1763 SPOOL_NOTIFY_INFO_DATA *data,
1764 print_queue_struct *queue,
1765 NT_PRINTER_INFO_LEVEL *printer,
1766 TALLOC_CTX *mem_ctx)
1768 data->notify_data.value[0] = printer->info_2->attributes;
1771 /*******************************************************************
1772 * fill a notify_info_data with the priority
1773 ********************************************************************/
1774 static void spoolss_notify_priority(int snum,
1775 SPOOL_NOTIFY_INFO_DATA *data,
1776 print_queue_struct *queue,
1777 NT_PRINTER_INFO_LEVEL *printer,
1778 TALLOC_CTX *mem_ctx)
1780 data->notify_data.value[0] = printer->info_2->priority;
1783 /*******************************************************************
1784 * fill a notify_info_data with the default priority
1785 ********************************************************************/
1786 static void spoolss_notify_default_priority(int snum,
1787 SPOOL_NOTIFY_INFO_DATA *data,
1788 print_queue_struct *queue,
1789 NT_PRINTER_INFO_LEVEL *printer,
1790 TALLOC_CTX *mem_ctx)
1792 data->notify_data.value[0] = printer->info_2->default_priority;
1795 /*******************************************************************
1796 * fill a notify_info_data with the start time
1797 ********************************************************************/
1798 static void spoolss_notify_start_time(int snum,
1799 SPOOL_NOTIFY_INFO_DATA *data,
1800 print_queue_struct *queue,
1801 NT_PRINTER_INFO_LEVEL *printer,
1802 TALLOC_CTX *mem_ctx)
1804 data->notify_data.value[0] = printer->info_2->starttime;
1807 /*******************************************************************
1808 * fill a notify_info_data with the until time
1809 ********************************************************************/
1810 static void spoolss_notify_until_time(int snum,
1811 SPOOL_NOTIFY_INFO_DATA *data,
1812 print_queue_struct *queue,
1813 NT_PRINTER_INFO_LEVEL *printer,
1814 TALLOC_CTX *mem_ctx)
1816 data->notify_data.value[0] = printer->info_2->untiltime;
1819 /*******************************************************************
1820 * fill a notify_info_data with the status
1821 ********************************************************************/
1822 static void spoolss_notify_status(int snum,
1823 SPOOL_NOTIFY_INFO_DATA *data,
1824 print_queue_struct *queue,
1825 NT_PRINTER_INFO_LEVEL *printer,
1826 TALLOC_CTX *mem_ctx)
1828 print_queue_struct *q=NULL;
1829 print_status_struct status;
1831 memset(&status, 0, sizeof(status));
1832 print_queue_status(snum, &q, &status);
1833 data->notify_data.value[0]=(uint32) status.status;
1834 safe_free(q);
1837 /*******************************************************************
1838 * fill a notify_info_data with the number of jobs queued
1839 ********************************************************************/
1840 static void spoolss_notify_cjobs(int snum,
1841 SPOOL_NOTIFY_INFO_DATA *data,
1842 print_queue_struct *queue,
1843 NT_PRINTER_INFO_LEVEL *printer,
1844 TALLOC_CTX *mem_ctx)
1846 print_queue_struct *q=NULL;
1847 print_status_struct status;
1849 memset(&status, 0, sizeof(status));
1850 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1851 safe_free(q);
1854 /*******************************************************************
1855 * fill a notify_info_data with the average ppm
1856 ********************************************************************/
1857 static void spoolss_notify_average_ppm(int snum,
1858 SPOOL_NOTIFY_INFO_DATA *data,
1859 print_queue_struct *queue,
1860 NT_PRINTER_INFO_LEVEL *printer,
1861 TALLOC_CTX *mem_ctx)
1863 /* always respond 8 pages per minutes */
1864 /* a little hard ! */
1865 data->notify_data.value[0] = printer->info_2->averageppm;
1868 /*******************************************************************
1869 * fill a notify_info_data with username
1870 ********************************************************************/
1871 static void spoolss_notify_username(int snum,
1872 SPOOL_NOTIFY_INFO_DATA *data,
1873 print_queue_struct *queue,
1874 NT_PRINTER_INFO_LEVEL *printer,
1875 TALLOC_CTX *mem_ctx)
1877 pstring temp;
1878 uint32 len;
1880 len = (uint32)dos_PutUniCode(temp, queue->user,
1881 sizeof(temp) - 2, True);
1883 data->notify_data.data.length = len / 2 - 1;
1884 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1886 if (!data->notify_data.data.string) {
1887 data->notify_data.data.length = 0;
1888 return;
1891 memcpy(data->notify_data.data.string, temp, len);
1894 /*******************************************************************
1895 * fill a notify_info_data with job status
1896 ********************************************************************/
1897 static void spoolss_notify_job_status(int snum,
1898 SPOOL_NOTIFY_INFO_DATA *data,
1899 print_queue_struct *queue,
1900 NT_PRINTER_INFO_LEVEL *printer,
1901 TALLOC_CTX *mem_ctx)
1903 data->notify_data.value[0]=nt_printj_status(queue->status);
1906 /*******************************************************************
1907 * fill a notify_info_data with job name
1908 ********************************************************************/
1909 static void spoolss_notify_job_name(int snum,
1910 SPOOL_NOTIFY_INFO_DATA *data,
1911 print_queue_struct *queue,
1912 NT_PRINTER_INFO_LEVEL *printer,
1913 TALLOC_CTX *mem_ctx)
1915 pstring temp;
1916 uint32 len;
1918 len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2,
1919 True);
1921 data->notify_data.data.length = len / 2 - 1;
1922 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1924 if (!data->notify_data.data.string) {
1925 data->notify_data.data.length = 0;
1926 return;
1929 memcpy(data->notify_data.data.string, temp, len);
1932 /*******************************************************************
1933 * fill a notify_info_data with job status
1934 ********************************************************************/
1935 static void spoolss_notify_job_status_string(int snum,
1936 SPOOL_NOTIFY_INFO_DATA *data,
1937 print_queue_struct *queue,
1938 NT_PRINTER_INFO_LEVEL *printer,
1939 TALLOC_CTX *mem_ctx)
1942 * Now we're returning job status codes we just return a "" here. JRA.
1945 char *p = "";
1946 pstring temp;
1947 uint32 len;
1949 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1950 p = "unknown";
1952 switch (queue->status) {
1953 case LPQ_QUEUED:
1954 p = "Queued";
1955 break;
1956 case LPQ_PAUSED:
1957 p = ""; /* NT provides the paused string */
1958 break;
1959 case LPQ_SPOOLING:
1960 p = "Spooling";
1961 break;
1962 case LPQ_PRINTING:
1963 p = "Printing";
1964 break;
1966 #endif /* NO LONGER NEEDED. */
1968 len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1970 data->notify_data.data.length = len / 2 - 1;
1971 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1973 if (!data->notify_data.data.string) {
1974 data->notify_data.data.length = 0;
1975 return;
1978 memcpy(data->notify_data.data.string, temp, len);
1981 /*******************************************************************
1982 * fill a notify_info_data with job time
1983 ********************************************************************/
1984 static void spoolss_notify_job_time(int snum,
1985 SPOOL_NOTIFY_INFO_DATA *data,
1986 print_queue_struct *queue,
1987 NT_PRINTER_INFO_LEVEL *printer,
1988 TALLOC_CTX *mem_ctx)
1990 data->notify_data.value[0]=0x0;
1993 /*******************************************************************
1994 * fill a notify_info_data with job size
1995 ********************************************************************/
1996 static void spoolss_notify_job_size(int snum,
1997 SPOOL_NOTIFY_INFO_DATA *data,
1998 print_queue_struct *queue,
1999 NT_PRINTER_INFO_LEVEL *printer,
2000 TALLOC_CTX *mem_ctx)
2002 data->notify_data.value[0]=queue->size;
2005 /*******************************************************************
2006 * fill a notify_info_data with job position
2007 ********************************************************************/
2008 static void spoolss_notify_job_position(int snum,
2009 SPOOL_NOTIFY_INFO_DATA *data,
2010 print_queue_struct *queue,
2011 NT_PRINTER_INFO_LEVEL *printer,
2012 TALLOC_CTX *mem_ctx)
2014 data->notify_data.value[0]=queue->job;
2017 /*******************************************************************
2018 * fill a notify_info_data with submitted time
2019 ********************************************************************/
2020 static void spoolss_notify_submitted_time(int snum,
2021 SPOOL_NOTIFY_INFO_DATA *data,
2022 print_queue_struct *queue,
2023 NT_PRINTER_INFO_LEVEL *printer,
2024 TALLOC_CTX *mem_ctx)
2026 struct tm *t;
2027 uint32 len;
2028 SYSTEMTIME st;
2030 t=gmtime(&queue->time);
2032 len = sizeof(SYSTEMTIME);
2034 data->notify_data.data.length = len/2 - 1;
2035 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2037 if (!data->notify_data.data.string) {
2038 data->notify_data.data.length = 0;
2039 return;
2042 make_systemtime(&st, t);
2043 memcpy(data->notify_data.data.string,&st,len);
2046 #define END 65535
2048 struct s_notify_info_data_table
2050 uint16 type;
2051 uint16 field;
2052 char *name;
2053 uint32 size;
2054 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2055 print_queue_struct *queue,
2056 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2059 struct s_notify_info_data_table notify_info_data_table[] =
2061 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2062 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2063 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2064 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2065 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2066 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2067 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2087 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2088 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2089 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2090 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2091 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2092 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2093 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2094 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2095 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2096 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2097 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2098 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2099 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2100 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2101 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2102 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2103 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2104 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2105 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2106 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2107 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2108 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2109 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2110 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2111 { END, END, "", END, NULL }
2114 /*******************************************************************
2115 return the size of info_data structure
2116 ********************************************************************/
2117 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2119 int i=0;
2121 while (notify_info_data_table[i].type != END)
2123 if ( (notify_info_data_table[i].type == type ) &&
2124 (notify_info_data_table[i].field == field ) )
2126 return (notify_info_data_table[i].size);
2128 i++;
2130 return (65535);
2133 /*******************************************************************
2134 return the type of notify_info_data
2135 ********************************************************************/
2136 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2138 int i=0;
2140 while (notify_info_data_table[i].type != END)
2142 if ( (notify_info_data_table[i].type == type ) &&
2143 (notify_info_data_table[i].field == field ) )
2145 if (notify_info_data_table[i].size == POINTER)
2147 return (False);
2149 else
2151 return (True);
2154 i++;
2156 return (False);
2159 /****************************************************************************
2160 ****************************************************************************/
2161 static int search_notify(uint16 type, uint16 field, int *value)
2163 int j;
2164 BOOL found;
2166 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2168 if ( (notify_info_data_table[j].type == type ) &&
2169 (notify_info_data_table[j].field == field ) )
2170 found=True;
2172 *value=--j;
2174 if ( found && (notify_info_data_table[j].fn != NULL) )
2175 return True;
2176 else
2177 return False;
2180 /****************************************************************************
2181 ****************************************************************************/
2182 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2184 info_data->type = type;
2185 info_data->field = field;
2186 info_data->reserved = 0;
2187 info_data->id = id;
2188 info_data->size = size_of_notify_info_data(type, field);
2189 info_data->enc_type = type_of_notify_info_data(type, field);
2193 /*******************************************************************
2195 * fill a notify_info struct with info asked
2197 ********************************************************************/
2198 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2199 snum, SPOOL_NOTIFY_OPTION_TYPE
2200 *option_type, uint32 id,
2201 TALLOC_CTX *mem_ctx)
2203 int field_num,j;
2204 uint16 type;
2205 uint16 field;
2207 SPOOL_NOTIFY_INFO_DATA *current_data;
2208 NT_PRINTER_INFO_LEVEL *printer = NULL;
2209 print_queue_struct *queue=NULL;
2211 type=option_type->type;
2213 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2214 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2215 option_type->count, lp_servicename(snum)));
2217 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2218 return False;
2220 for(field_num=0; field_num<option_type->count; field_num++) {
2221 field = option_type->fields[field_num];
2222 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2224 if (!search_notify(type, field, &j) )
2225 continue;
2227 if((info->data=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2228 return False;
2230 current_data=&info->data[info->count];
2232 construct_info_data(current_data, type, field, id);
2234 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2235 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2237 notify_info_data_table[j].fn(snum, current_data, queue,
2238 printer, mem_ctx);
2240 info->count++;
2243 free_a_printer(&printer, 2);
2244 return True;
2247 /*******************************************************************
2249 * fill a notify_info struct with info asked
2251 ********************************************************************/
2252 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2253 SPOOL_NOTIFY_INFO *info,
2254 NT_PRINTER_INFO_LEVEL *printer,
2255 int snum, SPOOL_NOTIFY_OPTION_TYPE
2256 *option_type, uint32 id,
2257 TALLOC_CTX *mem_ctx)
2259 int field_num,j;
2260 uint16 type;
2261 uint16 field;
2263 SPOOL_NOTIFY_INFO_DATA *current_data;
2265 DEBUG(4,("construct_notify_jobs_info\n"));
2267 type = option_type->type;
2269 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2270 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2271 option_type->count));
2273 for(field_num=0; field_num<option_type->count; field_num++) {
2274 field = option_type->fields[field_num];
2276 if (!search_notify(type, field, &j) )
2277 continue;
2279 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2280 return False;
2283 current_data=&(info->data[info->count]);
2285 construct_info_data(current_data, type, field, id);
2286 notify_info_data_table[j].fn(snum, current_data, queue,
2287 printer, mem_ctx);
2288 info->count++;
2291 return True;
2295 * JFM: The enumeration is not that simple, it's even non obvious.
2297 * let's take an example: I want to monitor the PRINTER SERVER for
2298 * the printer's name and the number of jobs currently queued.
2299 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2300 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2302 * I have 3 printers on the back of my server.
2304 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2305 * structures.
2306 * Number Data Id
2307 * 1 printer 1 name 1
2308 * 2 printer 1 cjob 1
2309 * 3 printer 2 name 2
2310 * 4 printer 2 cjob 2
2311 * 5 printer 3 name 3
2312 * 6 printer 3 name 3
2314 * that's the print server case, the printer case is even worse.
2317 /*******************************************************************
2319 * enumerate all printers on the printserver
2320 * fill a notify_info struct with info asked
2322 ********************************************************************/
2324 static uint32 printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2325 SPOOL_NOTIFY_INFO *info,
2326 TALLOC_CTX *mem_ctx)
2328 int snum;
2329 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2330 int n_services=lp_numservices();
2331 int i;
2332 uint32 id;
2333 SPOOL_NOTIFY_OPTION *option;
2334 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2336 DEBUG(4,("printserver_notify_info\n"));
2338 option=Printer->notify.option;
2339 id=1;
2340 info->version=2;
2341 info->data=NULL;
2342 info->count=0;
2344 for (i=0; i<option->count; i++) {
2345 option_type=&(option->ctr.type[i]);
2347 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2348 continue;
2350 for (snum=0; snum<n_services; snum++)
2351 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2352 if (construct_notify_printer_info
2353 (info, snum, option_type, id, mem_ctx))
2354 id++;
2358 * Debugging information, don't delete.
2361 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2362 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2363 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2365 for (i=0; i<info->count; i++) {
2366 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2367 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2368 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2372 return NT_STATUS_NO_PROBLEMO;
2375 /*******************************************************************
2377 * fill a notify_info struct with info asked
2379 ********************************************************************/
2380 static uint32 printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2381 TALLOC_CTX *mem_ctx)
2383 int snum;
2384 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2385 int i;
2386 uint32 id;
2387 SPOOL_NOTIFY_OPTION *option;
2388 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2389 int count,j;
2390 print_queue_struct *queue=NULL;
2391 print_status_struct status;
2393 DEBUG(4,("printer_notify_info\n"));
2395 option=Printer->notify.option;
2396 id=0xffffffff;
2397 info->version=2;
2398 info->data=NULL;
2399 info->count=0;
2401 get_printer_snum(p, hnd, &snum);
2403 for (i=0; i<option->count; i++) {
2404 option_type=&option->ctr.type[i];
2406 switch ( option_type->type ) {
2407 case PRINTER_NOTIFY_TYPE:
2408 if(construct_notify_printer_info(info, snum,
2409 option_type, id,
2410 mem_ctx))
2411 id--;
2412 break;
2414 case JOB_NOTIFY_TYPE: {
2415 NT_PRINTER_INFO_LEVEL *printer = NULL;
2417 memset(&status, 0, sizeof(status));
2418 count = print_queue_status(snum, &queue, &status);
2420 if (get_a_printer(&printer, 2,
2421 lp_servicename(snum)) != 0)
2422 goto done;
2424 for (j=0; j<count; j++) {
2425 construct_notify_jobs_info(&queue[j], info,
2426 printer, snum,
2427 option_type,
2428 queue[j].job,
2429 mem_ctx);
2432 free_a_printer(&printer, 2);
2434 done:
2435 safe_free(queue);
2436 break;
2442 * Debugging information, don't delete.
2445 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2446 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2447 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2449 for (i=0; i<info->count; i++) {
2450 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2451 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2452 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2455 return NT_STATUS_NO_PROBLEMO;
2458 /********************************************************************
2459 * spoolss_rfnpcnex
2460 ********************************************************************/
2462 uint32 _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2464 POLICY_HND *handle = &q_u->handle;
2465 /* uint32 change = q_u->change; - notused. */
2466 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2467 SPOOL_NOTIFY_INFO *info = &r_u->info;
2469 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2470 uint32 result = ERROR_INVALID_HANDLE;
2472 /* we always have a NOTIFY_INFO struct */
2473 r_u->info_ptr=0x1;
2475 if (!Printer) {
2476 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2477 OUR_HANDLE(handle)));
2478 goto done;
2481 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2483 /* jfm: the change value isn't used right now.
2484 * we will honour it when
2485 * a) we'll be able to send notification to the client
2486 * b) we'll have a way to communicate between the spoolss process.
2488 * same thing for option->flags
2489 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2490 * I don't have a global notification system, I'm sending back all the
2491 * informations even when _NOTHING_ has changed.
2494 /* just ignore the SPOOL_NOTIFY_OPTION */
2496 switch (Printer->printer_type) {
2497 case PRINTER_HANDLE_IS_PRINTSERVER:
2498 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2499 break;
2501 case PRINTER_HANDLE_IS_PRINTER:
2502 result = printer_notify_info(p, handle, info, p->mem_ctx);
2503 break;
2506 done:
2507 return result;
2510 /********************************************************************
2511 * construct_printer_info_0
2512 * fill a printer_info_0 struct
2513 ********************************************************************/
2514 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2516 pstring chaine;
2517 int count;
2518 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2519 counter_printer_0 *session_counter;
2520 uint32 global_counter;
2521 struct tm *t;
2522 time_t setuptime;
2524 print_queue_struct *queue=NULL;
2525 print_status_struct status;
2527 memset(&status, 0, sizeof(status));
2529 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2530 return False;
2532 count = print_queue_status(snum, &queue, &status);
2534 /* check if we already have a counter for this printer */
2535 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2537 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2538 if (session_counter->snum == snum)
2539 break;
2542 /* it's the first time, add it to the list */
2543 if (session_counter==NULL) {
2544 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2545 free_a_printer(&ntprinter, 2);
2546 return False;
2548 ZERO_STRUCTP(session_counter);
2549 session_counter->snum=snum;
2550 session_counter->counter=0;
2551 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2554 /* increment it */
2555 session_counter->counter++;
2557 /* JFM:
2558 * the global_counter should be stored in a TDB as it's common to all the clients
2559 * and should be zeroed on samba startup
2561 global_counter=session_counter->counter;
2563 pstrcpy(chaine,ntprinter->info_2->printername);
2565 init_unistr(&printer->printername, chaine);
2567 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2568 init_unistr(&printer->servername, chaine);
2570 printer->cjobs = count;
2571 printer->total_jobs = 0;
2572 printer->total_bytes = 0;
2574 setuptime = (time_t)ntprinter->info_2->setuptime;
2575 t=gmtime(&setuptime);
2577 printer->year = t->tm_year+1900;
2578 printer->month = t->tm_mon+1;
2579 printer->dayofweek = t->tm_wday;
2580 printer->day = t->tm_mday;
2581 printer->hour = t->tm_hour;
2582 printer->minute = t->tm_min;
2583 printer->second = t->tm_sec;
2584 printer->milliseconds = 0;
2586 printer->global_counter = global_counter;
2587 printer->total_pages = 0;
2588 printer->major_version = 0x0004; /* NT 4 */
2589 printer->build_version = 0x0565; /* build 1381 */
2590 printer->unknown7 = 0x1;
2591 printer->unknown8 = 0x0;
2592 printer->unknown9 = 0x0;
2593 printer->session_counter = session_counter->counter;
2594 printer->unknown11 = 0x0;
2595 printer->printer_errors = 0x0; /* number of print failure */
2596 printer->unknown13 = 0x0;
2597 printer->unknown14 = 0x1;
2598 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2599 printer->unknown16 = 0x0;
2600 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2601 printer->unknown18 = 0x0;
2602 printer->status = nt_printq_status(status.status);
2603 printer->unknown20 = 0x0;
2604 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2605 printer->unknown22 = 0x0;
2606 printer->unknown23 = 0x6; /* 6 ???*/
2607 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2608 printer->unknown25 = 0;
2609 printer->unknown26 = 0;
2610 printer->unknown27 = 0;
2611 printer->unknown28 = 0;
2612 printer->unknown29 = 0;
2614 safe_free(queue);
2615 free_a_printer(&ntprinter,2);
2616 return (True);
2619 /********************************************************************
2620 * construct_printer_info_1
2621 * fill a printer_info_1 struct
2622 ********************************************************************/
2623 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2625 pstring chaine;
2626 pstring chaine2;
2627 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2629 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2630 return False;
2632 printer->flags=flags;
2634 if (*ntprinter->info_2->comment == '\0') {
2635 init_unistr(&printer->comment, lp_comment(snum));
2636 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2637 ntprinter->info_2->drivername, lp_comment(snum));
2639 else {
2640 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2641 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2642 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2645 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2647 init_unistr(&printer->description, chaine);
2648 init_unistr(&printer->name, chaine2);
2650 free_a_printer(&ntprinter,2);
2652 return True;
2655 /****************************************************************************
2656 Free a DEVMODE struct.
2657 ****************************************************************************/
2659 static void free_dev_mode(DEVICEMODE *dev)
2661 if (dev == NULL)
2662 return;
2664 if (dev->private)
2665 safe_free(dev->private);
2667 safe_free(dev);
2670 /****************************************************************************
2671 Create a DEVMODE struct. Returns malloced memory.
2672 ****************************************************************************/
2674 static DEVICEMODE *construct_dev_mode(int snum)
2676 char adevice[32];
2677 char aform[32];
2678 NT_PRINTER_INFO_LEVEL *printer = NULL;
2679 NT_DEVICEMODE *ntdevmode = NULL;
2680 DEVICEMODE *devmode = NULL;
2682 DEBUG(7,("construct_dev_mode\n"));
2684 DEBUGADD(8,("getting printer characteristics\n"));
2686 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2687 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2688 return NULL;
2691 ZERO_STRUCTP(devmode);
2693 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2694 goto fail;
2696 if (printer->info_2->devmode)
2697 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2699 if (ntdevmode == NULL)
2700 goto fail;
2702 DEBUGADD(8,("loading DEVICEMODE\n"));
2704 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2705 init_unistr(&devmode->devicename, adevice);
2707 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2708 init_unistr(&devmode->formname, aform);
2710 devmode->specversion = ntdevmode->specversion;
2711 devmode->driverversion = ntdevmode->driverversion;
2712 devmode->size = ntdevmode->size;
2713 devmode->driverextra = ntdevmode->driverextra;
2714 devmode->fields = ntdevmode->fields;
2716 devmode->orientation = ntdevmode->orientation;
2717 devmode->papersize = ntdevmode->papersize;
2718 devmode->paperlength = ntdevmode->paperlength;
2719 devmode->paperwidth = ntdevmode->paperwidth;
2720 devmode->scale = ntdevmode->scale;
2721 devmode->copies = ntdevmode->copies;
2722 devmode->defaultsource = ntdevmode->defaultsource;
2723 devmode->printquality = ntdevmode->printquality;
2724 devmode->color = ntdevmode->color;
2725 devmode->duplex = ntdevmode->duplex;
2726 devmode->yresolution = ntdevmode->yresolution;
2727 devmode->ttoption = ntdevmode->ttoption;
2728 devmode->collate = ntdevmode->collate;
2729 devmode->icmmethod = ntdevmode->icmmethod;
2730 devmode->icmintent = ntdevmode->icmintent;
2731 devmode->mediatype = ntdevmode->mediatype;
2732 devmode->dithertype = ntdevmode->dithertype;
2734 if (ntdevmode->private != NULL) {
2735 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2736 goto fail;
2739 free_nt_devicemode(&ntdevmode);
2740 free_a_printer(&printer,2);
2742 return devmode;
2744 fail:
2746 if (ntdevmode)
2747 free_nt_devicemode(&ntdevmode);
2748 if (printer)
2749 free_a_printer(&printer,2);
2750 free_dev_mode(devmode);
2752 return NULL;
2755 /********************************************************************
2756 * construct_printer_info_2
2757 * fill a printer_info_2 struct
2758 ********************************************************************/
2760 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2762 int count;
2763 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2765 print_queue_struct *queue=NULL;
2766 print_status_struct status;
2767 memset(&status, 0, sizeof(status));
2769 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2770 return False;
2772 memset(&status, 0, sizeof(status));
2773 count = print_queue_status(snum, &queue, &status);
2775 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2776 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2777 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2778 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2779 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2781 if (*ntprinter->info_2->comment == '\0')
2782 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2783 else
2784 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2786 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2787 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2788 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2789 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2790 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2792 printer->attributes = ntprinter->info_2->attributes;
2794 printer->priority = ntprinter->info_2->priority; /* priority */
2795 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2796 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2797 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2798 printer->status = nt_printq_status(status.status); /* status */
2799 printer->cjobs = count; /* jobs */
2800 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2802 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2803 DEBUG(8, ("Returning NULL Devicemode!\n"));
2806 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2807 /* steal the printer info sec_desc structure. [badly done]. */
2808 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2809 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2810 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2811 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2813 else {
2814 printer->secdesc = NULL;
2817 free_a_printer(&ntprinter, 2);
2818 safe_free(queue);
2819 return True;
2822 /********************************************************************
2823 * construct_printer_info_3
2824 * fill a printer_info_3 struct
2825 ********************************************************************/
2826 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2828 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2829 PRINTER_INFO_3 *printer = NULL;
2831 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2832 return False;
2834 *pp_printer = NULL;
2835 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2836 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2837 return False;
2840 ZERO_STRUCTP(printer);
2842 printer->flags = 4; /* These are the components of the SD we are returning. */
2843 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2844 /* steal the printer info sec_desc structure. [badly done]. */
2845 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2847 #if 0
2849 * Set the flags for the components we are returning.
2852 if (printer->secdesc->owner_sid)
2853 printer->flags |= OWNER_SECURITY_INFORMATION;
2855 if (printer->secdesc->grp_sid)
2856 printer->flags |= GROUP_SECURITY_INFORMATION;
2858 if (printer->secdesc->dacl)
2859 printer->flags |= DACL_SECURITY_INFORMATION;
2861 if (printer->secdesc->sacl)
2862 printer->flags |= SACL_SECURITY_INFORMATION;
2863 #endif
2865 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2866 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2867 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2870 free_a_printer(&ntprinter, 2);
2872 *pp_printer = printer;
2873 return True;
2876 /********************************************************************
2877 Spoolss_enumprinters.
2878 ********************************************************************/
2879 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2881 int snum;
2882 int i;
2883 int n_services=lp_numservices();
2884 PRINTER_INFO_1 *printers=NULL;
2885 PRINTER_INFO_1 current_prt;
2887 DEBUG(4,("enum_all_printers_info_1\n"));
2889 for (snum=0; snum<n_services; snum++) {
2890 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2891 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2893 if (construct_printer_info_1(flags, &current_prt, snum)) {
2894 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2895 *returned=0;
2896 return ERROR_NOT_ENOUGH_MEMORY;
2898 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2899 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
2900 (*returned)++;
2905 /* check the required size. */
2906 for (i=0; i<*returned; i++)
2907 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2909 if (!alloc_buffer_size(buffer, *needed))
2910 return ERROR_INSUFFICIENT_BUFFER;
2912 /* fill the buffer with the structures */
2913 for (i=0; i<*returned; i++)
2914 smb_io_printer_info_1("", buffer, &printers[i], 0);
2916 /* clear memory */
2917 safe_free(printers);
2919 if (*needed > offered) {
2920 *returned=0;
2921 return ERROR_INSUFFICIENT_BUFFER;
2923 else
2924 return NT_STATUS_NO_PROBLEMO;
2927 /********************************************************************
2928 enum_all_printers_info_1_local.
2929 *********************************************************************/
2930 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2932 DEBUG(4,("enum_all_printers_info_1_local\n"));
2934 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2937 /********************************************************************
2938 enum_all_printers_info_1_name.
2939 *********************************************************************/
2940 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2942 fstring temp;
2943 DEBUG(4,("enum_all_printers_info_1_name\n"));
2945 fstrcpy(temp, "\\\\");
2946 fstrcat(temp, global_myname);
2948 if (strequal(name, temp)) {
2949 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2951 else
2952 return ERROR_INVALID_NAME;
2955 /********************************************************************
2956 enum_all_printers_info_1_remote.
2957 *********************************************************************/
2958 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2960 PRINTER_INFO_1 *printer;
2961 fstring printername;
2962 fstring desc;
2963 fstring comment;
2964 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2966 /* JFM: currently it's more a place holder than anything else.
2967 * In the spooler world there is a notion of server registration.
2968 * the print servers are registring (sp ?) on the PDC (in the same domain)
2970 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2973 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2974 return ERROR_NOT_ENOUGH_MEMORY;
2976 *returned=1;
2978 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2979 slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2980 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2982 init_unistr(&printer->description, desc);
2983 init_unistr(&printer->name, printername);
2984 init_unistr(&printer->comment, comment);
2985 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2987 /* check the required size. */
2988 *needed += spoolss_size_printer_info_1(printer);
2990 if (!alloc_buffer_size(buffer, *needed)) {
2991 safe_free(printer);
2992 return ERROR_INSUFFICIENT_BUFFER;
2995 /* fill the buffer with the structures */
2996 smb_io_printer_info_1("", buffer, printer, 0);
2998 /* clear memory */
2999 safe_free(printer);
3001 if (*needed > offered) {
3002 *returned=0;
3003 return ERROR_INSUFFICIENT_BUFFER;
3005 else
3006 return NT_STATUS_NO_PROBLEMO;
3009 /********************************************************************
3010 enum_all_printers_info_1_network.
3011 *********************************************************************/
3013 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3015 DEBUG(4,("enum_all_printers_info_1_network\n"));
3017 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3020 /********************************************************************
3021 * api_spoolss_enumprinters
3023 * called from api_spoolss_enumprinters (see this to understand)
3024 ********************************************************************/
3026 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3028 int snum;
3029 int i;
3030 int n_services=lp_numservices();
3031 PRINTER_INFO_2 *printers=NULL;
3032 PRINTER_INFO_2 current_prt;
3034 for (snum=0; snum<n_services; snum++) {
3035 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3036 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3038 if (construct_printer_info_2(&current_prt, snum)) {
3039 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
3040 return ERROR_NOT_ENOUGH_MEMORY;
3041 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3042 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3043 (*returned)++;
3048 /* check the required size. */
3049 for (i=0; i<*returned; i++)
3050 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3052 if (!alloc_buffer_size(buffer, *needed)) {
3053 for (i=0; i<*returned; i++) {
3054 free_devmode(printers[i].devmode);
3056 safe_free(printers);
3057 return ERROR_INSUFFICIENT_BUFFER;
3060 /* fill the buffer with the structures */
3061 for (i=0; i<*returned; i++)
3062 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3064 /* clear memory */
3065 for (i=0; i<*returned; i++) {
3066 free_devmode(printers[i].devmode);
3068 safe_free(printers);
3070 if (*needed > offered) {
3071 *returned=0;
3072 return ERROR_INSUFFICIENT_BUFFER;
3074 else
3075 return NT_STATUS_NO_PROBLEMO;
3078 /********************************************************************
3079 * handle enumeration of printers at level 1
3080 ********************************************************************/
3081 static uint32 enumprinters_level1( uint32 flags, fstring name,
3082 NEW_BUFFER *buffer, uint32 offered,
3083 uint32 *needed, uint32 *returned)
3085 /* Not all the flags are equals */
3087 if (flags & PRINTER_ENUM_LOCAL)
3088 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3090 if (flags & PRINTER_ENUM_NAME)
3091 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3093 if (flags & PRINTER_ENUM_REMOTE)
3094 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3096 if (flags & PRINTER_ENUM_NETWORK)
3097 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3099 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
3102 /********************************************************************
3103 * handle enumeration of printers at level 2
3104 ********************************************************************/
3105 static uint32 enumprinters_level2( uint32 flags, fstring servername,
3106 NEW_BUFFER *buffer, uint32 offered,
3107 uint32 *needed, uint32 *returned)
3109 fstring temp;
3111 fstrcpy(temp, "\\\\");
3112 fstrcat(temp, global_myname);
3114 if (flags & PRINTER_ENUM_LOCAL) {
3115 if (strequal(servername, temp))
3116 return enum_all_printers_info_2(buffer, offered, needed, returned);
3117 else
3118 return enum_all_printers_info_2(buffer, offered, needed, returned);
3121 if (flags & PRINTER_ENUM_NAME) {
3122 if (strequal(servername, temp))
3123 return enum_all_printers_info_2(buffer, offered, needed, returned);
3124 else
3125 return ERROR_INVALID_NAME;
3128 if (flags & PRINTER_ENUM_REMOTE)
3129 return ERROR_INVALID_LEVEL;
3131 return NT_STATUS_NO_PROBLEMO;
3134 /********************************************************************
3135 * handle enumeration of printers at level 5
3136 ********************************************************************/
3137 static uint32 enumprinters_level5( uint32 flags, fstring servername,
3138 NEW_BUFFER *buffer, uint32 offered,
3139 uint32 *needed, uint32 *returned)
3141 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3142 return NT_STATUS_NO_PROBLEMO;
3145 /********************************************************************
3146 * api_spoolss_enumprinters
3148 * called from api_spoolss_enumprinters (see this to understand)
3149 ********************************************************************/
3151 uint32 _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3153 uint32 flags = q_u->flags;
3154 UNISTR2 *servername = &q_u->servername;
3155 uint32 level = q_u->level;
3156 NEW_BUFFER *buffer = NULL;
3157 uint32 offered = q_u->offered;
3158 uint32 *needed = &r_u->needed;
3159 uint32 *returned = &r_u->returned;
3161 fstring name;
3163 /* that's an [in out] buffer */
3164 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3165 buffer = r_u->buffer;
3167 DEBUG(4,("_spoolss_enumprinters\n"));
3169 *needed=0;
3170 *returned=0;
3173 * Level 1:
3174 * flags==PRINTER_ENUM_NAME
3175 * if name=="" then enumerates all printers
3176 * if name!="" then enumerate the printer
3177 * flags==PRINTER_ENUM_REMOTE
3178 * name is NULL, enumerate printers
3179 * Level 2: name!="" enumerates printers, name can't be NULL
3180 * Level 3: doesn't exist
3181 * Level 4: does a local registry lookup
3182 * Level 5: same as Level 2
3185 unistr2_to_ascii(name, servername, sizeof(name)-1);
3186 strupper(name);
3188 switch (level) {
3189 case 1:
3190 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3191 case 2:
3192 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3193 case 5:
3194 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3195 case 3:
3196 case 4:
3197 default:
3198 return ERROR_INVALID_LEVEL;
3202 /****************************************************************************
3203 ****************************************************************************/
3204 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3206 PRINTER_INFO_0 *printer=NULL;
3208 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3209 return ERROR_NOT_ENOUGH_MEMORY;
3211 construct_printer_info_0(printer, snum);
3213 /* check the required size. */
3214 *needed += spoolss_size_printer_info_0(printer);
3216 if (!alloc_buffer_size(buffer, *needed)) {
3217 safe_free(printer);
3218 return ERROR_INSUFFICIENT_BUFFER;
3221 /* fill the buffer with the structures */
3222 smb_io_printer_info_0("", buffer, printer, 0);
3224 /* clear memory */
3225 safe_free(printer);
3227 if (*needed > offered) {
3228 return ERROR_INSUFFICIENT_BUFFER;
3230 else
3231 return NT_STATUS_NO_PROBLEMO;
3234 /****************************************************************************
3235 ****************************************************************************/
3236 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3238 PRINTER_INFO_1 *printer=NULL;
3240 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3241 return ERROR_NOT_ENOUGH_MEMORY;
3243 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3245 /* check the required size. */
3246 *needed += spoolss_size_printer_info_1(printer);
3248 if (!alloc_buffer_size(buffer, *needed)) {
3249 safe_free(printer);
3250 return ERROR_INSUFFICIENT_BUFFER;
3253 /* fill the buffer with the structures */
3254 smb_io_printer_info_1("", buffer, printer, 0);
3256 /* clear memory */
3257 safe_free(printer);
3259 if (*needed > offered) {
3260 return ERROR_INSUFFICIENT_BUFFER;
3262 else
3263 return NT_STATUS_NO_PROBLEMO;
3266 /****************************************************************************
3267 ****************************************************************************/
3268 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3270 PRINTER_INFO_2 *printer=NULL;
3272 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3273 return ERROR_NOT_ENOUGH_MEMORY;
3275 construct_printer_info_2(printer, snum);
3277 /* check the required size. */
3278 *needed += spoolss_size_printer_info_2(printer);
3280 if (!alloc_buffer_size(buffer, *needed)) {
3281 free_printer_info_2(printer);
3282 return ERROR_INSUFFICIENT_BUFFER;
3285 /* fill the buffer with the structures */
3286 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3287 free_printer_info_2(printer);
3288 return ERROR_NOT_ENOUGH_MEMORY;
3291 /* clear memory */
3292 free_printer_info_2(printer);
3294 if (*needed > offered) {
3295 return ERROR_INSUFFICIENT_BUFFER;
3297 else
3298 return NT_STATUS_NO_PROBLEMO;
3301 /****************************************************************************
3302 ****************************************************************************/
3303 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3305 PRINTER_INFO_3 *printer=NULL;
3307 if (!construct_printer_info_3(&printer, snum))
3308 return ERROR_NOT_ENOUGH_MEMORY;
3310 /* check the required size. */
3311 *needed += spoolss_size_printer_info_3(printer);
3313 if (!alloc_buffer_size(buffer, *needed)) {
3314 free_printer_info_3(printer);
3315 return ERROR_INSUFFICIENT_BUFFER;
3318 /* fill the buffer with the structures */
3319 smb_io_printer_info_3("", buffer, printer, 0);
3321 /* clear memory */
3322 free_printer_info_3(printer);
3324 if (*needed > offered) {
3325 return ERROR_INSUFFICIENT_BUFFER;
3327 else
3328 return NT_STATUS_NO_PROBLEMO;
3331 /****************************************************************************
3332 ****************************************************************************/
3334 uint32 _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3336 POLICY_HND *handle = &q_u->handle;
3337 uint32 level = q_u->level;
3338 NEW_BUFFER *buffer = NULL;
3339 uint32 offered = q_u->offered;
3340 uint32 *needed = &r_u->needed;
3342 int snum;
3344 /* that's an [in out] buffer */
3345 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3346 buffer = r_u->buffer;
3348 *needed=0;
3350 if (!get_printer_snum(p, handle, &snum))
3351 return ERROR_INVALID_HANDLE;
3353 switch (level) {
3354 case 0:
3355 return getprinter_level_0(snum, buffer, offered, needed);
3356 case 1:
3357 return getprinter_level_1(snum, buffer, offered, needed);
3358 case 2:
3359 return getprinter_level_2(snum, buffer, offered, needed);
3360 case 3:
3361 return getprinter_level_3(snum, buffer, offered, needed);
3362 default:
3363 return ERROR_INVALID_LEVEL;
3367 /********************************************************************
3368 * fill a DRIVER_INFO_1 struct
3369 ********************************************************************/
3370 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3372 init_unistr( &info->name, driver.info_3->name);
3375 /********************************************************************
3376 * construct_printer_driver_info_1
3377 ********************************************************************/
3378 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3380 NT_PRINTER_INFO_LEVEL *printer = NULL;
3381 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3383 ZERO_STRUCT(driver);
3385 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3386 return ERROR_INVALID_PRINTER_NAME;
3388 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3389 return ERROR_UNKNOWN_PRINTER_DRIVER;
3391 fill_printer_driver_info_1(info, driver, servername, architecture);
3393 free_a_printer(&printer,2);
3395 return NT_STATUS_NO_PROBLEMO;
3398 /********************************************************************
3399 * construct_printer_driver_info_2
3400 * fill a printer_info_2 struct
3401 ********************************************************************/
3402 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3404 pstring temp;
3406 info->version=driver.info_3->cversion;
3408 init_unistr( &info->name, driver.info_3->name );
3409 init_unistr( &info->architecture, driver.info_3->environment );
3412 if (strlen(driver.info_3->driverpath)) {
3413 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3414 init_unistr( &info->driverpath, temp );
3415 } else
3416 init_unistr( &info->driverpath, "" );
3418 if (strlen(driver.info_3->datafile)) {
3419 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3420 init_unistr( &info->datafile, temp );
3421 } else
3422 init_unistr( &info->datafile, "" );
3424 if (strlen(driver.info_3->configfile)) {
3425 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3426 init_unistr( &info->configfile, temp );
3427 } else
3428 init_unistr( &info->configfile, "" );
3431 /********************************************************************
3432 * construct_printer_driver_info_2
3433 * fill a printer_info_2 struct
3434 ********************************************************************/
3435 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3437 NT_PRINTER_INFO_LEVEL *printer = NULL;
3438 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3440 ZERO_STRUCT(printer);
3441 ZERO_STRUCT(driver);
3443 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3444 return ERROR_INVALID_PRINTER_NAME;
3446 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3447 return ERROR_UNKNOWN_PRINTER_DRIVER;
3449 fill_printer_driver_info_2(info, driver, servername);
3451 free_a_printer(&printer,2);
3453 return NT_STATUS_NO_PROBLEMO;
3456 /********************************************************************
3457 * copy a strings array and convert to UNICODE
3459 * convert an array of ascii string to a UNICODE string
3460 ********************************************************************/
3461 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3463 int i=0;
3464 int j=0;
3465 char *v;
3466 pstring line;
3468 DEBUG(6,("init_unistr_array\n"));
3469 *uni_array=NULL;
3471 while (1) {
3472 if (char_array == NULL)
3473 v = "";
3474 else {
3475 v = char_array[i];
3476 if (!v) v = ""; /* hack to handle null lists */
3478 if (strlen(v) == 0) break;
3479 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3480 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3481 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3482 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3483 return;
3485 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3486 i++;
3489 if (*uni_array) {
3490 (*uni_array)[j]=0x0000;
3493 DEBUGADD(6,("last one:done\n"));
3496 /********************************************************************
3497 * construct_printer_info_3
3498 * fill a printer_info_3 struct
3499 ********************************************************************/
3500 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3502 pstring temp;
3504 ZERO_STRUCTP(info);
3506 info->version=driver.info_3->cversion;
3508 init_unistr( &info->name, driver.info_3->name );
3509 init_unistr( &info->architecture, driver.info_3->environment );
3511 if (strlen(driver.info_3->driverpath)) {
3512 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3513 init_unistr( &info->driverpath, temp );
3514 } else
3515 init_unistr( &info->driverpath, "" );
3517 if (strlen(driver.info_3->datafile)) {
3518 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3519 init_unistr( &info->datafile, temp );
3520 } else
3521 init_unistr( &info->datafile, "" );
3523 if (strlen(driver.info_3->configfile)) {
3524 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3525 init_unistr( &info->configfile, temp );
3526 } else
3527 init_unistr( &info->configfile, "" );
3529 if (strlen(driver.info_3->helpfile)) {
3530 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3531 init_unistr( &info->helpfile, temp );
3532 } else
3533 init_unistr( &info->helpfile, "" );
3535 init_unistr( &info->monitorname, driver.info_3->monitorname );
3536 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3538 info->dependentfiles=NULL;
3539 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3542 /********************************************************************
3543 * construct_printer_info_3
3544 * fill a printer_info_3 struct
3545 ********************************************************************/
3546 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3548 NT_PRINTER_INFO_LEVEL *printer = NULL;
3549 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3550 uint32 status=0;
3551 ZERO_STRUCT(driver);
3553 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3554 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3555 if (status != 0)
3556 return ERROR_INVALID_PRINTER_NAME;
3558 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3559 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3560 if (status != 0) {
3561 free_a_printer(&printer,2);
3562 return ERROR_UNKNOWN_PRINTER_DRIVER;
3565 fill_printer_driver_info_3(info, driver, servername);
3567 free_a_printer(&printer,2);
3569 return NT_STATUS_NO_PROBLEMO;
3572 /********************************************************************
3573 * construct_printer_info_6
3574 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3575 ********************************************************************/
3577 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3579 pstring temp;
3580 fstring nullstr;
3582 ZERO_STRUCTP(info);
3583 memset(&nullstr, '\0', sizeof(fstring));
3585 info->version=driver.info_3->cversion;
3587 init_unistr( &info->name, driver.info_3->name );
3588 init_unistr( &info->architecture, driver.info_3->environment );
3590 if (strlen(driver.info_3->driverpath)) {
3591 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3592 init_unistr( &info->driverpath, temp );
3593 } else
3594 init_unistr( &info->driverpath, "" );
3596 if (strlen(driver.info_3->datafile)) {
3597 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3598 init_unistr( &info->datafile, temp );
3599 } else
3600 init_unistr( &info->datafile, "" );
3602 if (strlen(driver.info_3->configfile)) {
3603 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3604 init_unistr( &info->configfile, temp );
3605 } else
3606 init_unistr( &info->configfile, "" );
3608 if (strlen(driver.info_3->helpfile)) {
3609 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3610 init_unistr( &info->helpfile, temp );
3611 } else
3612 init_unistr( &info->helpfile, "" );
3614 init_unistr( &info->monitorname, driver.info_3->monitorname );
3615 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3617 info->dependentfiles=NULL;
3618 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3620 info->previousdrivernames=NULL;
3621 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3623 info->driver_date.low=0;
3624 info->driver_date.high=0;
3626 info->padding=0;
3627 info->driver_version_low=0;
3628 info->driver_version_high=0;
3630 init_unistr( &info->mfgname, "");
3631 init_unistr( &info->oem_url, "");
3632 init_unistr( &info->hardware_id, "");
3633 init_unistr( &info->provider, "");
3636 /********************************************************************
3637 * construct_printer_info_6
3638 * fill a printer_info_6 struct
3639 ********************************************************************/
3640 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3642 NT_PRINTER_INFO_LEVEL *printer = NULL;
3643 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3644 uint32 status=0;
3645 ZERO_STRUCT(driver);
3647 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3648 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3649 if (status != 0)
3650 return ERROR_INVALID_PRINTER_NAME;
3652 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3653 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3654 if (status != 0) {
3656 * Is this a W2k client ?
3659 if (version < 3) {
3660 free_a_printer(&printer,2);
3661 return ERROR_UNKNOWN_PRINTER_DRIVER;
3664 /* Yes - try again with a WinNT driver. */
3665 version = 2;
3666 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3667 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3668 if (status != 0) {
3669 free_a_printer(&printer,2);
3670 return ERROR_UNKNOWN_PRINTER_DRIVER;
3674 fill_printer_driver_info_6(info, driver, servername);
3676 free_a_printer(&printer,2);
3678 return NT_STATUS_NO_PROBLEMO;
3681 /****************************************************************************
3682 ****************************************************************************/
3684 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3686 safe_free(info->dependentfiles);
3689 /****************************************************************************
3690 ****************************************************************************/
3692 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3694 safe_free(info->dependentfiles);
3698 /****************************************************************************
3699 ****************************************************************************/
3700 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3702 DRIVER_INFO_1 *info=NULL;
3703 uint32 status;
3705 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3706 return ERROR_NOT_ENOUGH_MEMORY;
3708 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3709 if (status != NT_STATUS_NO_PROBLEMO) {
3710 safe_free(info);
3711 return status;
3714 /* check the required size. */
3715 *needed += spoolss_size_printer_driver_info_1(info);
3717 if (!alloc_buffer_size(buffer, *needed)) {
3718 safe_free(info);
3719 return ERROR_INSUFFICIENT_BUFFER;
3722 /* fill the buffer with the structures */
3723 smb_io_printer_driver_info_1("", buffer, info, 0);
3725 /* clear memory */
3726 safe_free(info);
3728 if (*needed > offered)
3729 return ERROR_INSUFFICIENT_BUFFER;
3730 else
3731 return NT_STATUS_NO_PROBLEMO;
3734 /****************************************************************************
3735 ****************************************************************************/
3736 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3738 DRIVER_INFO_2 *info=NULL;
3739 uint32 status;
3741 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3742 return ERROR_NOT_ENOUGH_MEMORY;
3744 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3745 if (status != NT_STATUS_NO_PROBLEMO) {
3746 safe_free(info);
3747 return status;
3750 /* check the required size. */
3751 *needed += spoolss_size_printer_driver_info_2(info);
3753 if (!alloc_buffer_size(buffer, *needed)) {
3754 safe_free(info);
3755 return ERROR_INSUFFICIENT_BUFFER;
3758 /* fill the buffer with the structures */
3759 smb_io_printer_driver_info_2("", buffer, info, 0);
3761 /* clear memory */
3762 safe_free(info);
3764 if (*needed > offered)
3765 return ERROR_INSUFFICIENT_BUFFER;
3766 else
3767 return NT_STATUS_NO_PROBLEMO;
3770 /****************************************************************************
3771 ****************************************************************************/
3772 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3774 DRIVER_INFO_3 info;
3775 uint32 status;
3777 ZERO_STRUCT(info);
3779 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3780 if (status != NT_STATUS_NO_PROBLEMO) {
3781 return status;
3784 /* check the required size. */
3785 *needed += spoolss_size_printer_driver_info_3(&info);
3787 if (!alloc_buffer_size(buffer, *needed)) {
3788 free_printer_driver_info_3(&info);
3789 return ERROR_INSUFFICIENT_BUFFER;
3792 /* fill the buffer with the structures */
3793 smb_io_printer_driver_info_3("", buffer, &info, 0);
3795 free_printer_driver_info_3(&info);
3797 if (*needed > offered)
3798 return ERROR_INSUFFICIENT_BUFFER;
3799 else
3800 return NT_STATUS_NO_PROBLEMO;
3803 /****************************************************************************
3804 ****************************************************************************/
3805 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3807 DRIVER_INFO_6 info;
3808 uint32 status;
3810 ZERO_STRUCT(info);
3812 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3813 if (status != NT_STATUS_NO_PROBLEMO) {
3814 return status;
3817 /* check the required size. */
3818 *needed += spoolss_size_printer_driver_info_6(&info);
3820 if (!alloc_buffer_size(buffer, *needed)) {
3821 free_printer_driver_info_6(&info);
3822 return ERROR_INSUFFICIENT_BUFFER;
3825 /* fill the buffer with the structures */
3826 smb_io_printer_driver_info_6("", buffer, &info, 0);
3828 free_printer_driver_info_6(&info);
3830 if (*needed > offered)
3831 return ERROR_INSUFFICIENT_BUFFER;
3832 else
3833 return NT_STATUS_NO_PROBLEMO;
3836 /****************************************************************************
3837 ****************************************************************************/
3839 uint32 _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3841 POLICY_HND *handle = &q_u->handle;
3842 UNISTR2 *uni_arch = &q_u->architecture;
3843 uint32 level = q_u->level;
3844 uint32 clientmajorversion = q_u->clientmajorversion;
3845 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3846 NEW_BUFFER *buffer = NULL;
3847 uint32 offered = q_u->offered;
3848 uint32 *needed = &r_u->needed;
3849 uint32 *servermajorversion = &r_u->servermajorversion;
3850 uint32 *serverminorversion = &r_u->serverminorversion;
3852 fstring servername;
3853 fstring architecture;
3854 int snum;
3856 /* that's an [in out] buffer */
3857 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3858 buffer = r_u->buffer;
3860 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3862 *needed=0;
3863 *servermajorversion=0;
3864 *serverminorversion=0;
3866 pstrcpy(servername, global_myname);
3867 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3869 if (!get_printer_snum(p, handle, &snum))
3870 return ERROR_INVALID_HANDLE;
3872 switch (level) {
3873 case 1:
3874 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3875 case 2:
3876 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3877 case 3:
3878 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3879 case 6:
3880 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3881 default:
3882 return ERROR_INVALID_LEVEL;
3886 /****************************************************************************
3887 ****************************************************************************/
3889 uint32 _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
3891 POLICY_HND *handle = &q_u->handle;
3893 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3895 if (Printer) {
3896 Printer->page_started=True;
3897 return 0x0;
3900 DEBUG(3,("Error in startpageprinter printer handle\n"));
3901 return ERROR_INVALID_HANDLE;
3904 /****************************************************************************
3905 ****************************************************************************/
3907 uint32 _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
3909 POLICY_HND *handle = &q_u->handle;
3911 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3913 if (!Printer) {
3914 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3915 return ERROR_INVALID_HANDLE;
3918 Printer->page_started=False;
3920 return NT_STATUS_NO_PROBLEMO;
3923 /********************************************************************
3924 * api_spoolss_getprinter
3925 * called from the spoolss dispatcher
3927 ********************************************************************/
3929 uint32 _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
3931 POLICY_HND *handle = &q_u->handle;
3932 /* uint32 level = q_u->doc_info_container.level; - notused. */
3933 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
3934 uint32 *jobid = &r_u->jobid;
3936 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3937 int snum;
3938 pstring jobname;
3939 fstring datatype;
3940 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3941 struct current_user user;
3943 if (!Printer) {
3944 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3945 return ERROR_INVALID_HANDLE;
3948 get_current_user(&user, p);
3951 * a nice thing with NT is it doesn't listen to what you tell it.
3952 * when asked to send _only_ RAW datas, it tries to send datas
3953 * in EMF format.
3955 * So I add checks like in NT Server ...
3957 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3958 * there's a bug in NT client-side code, so we'll fix it in the
3959 * server-side code. *nnnnnggggh!*
3962 if (info_1->p_datatype != 0) {
3963 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3964 if (strcmp(datatype, "RAW") != 0) {
3965 (*jobid)=0;
3966 return ERROR_INVALID_DATATYPE;
3970 /* get the share number of the printer */
3971 if (!get_printer_snum(p, handle, &snum)) {
3972 return ERROR_INVALID_HANDLE;
3975 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3977 Printer->jobid = print_job_start(&user, snum, jobname);
3979 /* An error occured in print_job_start() so return an appropriate
3980 NT error code. */
3982 if (Printer->jobid == -1) {
3983 return map_nt_error_from_unix(errno);
3986 Printer->document_started=True;
3987 (*jobid) = Printer->jobid;
3989 return 0x0;
3992 /********************************************************************
3993 * api_spoolss_getprinter
3994 * called from the spoolss dispatcher
3996 ********************************************************************/
3998 uint32 _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4000 POLICY_HND *handle = &q_u->handle;
4002 return _spoolss_enddocprinter_internal(p, handle);
4005 /****************************************************************************
4006 ****************************************************************************/
4008 uint32 _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4010 POLICY_HND *handle = &q_u->handle;
4011 uint32 buffer_size = q_u->buffer_size;
4012 uint8 *buffer = q_u->buffer;
4013 uint32 *buffer_written = &q_u->buffer_size2;
4015 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4017 if (!Printer) {
4018 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
4019 r_u->buffer_written = q_u->buffer_size2;
4020 return ERROR_INVALID_HANDLE;
4023 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4026 r_u->buffer_written = q_u->buffer_size2;
4028 return 0x0;
4031 /********************************************************************
4032 * api_spoolss_getprinter
4033 * called from the spoolss dispatcher
4035 ********************************************************************/
4036 static uint32 control_printer(POLICY_HND *handle, uint32 command,
4037 pipes_struct *p)
4039 struct current_user user;
4040 int snum, errcode = ERROR_INVALID_FUNCTION;
4041 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4043 get_current_user(&user, p);
4045 if (!Printer) {
4046 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4047 return ERROR_INVALID_HANDLE;
4050 if (!get_printer_snum(p, handle, &snum))
4051 return ERROR_INVALID_HANDLE;
4053 switch (command) {
4054 case PRINTER_CONTROL_PAUSE:
4055 if (print_queue_pause(&user, snum, &errcode)) {
4056 errcode = 0;
4058 break;
4059 case PRINTER_CONTROL_RESUME:
4060 case PRINTER_CONTROL_UNPAUSE:
4061 if (print_queue_resume(&user, snum, &errcode)) {
4062 errcode = 0;
4064 break;
4065 case PRINTER_CONTROL_PURGE:
4066 if (print_queue_purge(&user, snum, &errcode)) {
4067 errcode = 0;
4069 break;
4070 default:
4071 return ERROR_INVALID_LEVEL;
4074 return errcode;
4077 /********************************************************************
4078 * api_spoolss_abortprinter
4079 ********************************************************************/
4081 uint32 _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4083 POLICY_HND *handle = &q_u->handle;
4085 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4088 /********************************************************************
4089 * called by spoolss_api_setprinter
4090 * when updating a printer description
4091 ********************************************************************/
4092 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
4093 const SPOOL_PRINTER_INFO_LEVEL *info,
4094 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4096 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4097 struct current_user user;
4098 uint32 result;
4099 int snum;
4101 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4103 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4104 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4105 OUR_HANDLE(handle)));
4107 result = ERROR_INVALID_HANDLE;
4108 goto done;
4111 /* NT seems to like setting the security descriptor even though
4112 nothing may have actually changed. This causes annoying
4113 dialog boxes when the user doesn't have permission to change
4114 the security descriptor. */
4116 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4118 if (DEBUGLEVEL >= 10) {
4119 SEC_ACL *the_acl;
4120 int i;
4122 the_acl = old_secdesc_ctr->sec->dacl;
4123 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4124 PRINTERNAME(snum), the_acl->num_aces));
4126 for (i = 0; i < the_acl->num_aces; i++) {
4127 fstring sid_str;
4129 sid_to_string(sid_str, &the_acl->ace[i].sid);
4131 DEBUG(10, ("%s 0x%08x\n", sid_str,
4132 the_acl->ace[i].info.mask));
4135 the_acl = secdesc_ctr->sec->dacl;
4137 if (the_acl) {
4138 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4139 PRINTERNAME(snum), the_acl->num_aces));
4141 for (i = 0; i < the_acl->num_aces; i++) {
4142 fstring sid_str;
4144 sid_to_string(sid_str, &the_acl->ace[i].sid);
4146 DEBUG(10, ("%s 0x%08x\n", sid_str,
4147 the_acl->ace[i].info.mask));
4149 } else {
4150 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4154 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4156 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4157 result = NT_STATUS_NO_PROBLEMO;
4158 goto done;
4161 /* Work out which user is performing the operation */
4163 get_current_user(&user, p);
4165 /* Check the user has permissions to change the security
4166 descriptor. By experimentation with two NT machines, the user
4167 requires Full Access to the printer to change security
4168 information. */
4170 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4171 result = ERROR_ACCESS_DENIED;
4172 goto done;
4175 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4177 done:
4179 return result;
4182 /********************************************************************
4183 Do Samba sanity checks on a printer info struct.
4184 this has changed purpose: it now "canonicalises" printer
4185 info from a client rather than just checking it is correct
4186 ********************************************************************/
4188 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4190 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4191 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4193 /* we force some elements to "correct" values */
4194 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4195 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4196 global_myname, lp_servicename(snum));
4197 fstrcpy(info->sharename, lp_servicename(snum));
4198 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4199 | PRINTER_ATTRIBUTE_LOCAL \
4200 | PRINTER_ATTRIBUTE_RAW_ONLY \
4201 | PRINTER_ATTRIBUTE_QUEUED ;
4203 return True;
4206 /****************************************************************************
4207 ****************************************************************************/
4208 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4210 char *cmd = lp_addprinter_cmd();
4211 char *path;
4212 char **qlines;
4213 pstring command;
4214 pstring driverlocation;
4215 int numlines;
4216 int ret;
4217 int fd;
4219 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4220 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4221 else
4222 path = lp_lockdir();
4224 /* build driver path... only 9X architecture is needed for legacy reasons */
4225 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4226 global_myname);
4227 /* change \ to \\ for the shell */
4228 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4230 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4231 cmd, printer->info_2->printername, printer->info_2->sharename,
4232 printer->info_2->portname, printer->info_2->drivername,
4233 printer->info_2->location, driverlocation);
4235 /* Convert script args to unix-codepage */
4236 dos_to_unix(command, True);
4237 DEBUG(10,("Running [%s]\n", command));
4238 ret = smbrun(command, &fd);
4239 DEBUGADD(10,("returned [%d]\n", ret));
4241 if ( ret != 0 ) {
4242 if (fd != -1)
4243 close(fd);
4244 return False;
4247 numlines = 0;
4248 /* Get lines and convert them back to dos-codepage */
4249 qlines = fd_lines_load(fd, &numlines, True);
4250 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4251 close(fd);
4253 if(numlines) {
4254 /* Set the portname to what the script says the portname should be. */
4255 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4256 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4258 /* Send SIGHUP to process group... is there a better way? */
4259 kill(0, SIGHUP);
4260 add_all_printers();
4263 file_lines_free(qlines);
4264 return True;
4267 /* Return true if two devicemodes are equal */
4269 #define DEVMODE_CHECK_INT(field) \
4270 if (d1->field != d2->field) { \
4271 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4272 d1->field, d2->field)); \
4273 return False; \
4276 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4278 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4280 if (!d1 ^ !d2) {
4281 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4282 return False; /* if either is exclusively NULL are not equal */
4285 if (!strequal(d1->devicename, d2->devicename)) {
4286 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4287 return False;
4290 if (!strequal(d1->formname, d2->formname)) {
4291 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4292 return False;
4295 DEVMODE_CHECK_INT(specversion);
4296 DEVMODE_CHECK_INT(driverversion);
4297 DEVMODE_CHECK_INT(driverextra);
4298 DEVMODE_CHECK_INT(orientation);
4299 DEVMODE_CHECK_INT(papersize);
4300 DEVMODE_CHECK_INT(paperlength);
4301 DEVMODE_CHECK_INT(paperwidth);
4302 DEVMODE_CHECK_INT(scale);
4303 DEVMODE_CHECK_INT(copies);
4304 DEVMODE_CHECK_INT(defaultsource);
4305 DEVMODE_CHECK_INT(printquality);
4306 DEVMODE_CHECK_INT(color);
4307 DEVMODE_CHECK_INT(duplex);
4308 DEVMODE_CHECK_INT(yresolution);
4309 DEVMODE_CHECK_INT(ttoption);
4310 DEVMODE_CHECK_INT(collate);
4311 DEVMODE_CHECK_INT(logpixels);
4313 DEVMODE_CHECK_INT(fields);
4314 DEVMODE_CHECK_INT(bitsperpel);
4315 DEVMODE_CHECK_INT(pelswidth);
4316 DEVMODE_CHECK_INT(pelsheight);
4317 DEVMODE_CHECK_INT(displayflags);
4318 DEVMODE_CHECK_INT(displayfrequency);
4319 DEVMODE_CHECK_INT(icmmethod);
4320 DEVMODE_CHECK_INT(icmintent);
4321 DEVMODE_CHECK_INT(mediatype);
4322 DEVMODE_CHECK_INT(dithertype);
4323 DEVMODE_CHECK_INT(reserved1);
4324 DEVMODE_CHECK_INT(reserved2);
4325 DEVMODE_CHECK_INT(panningwidth);
4326 DEVMODE_CHECK_INT(panningheight);
4328 /* compare the private data if it exists */
4329 if (!d1->driverextra && !d2->driverextra) goto equal;
4332 DEVMODE_CHECK_INT(driverextra);
4334 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4335 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4336 return False;
4339 equal:
4340 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4341 return True;
4344 /* Return true if two NT_PRINTER_PARAM structures are equal */
4346 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4347 NT_PRINTER_PARAM *p2)
4349 if (!p1 && !p2) goto equal;
4351 if ((!p1 && p2) || (p1 && !p2)) {
4352 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4353 return False;
4356 /* Compare lists of printer parameters */
4358 while (p1) {
4359 BOOL found = False;
4360 NT_PRINTER_PARAM *q = p1;
4362 /* Find the parameter in the second structure */
4364 while(q) {
4366 if (strequal(p1->value, q->value)) {
4368 if (p1->type != q->type) {
4369 DEBUG(10, ("nt_printer_param_equal():"
4370 "types for %s differ (%d != %d)\n",
4371 p1->value, p1->type,
4372 q->type));
4373 break;
4376 if (p1->data_len != q->data_len) {
4377 DEBUG(10, ("nt_printer_param_equal():"
4378 "len for %s differs (%d != %d)\n",
4379 p1->value, p1->data_len,
4380 q->data_len));
4381 break;
4384 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4385 found = True;
4386 } else {
4387 DEBUG(10, ("nt_printer_param_equal():"
4388 "data for %s differs\n", p1->value));
4391 break;
4394 q = q->next;
4397 if (!found) {
4398 DEBUG(10, ("nt_printer_param_equal(): param %s "
4399 "does not exist\n", p1->value));
4400 return False;
4403 p1 = p1->next;
4406 equal:
4408 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4409 return True;
4412 /********************************************************************
4413 * Called by update_printer when trying to work out whether to
4414 * actually update printer info.
4415 ********************************************************************/
4417 #define PI_CHECK_INT(field) \
4418 if (pi1->field != pi2->field) { \
4419 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4420 pi1->field, pi2->field)); \
4421 return False; \
4424 #define PI_CHECK_STR(field) \
4425 if (!strequal(pi1->field, pi2->field)) { \
4426 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4427 pi1->field, pi2->field)); \
4428 return False; \
4431 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4432 NT_PRINTER_INFO_LEVEL *p2)
4434 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4436 /* Trivial conditions */
4438 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4439 goto equal;
4442 if ((!p1 && p2) || (p1 && !p2) ||
4443 (!p1->info_2 && p2->info_2) ||
4444 (p1->info_2 && !p2->info_2)) {
4445 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4446 "differ\n"));
4447 return False;
4450 /* Compare two nt_printer_info_level structures. Don't compare
4451 status or cjobs as they seem to have something to do with the
4452 printer queue. */
4454 pi1 = p1->info_2;
4455 pi2 = p2->info_2;
4457 /* Don't check the attributes as we stomp on the value in
4458 check_printer_ok() anyway. */
4460 #if 0
4461 PI_CHECK_INT(attributes);
4462 #endif
4464 PI_CHECK_INT(priority);
4465 PI_CHECK_INT(default_priority);
4466 PI_CHECK_INT(starttime);
4467 PI_CHECK_INT(untiltime);
4468 PI_CHECK_INT(averageppm);
4470 /* Yuck - don't check the printername or servername as the
4471 add_a_printer() code plays games with them. You can't
4472 change the printername or the sharename through this interface
4473 in Samba. */
4475 PI_CHECK_STR(sharename);
4476 PI_CHECK_STR(portname);
4477 PI_CHECK_STR(drivername);
4478 PI_CHECK_STR(comment);
4479 PI_CHECK_STR(location);
4481 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4482 return False;
4485 PI_CHECK_STR(sepfile);
4486 PI_CHECK_STR(printprocessor);
4487 PI_CHECK_STR(datatype);
4488 PI_CHECK_STR(parameters);
4490 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4491 return False;
4494 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4495 return False;
4498 PI_CHECK_INT(changeid);
4499 PI_CHECK_INT(c_setprinter);
4500 PI_CHECK_INT(setuptime);
4502 equal:
4503 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4504 return True;
4507 /********************************************************************
4508 * called by spoolss_api_setprinter
4509 * when updating a printer description
4510 ********************************************************************/
4512 static uint32 update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4513 const SPOOL_PRINTER_INFO_LEVEL *info,
4514 DEVICEMODE *devmode)
4516 int snum;
4517 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4518 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4519 uint32 result;
4521 DEBUG(8,("update_printer\n"));
4523 result = NT_STATUS_NO_PROBLEMO;
4525 if (level!=2) {
4526 DEBUG(0,("Send a mail to samba@samba.org\n"));
4527 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4528 result = ERROR_INVALID_LEVEL;
4529 goto done;
4532 if (!Printer) {
4533 result = ERROR_INVALID_HANDLE;
4534 goto done;
4537 if (!get_printer_snum(p, handle, &snum)) {
4538 result = ERROR_INVALID_HANDLE;
4539 goto done;
4542 if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4543 (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4544 result = ERROR_INVALID_HANDLE;
4545 goto done;
4548 DEBUGADD(8,("Converting info_2 struct\n"));
4551 * convert_printer_info converts the incoming
4552 * info from the client and overwrites the info
4553 * just read from the tdb in the pointer 'printer'.
4556 convert_printer_info(info, printer, level);
4558 if (info->info_2->devmode_ptr != 0) {
4559 /* we have a valid devmode
4560 convert it and link it*/
4562 DEBUGADD(8,("Converting the devicemode struct\n"));
4563 if (!convert_devicemode(printer->info_2->printername, devmode,
4564 &printer->info_2->devmode)) {
4565 result = ERROR_NOT_ENOUGH_MEMORY;
4566 goto done;
4570 /* Do sanity check on the requested changes for Samba */
4572 if (!check_printer_ok(printer->info_2, snum)) {
4573 result = ERROR_INVALID_PARAMETER;
4574 goto done;
4577 /* NT likes to call this function even though nothing has actually
4578 changed. Check this so the user doesn't end up with an
4579 annoying permission denied dialog box. */
4581 if (nt_printer_info_level_equal(printer, old_printer)) {
4582 DEBUG(3, ("printer info has not changed\n"));
4583 result = NT_STATUS_NO_PROBLEMO;
4584 goto done;
4587 /* Check calling user has permission to update printer description */
4589 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4590 DEBUG(3, ("printer property change denied by security "
4591 "descriptor\n"));
4592 result = ERROR_ACCESS_DENIED;
4593 goto done;
4596 /* Call addprinter hook */
4598 if (*lp_addprinter_cmd() )
4599 if ( !add_printer_hook(printer) ) {
4600 result = ERROR_ACCESS_DENIED;
4601 goto done;
4604 /* Update printer info */
4606 if (add_a_printer(*printer, 2)!=0) {
4607 /* I don't really know what to return here !!! */
4608 result = ERROR_ACCESS_DENIED;
4609 goto done;
4612 done:
4613 free_a_printer(&printer, 2);
4614 free_a_printer(&old_printer, 2);
4616 srv_spoolss_sendnotify(p, handle);
4618 return result;
4621 /****************************************************************************
4622 ****************************************************************************/
4624 uint32 _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4626 POLICY_HND *handle = &q_u->handle;
4627 uint32 level = q_u->level;
4628 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4629 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4630 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4631 uint32 command = q_u->command;
4633 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4635 if (!Printer) {
4636 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4637 return ERROR_INVALID_HANDLE;
4640 /* check the level */
4641 switch (level) {
4642 case 0:
4643 return control_printer(handle, command, p);
4644 case 2:
4645 return update_printer(p, handle, level, info, devmode_ctr.devmode);
4646 case 3:
4647 return update_printer_sec(handle, level, info, p,
4648 secdesc_ctr);
4649 default:
4650 return ERROR_INVALID_LEVEL;
4654 /****************************************************************************
4655 ****************************************************************************/
4657 uint32 _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4659 POLICY_HND *handle = &q_u->handle;
4661 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4663 if (!Printer) {
4664 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4665 return ERROR_INVALID_HANDLE;
4668 if (Printer->notify.client_connected==True)
4669 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4671 Printer->notify.flags=0;
4672 Printer->notify.options=0;
4673 Printer->notify.localmachine[0]='\0';
4674 Printer->notify.printerlocal=0;
4675 if (Printer->notify.option)
4676 free_spool_notify_option(&Printer->notify.option);
4677 Printer->notify.client_connected=False;
4679 return NT_STATUS_NO_PROBLEMO;
4682 /****************************************************************************
4683 ****************************************************************************/
4685 uint32 _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4687 /* that's an [in out] buffer (despite appearences to the contrary) */
4688 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4690 r_u->needed = 0;
4691 return ERROR_INVALID_PARAMETER; /* this is what a NT server
4692 returns for AddJob. AddJob
4693 must fail on non-local
4694 printers */
4697 /****************************************************************************
4698 ****************************************************************************/
4699 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4700 int position, int snum)
4702 pstring temp_name;
4704 struct tm *t;
4706 t=gmtime(&queue->time);
4707 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4709 job_info->jobid=queue->job;
4710 init_unistr(&job_info->printername, lp_servicename(snum));
4711 init_unistr(&job_info->machinename, temp_name);
4712 init_unistr(&job_info->username, queue->user);
4713 init_unistr(&job_info->document, queue->file);
4714 init_unistr(&job_info->datatype, "RAW");
4715 init_unistr(&job_info->text_status, "");
4716 job_info->status=nt_printj_status(queue->status);
4717 job_info->priority=queue->priority;
4718 job_info->position=position;
4719 job_info->totalpages=0;
4720 job_info->pagesprinted=0;
4722 make_systemtime(&job_info->submitted, t);
4725 /****************************************************************************
4726 ****************************************************************************/
4727 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4728 int position, int snum,
4729 NT_PRINTER_INFO_LEVEL *ntprinter)
4731 pstring temp_name;
4732 pstring chaine;
4733 struct tm *t;
4735 t=gmtime(&queue->time);
4736 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4738 job_info->jobid=queue->job;
4740 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4742 init_unistr(&job_info->printername, chaine);
4744 init_unistr(&job_info->machinename, temp_name);
4745 init_unistr(&job_info->username, queue->user);
4746 init_unistr(&job_info->document, queue->file);
4747 init_unistr(&job_info->notifyname, queue->user);
4748 init_unistr(&job_info->datatype, "RAW");
4749 init_unistr(&job_info->printprocessor, "winprint");
4750 init_unistr(&job_info->parameters, "");
4751 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4752 init_unistr(&job_info->text_status, "");
4754 /* and here the security descriptor */
4756 job_info->status=nt_printj_status(queue->status);
4757 job_info->priority=queue->priority;
4758 job_info->position=position;
4759 job_info->starttime=0;
4760 job_info->untiltime=0;
4761 job_info->totalpages=0;
4762 job_info->size=queue->size;
4763 make_systemtime(&(job_info->submitted), t);
4764 job_info->timeelapsed=0;
4765 job_info->pagesprinted=0;
4767 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4768 return False;
4771 return (True);
4774 /****************************************************************************
4775 Enumjobs at level 1.
4776 ****************************************************************************/
4777 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4778 NEW_BUFFER *buffer, uint32 offered,
4779 uint32 *needed, uint32 *returned)
4781 JOB_INFO_1 *info;
4782 int i;
4784 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4785 if (info==NULL) {
4786 safe_free(queue);
4787 *returned=0;
4788 return ERROR_NOT_ENOUGH_MEMORY;
4791 for (i=0; i<*returned; i++)
4792 fill_job_info_1(&info[i], &queue[i], i, snum);
4794 safe_free(queue);
4796 /* check the required size. */
4797 for (i=0; i<*returned; i++)
4798 (*needed) += spoolss_size_job_info_1(&info[i]);
4800 if (!alloc_buffer_size(buffer, *needed)) {
4801 safe_free(info);
4802 return ERROR_INSUFFICIENT_BUFFER;
4805 /* fill the buffer with the structures */
4806 for (i=0; i<*returned; i++)
4807 smb_io_job_info_1("", buffer, &info[i], 0);
4809 /* clear memory */
4810 safe_free(info);
4812 if (*needed > offered) {
4813 *returned=0;
4814 return ERROR_INSUFFICIENT_BUFFER;
4816 else
4817 return NT_STATUS_NO_PROBLEMO;
4820 /****************************************************************************
4821 Enumjobs at level 2.
4822 ****************************************************************************/
4823 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4824 NEW_BUFFER *buffer, uint32 offered,
4825 uint32 *needed, uint32 *returned)
4827 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4828 JOB_INFO_2 *info;
4829 int i;
4831 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4832 if (info==NULL) {
4833 *returned=0;
4834 return ERROR_NOT_ENOUGH_MEMORY;
4837 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4838 *returned = 0;
4839 return ERROR_NOT_ENOUGH_MEMORY;
4842 for (i=0; i<*returned; i++)
4843 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4845 free_a_printer(&ntprinter, 2);
4846 safe_free(queue);
4848 /* check the required size. */
4849 for (i=0; i<*returned; i++)
4850 (*needed) += spoolss_size_job_info_2(&info[i]);
4852 if (!alloc_buffer_size(buffer, *needed)) {
4853 safe_free(info);
4854 return ERROR_INSUFFICIENT_BUFFER;
4857 /* fill the buffer with the structures */
4858 for (i=0; i<*returned; i++)
4859 smb_io_job_info_2("", buffer, &info[i], 0);
4861 /* clear memory */
4862 for (i = 0; i < *returned; i++)
4863 free_job_info_2(&info[i]);
4865 free(info);
4867 if (*needed > offered) {
4868 *returned=0;
4869 return ERROR_INSUFFICIENT_BUFFER;
4871 else
4872 return NT_STATUS_NO_PROBLEMO;
4875 /****************************************************************************
4876 Enumjobs.
4877 ****************************************************************************/
4879 uint32 _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4881 POLICY_HND *handle = &q_u->handle;
4882 /* uint32 firstjob = q_u->firstjob; - notused. */
4883 /* uint32 numofjobs = q_u->numofjobs; - notused. */
4884 uint32 level = q_u->level;
4885 NEW_BUFFER *buffer = NULL;
4886 uint32 offered = q_u->offered;
4887 uint32 *needed = &r_u->needed;
4888 uint32 *returned = &r_u->returned;
4890 int snum;
4891 print_queue_struct *queue=NULL;
4892 print_status_struct prt_status;
4894 /* that's an [in out] buffer */
4895 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4896 buffer = r_u->buffer;
4898 DEBUG(4,("_spoolss_enumjobs\n"));
4900 ZERO_STRUCT(prt_status);
4902 *needed=0;
4903 *returned=0;
4905 if (!get_printer_snum(p, handle, &snum))
4906 return ERROR_INVALID_HANDLE;
4908 *returned = print_queue_status(snum, &queue, &prt_status);
4909 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4911 if (*returned == 0) {
4912 safe_free(queue);
4913 return NT_STATUS_NO_PROBLEMO;
4916 switch (level) {
4917 case 1:
4918 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4919 case 2:
4920 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4921 default:
4922 safe_free(queue);
4923 *returned=0;
4924 return ERROR_INVALID_LEVEL;
4928 /****************************************************************************
4929 ****************************************************************************/
4931 uint32 _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
4933 return 0x0;
4936 /****************************************************************************
4937 ****************************************************************************/
4939 uint32 _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
4941 POLICY_HND *handle = &q_u->handle;
4942 uint32 jobid = q_u->jobid;
4943 /* uint32 level = q_u->level; - notused. */
4944 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
4945 uint32 command = q_u->command;
4947 struct current_user user;
4948 print_status_struct prt_status;
4949 int snum, errcode = ERROR_INVALID_FUNCTION;
4951 memset(&prt_status, 0, sizeof(prt_status));
4953 if (!get_printer_snum(p, handle, &snum)) {
4954 return ERROR_INVALID_HANDLE;
4957 if (!print_job_exists(jobid)) {
4958 return ERROR_INVALID_PRINTER_NAME;
4961 get_current_user(&user, p);
4963 switch (command) {
4964 case JOB_CONTROL_CANCEL:
4965 case JOB_CONTROL_DELETE:
4966 if (print_job_delete(&user, jobid, &errcode)) {
4967 errcode = 0;
4969 break;
4970 case JOB_CONTROL_PAUSE:
4971 if (print_job_pause(&user, jobid, &errcode)) {
4972 errcode = 0;
4974 break;
4975 case JOB_CONTROL_RESTART:
4976 case JOB_CONTROL_RESUME:
4977 if (print_job_resume(&user, jobid, &errcode)) {
4978 errcode = 0;
4980 break;
4981 default:
4982 return ERROR_INVALID_LEVEL;
4985 return errcode;
4988 /****************************************************************************
4989 Enumerates all printer drivers at level 1.
4990 ****************************************************************************/
4991 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4993 int i;
4994 int ndrivers;
4995 uint32 version;
4996 fstring *list = NULL;
4998 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4999 DRIVER_INFO_1 *driver_info_1=NULL;
5001 *returned=0;
5003 #define MAX_VERSION 4
5005 for (version=0; version<MAX_VERSION; version++) {
5006 list=NULL;
5007 ndrivers=get_ntdrivers(&list, architecture, version);
5008 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5010 if(ndrivers == -1)
5011 return ERROR_NOT_ENOUGH_MEMORY;
5013 if(ndrivers != 0) {
5014 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5015 safe_free(list);
5016 return ERROR_NOT_ENOUGH_MEMORY;
5020 for (i=0; i<ndrivers; i++) {
5021 uint32 status;
5022 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5023 ZERO_STRUCT(driver);
5024 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5025 safe_free(list);
5026 return status;
5028 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5029 free_a_printer_driver(driver, 3);
5032 *returned+=ndrivers;
5033 safe_free(list);
5036 /* check the required size. */
5037 for (i=0; i<*returned; i++) {
5038 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5039 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5042 if (!alloc_buffer_size(buffer, *needed)) {
5043 safe_free(driver_info_1);
5044 return ERROR_INSUFFICIENT_BUFFER;
5047 /* fill the buffer with the driver structures */
5048 for (i=0; i<*returned; i++) {
5049 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5050 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5053 safe_free(driver_info_1);
5055 if (*needed > offered) {
5056 *returned=0;
5057 return ERROR_INSUFFICIENT_BUFFER;
5059 else
5060 return NT_STATUS_NO_PROBLEMO;
5063 /****************************************************************************
5064 Enumerates all printer drivers at level 2.
5065 ****************************************************************************/
5066 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5068 int i;
5069 int ndrivers;
5070 uint32 version;
5071 fstring *list = NULL;
5073 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5074 DRIVER_INFO_2 *driver_info_2=NULL;
5076 *returned=0;
5078 #define MAX_VERSION 4
5080 for (version=0; version<MAX_VERSION; version++) {
5081 list=NULL;
5082 ndrivers=get_ntdrivers(&list, architecture, version);
5083 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5085 if(ndrivers == -1)
5086 return ERROR_NOT_ENOUGH_MEMORY;
5088 if(ndrivers != 0) {
5089 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5090 safe_free(list);
5091 return ERROR_NOT_ENOUGH_MEMORY;
5095 for (i=0; i<ndrivers; i++) {
5096 uint32 status;
5098 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5099 ZERO_STRUCT(driver);
5100 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5101 safe_free(list);
5102 return status;
5104 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5105 free_a_printer_driver(driver, 3);
5108 *returned+=ndrivers;
5109 safe_free(list);
5112 /* check the required size. */
5113 for (i=0; i<*returned; i++) {
5114 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5115 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5118 if (!alloc_buffer_size(buffer, *needed)) {
5119 safe_free(driver_info_2);
5120 return ERROR_INSUFFICIENT_BUFFER;
5123 /* fill the buffer with the form structures */
5124 for (i=0; i<*returned; i++) {
5125 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5126 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5129 safe_free(driver_info_2);
5131 if (*needed > offered) {
5132 *returned=0;
5133 return ERROR_INSUFFICIENT_BUFFER;
5135 else
5136 return NT_STATUS_NO_PROBLEMO;
5139 /****************************************************************************
5140 Enumerates all printer drivers at level 3.
5141 ****************************************************************************/
5142 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5144 int i;
5145 int ndrivers;
5146 uint32 version;
5147 fstring *list = NULL;
5149 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5150 DRIVER_INFO_3 *driver_info_3=NULL;
5152 *returned=0;
5154 #define MAX_VERSION 4
5156 for (version=0; version<MAX_VERSION; version++) {
5157 list=NULL;
5158 ndrivers=get_ntdrivers(&list, architecture, version);
5159 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5161 if(ndrivers == -1)
5162 return ERROR_NOT_ENOUGH_MEMORY;
5164 if(ndrivers != 0) {
5165 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5166 safe_free(list);
5167 return ERROR_NOT_ENOUGH_MEMORY;
5171 for (i=0; i<ndrivers; i++) {
5172 uint32 status;
5174 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5175 ZERO_STRUCT(driver);
5176 if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5177 safe_free(list);
5178 return status;
5180 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5181 free_a_printer_driver(driver, 3);
5184 *returned+=ndrivers;
5185 safe_free(list);
5188 /* check the required size. */
5189 for (i=0; i<*returned; i++) {
5190 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5191 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5194 if (!alloc_buffer_size(buffer, *needed)) {
5195 safe_free(driver_info_3);
5196 return ERROR_INSUFFICIENT_BUFFER;
5199 /* fill the buffer with the driver structures */
5200 for (i=0; i<*returned; i++) {
5201 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5202 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5205 for (i=0; i<*returned; i++)
5206 safe_free(driver_info_3[i].dependentfiles);
5208 safe_free(driver_info_3);
5210 if (*needed > offered) {
5211 *returned=0;
5212 return ERROR_INSUFFICIENT_BUFFER;
5214 else
5215 return NT_STATUS_NO_PROBLEMO;
5218 /****************************************************************************
5219 Enumerates all printer drivers.
5220 ****************************************************************************/
5222 uint32 _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5224 /* UNISTR2 *name = &q_u->name; - notused. */
5225 UNISTR2 *environment = &q_u->environment;
5226 uint32 level = q_u->level;
5227 NEW_BUFFER *buffer = NULL;
5228 uint32 offered = q_u->offered;
5229 uint32 *needed = &r_u->needed;
5230 uint32 *returned = &r_u->returned;
5232 fstring *list = NULL;
5233 fstring servername;
5234 fstring architecture;
5236 /* that's an [in out] buffer */
5237 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5238 buffer = r_u->buffer;
5240 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5241 fstrcpy(servername, global_myname);
5242 *needed=0;
5243 *returned=0;
5245 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5247 switch (level) {
5248 case 1:
5249 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5250 case 2:
5251 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5252 case 3:
5253 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5254 default:
5255 *returned=0;
5256 safe_free(list);
5257 return ERROR_INVALID_LEVEL;
5261 /****************************************************************************
5262 ****************************************************************************/
5264 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5266 form->flag=list->flag;
5267 init_unistr(&form->name, list->name);
5268 form->width=list->width;
5269 form->length=list->length;
5270 form->left=list->left;
5271 form->top=list->top;
5272 form->right=list->right;
5273 form->bottom=list->bottom;
5276 /****************************************************************************
5277 ****************************************************************************/
5279 uint32 _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5281 /* POLICY_HND *handle = &q_u->handle; - notused. */
5282 uint32 level = q_u->level;
5283 NEW_BUFFER *buffer = NULL;
5284 uint32 offered = q_u->offered;
5285 uint32 *needed = &r_u->needed;
5286 uint32 *numofforms = &r_u->numofforms;
5287 uint32 numbuiltinforms;
5289 nt_forms_struct *list=NULL;
5290 nt_forms_struct *builtinlist=NULL;
5291 FORM_1 *forms_1;
5292 int buffer_size=0;
5293 int i;
5295 /* that's an [in out] buffer */
5296 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5297 buffer = r_u->buffer;
5299 DEBUG(4,("_spoolss_enumforms\n"));
5300 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5301 DEBUGADD(5,("Info level [%d]\n", level));
5303 numbuiltinforms = get_builtin_ntforms(&builtinlist);
5304 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
5305 *numofforms = get_ntforms(&list);
5306 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
5307 *numofforms += numbuiltinforms;
5309 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
5311 switch (level) {
5312 case 1:
5313 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5314 *numofforms=0;
5315 return ERROR_NOT_ENOUGH_MEMORY;
5318 /* construct the list of form structures */
5319 for (i=0; i<numbuiltinforms; i++) {
5320 DEBUGADD(6,("Filling form number [%d]\n",i));
5321 fill_form_1(&forms_1[i], &builtinlist[i]);
5324 safe_free(builtinlist);
5326 for (; i<*numofforms; i++) {
5327 DEBUGADD(6,("Filling form number [%d]\n",i));
5328 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5331 safe_free(list);
5333 /* check the required size. */
5334 for (i=0; i<numbuiltinforms; i++) {
5335 DEBUGADD(6,("adding form [%d]'s size\n",i));
5336 buffer_size += spoolss_size_form_1(&forms_1[i]);
5338 for (; i<*numofforms; i++) {
5339 DEBUGADD(6,("adding form [%d]'s size\n",i));
5340 buffer_size += spoolss_size_form_1(&forms_1[i]);
5343 *needed=buffer_size;
5345 if (!alloc_buffer_size(buffer, buffer_size)){
5346 safe_free(forms_1);
5347 return ERROR_INSUFFICIENT_BUFFER;
5350 /* fill the buffer with the form structures */
5351 for (i=0; i<numbuiltinforms; i++) {
5352 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5353 smb_io_form_1("", buffer, &forms_1[i], 0);
5355 for (; i<*numofforms; i++) {
5356 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5357 smb_io_form_1("", buffer, &forms_1[i], 0);
5360 safe_free(forms_1);
5362 if (*needed > offered) {
5363 *numofforms=0;
5364 return ERROR_INSUFFICIENT_BUFFER;
5366 else
5367 return NT_STATUS_NO_PROBLEMO;
5369 default:
5370 safe_free(list);
5371 safe_free(builtinlist);
5372 return ERROR_INVALID_LEVEL;
5377 /****************************************************************************
5378 ****************************************************************************/
5380 uint32 _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5382 /* POLICY_HND *handle = &q_u->handle; - notused. */
5383 uint32 level = q_u->level;
5384 UNISTR2 *uni_formname = &q_u->formname;
5385 NEW_BUFFER *buffer = NULL;
5386 uint32 offered = q_u->offered;
5387 uint32 *needed = &r_u->needed;
5389 nt_forms_struct *list=NULL;
5390 nt_forms_struct builtin_form;
5391 BOOL foundBuiltin;
5392 FORM_1 form_1;
5393 fstring form_name;
5394 int buffer_size=0;
5395 int numofforms=0, i=0;
5397 /* that's an [in out] buffer */
5398 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5399 buffer = r_u->buffer;
5401 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5403 DEBUG(4,("_spoolss_getform\n"));
5404 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5405 DEBUGADD(5,("Info level [%d]\n", level));
5407 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5408 if (!foundBuiltin) {
5409 numofforms = get_ntforms(&list);
5410 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5412 if (numofforms == 0)
5413 return ERROR_INVALID_HANDLE;
5416 switch (level) {
5417 case 1:
5418 if (foundBuiltin) {
5419 fill_form_1(&form_1, &builtin_form);
5420 } else {
5422 /* Check if the requested name is in the list of form structures */
5423 for (i=0; i<numofforms; i++) {
5425 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5427 if (strequal(form_name, list[i].name)) {
5428 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5429 fill_form_1(&form_1, &list[i]);
5430 break;
5434 safe_free(list);
5435 if (i == numofforms) {
5436 return ERROR_INVALID_HANDLE;
5439 /* check the required size. */
5441 *needed=spoolss_size_form_1(&form_1);
5443 if (!alloc_buffer_size(buffer, buffer_size)){
5444 return ERROR_INSUFFICIENT_BUFFER;
5447 if (*needed > offered) {
5448 return ERROR_INSUFFICIENT_BUFFER;
5451 /* fill the buffer with the form structures */
5452 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5453 smb_io_form_1("", buffer, &form_1, 0);
5455 return NT_STATUS_NO_PROBLEMO;
5457 default:
5458 safe_free(list);
5459 return ERROR_INVALID_LEVEL;
5463 /****************************************************************************
5464 ****************************************************************************/
5465 static void fill_port_1(PORT_INFO_1 *port, char *name)
5467 init_unistr(&port->port_name, name);
5470 /****************************************************************************
5471 ****************************************************************************/
5472 static void fill_port_2(PORT_INFO_2 *port, char *name)
5474 init_unistr(&port->port_name, name);
5475 init_unistr(&port->monitor_name, "Local Monitor");
5476 init_unistr(&port->description, "Local Port");
5477 #define PORT_TYPE_WRITE 1
5478 port->port_type=PORT_TYPE_WRITE;
5479 port->reserved=0x0;
5482 /****************************************************************************
5483 enumports level 1.
5484 ****************************************************************************/
5485 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5487 PORT_INFO_1 *ports=NULL;
5488 int i=0;
5490 if (*lp_enumports_cmd()) {
5491 char *cmd = lp_enumports_cmd();
5492 char *path;
5493 char **qlines;
5494 pstring command;
5495 int numlines;
5496 int ret;
5497 int fd;
5499 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5500 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5501 else
5502 path = lp_lockdir();
5504 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5506 DEBUG(10,("Running [%s]\n", command));
5507 ret = smbrun(command, &fd);
5508 DEBUG(10,("Returned [%d]\n", ret));
5509 if (ret != 0) {
5510 if (fd != -1)
5511 close(fd);
5512 /* Is this the best error to return here? */
5513 return ERROR_ACCESS_DENIED;
5516 numlines = 0;
5517 qlines = fd_lines_load(fd, &numlines,True);
5518 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5519 close(fd);
5521 if(numlines) {
5522 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5523 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5524 file_lines_free(qlines);
5525 return ERROR_NOT_ENOUGH_MEMORY;
5528 for (i=0; i<numlines; i++) {
5529 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5530 fill_port_1(&ports[i], qlines[i]);
5533 file_lines_free(qlines);
5536 *returned = numlines;
5538 } else {
5539 *returned = 1; /* Sole Samba port returned. */
5541 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5542 return ERROR_NOT_ENOUGH_MEMORY;
5544 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5546 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5549 /* check the required size. */
5550 for (i=0; i<*returned; i++) {
5551 DEBUGADD(6,("adding port [%d]'s size\n", i));
5552 *needed += spoolss_size_port_info_1(&ports[i]);
5555 if (!alloc_buffer_size(buffer, *needed)) {
5556 safe_free(ports);
5557 return ERROR_INSUFFICIENT_BUFFER;
5560 /* fill the buffer with the ports structures */
5561 for (i=0; i<*returned; i++) {
5562 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5563 smb_io_port_1("", buffer, &ports[i], 0);
5566 safe_free(ports);
5568 if (*needed > offered) {
5569 *returned=0;
5570 return ERROR_INSUFFICIENT_BUFFER;
5572 else
5573 return NT_STATUS_NO_PROBLEMO;
5576 /****************************************************************************
5577 enumports level 2.
5578 ****************************************************************************/
5580 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5582 PORT_INFO_2 *ports=NULL;
5583 int i=0;
5585 if (*lp_enumports_cmd()) {
5586 char *cmd = lp_enumports_cmd();
5587 char *path;
5588 char **qlines;
5589 pstring tmp_file;
5590 pstring command;
5591 int numlines;
5592 int ret;
5593 int fd;
5595 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5596 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5597 else
5598 path = lp_lockdir();
5600 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
5601 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5603 unlink(tmp_file);
5604 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5605 ret = smbrun(command, &fd);
5606 DEBUGADD(10,("returned [%d]\n", ret));
5607 if (ret != 0) {
5608 if (fd != -1)
5609 close(fd);
5610 /* Is this the best error to return here? */
5611 return ERROR_ACCESS_DENIED;
5614 numlines = 0;
5615 qlines = fd_lines_load(fd, &numlines,True);
5616 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5617 close(fd);
5619 if(numlines) {
5620 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5621 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5622 file_lines_free(qlines);
5623 return ERROR_NOT_ENOUGH_MEMORY;
5626 for (i=0; i<numlines; i++) {
5627 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5628 fill_port_2(&(ports[i]), qlines[i]);
5631 file_lines_free(qlines);
5634 *returned = numlines;
5636 } else {
5638 *returned = 1;
5640 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5641 return ERROR_NOT_ENOUGH_MEMORY;
5643 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5645 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5648 /* check the required size. */
5649 for (i=0; i<*returned; i++) {
5650 DEBUGADD(6,("adding port [%d]'s size\n", i));
5651 *needed += spoolss_size_port_info_2(&ports[i]);
5654 if (!alloc_buffer_size(buffer, *needed)) {
5655 safe_free(ports);
5656 return ERROR_INSUFFICIENT_BUFFER;
5659 /* fill the buffer with the ports structures */
5660 for (i=0; i<*returned; i++) {
5661 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5662 smb_io_port_2("", buffer, &ports[i], 0);
5665 safe_free(ports);
5667 if (*needed > offered) {
5668 *returned=0;
5669 return ERROR_INSUFFICIENT_BUFFER;
5671 else
5672 return NT_STATUS_NO_PROBLEMO;
5675 /****************************************************************************
5676 enumports.
5677 ****************************************************************************/
5679 uint32 _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5681 /* UNISTR2 *name = &q_u->name; - notused. */
5682 uint32 level = q_u->level;
5683 NEW_BUFFER *buffer = NULL;
5684 uint32 offered = q_u->offered;
5685 uint32 *needed = &r_u->needed;
5686 uint32 *returned = &r_u->returned;
5688 /* that's an [in out] buffer */
5689 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5690 buffer = r_u->buffer;
5692 DEBUG(4,("_spoolss_enumports\n"));
5694 *returned=0;
5695 *needed=0;
5697 switch (level) {
5698 case 1:
5699 return enumports_level_1(buffer, offered, needed, returned);
5700 case 2:
5701 return enumports_level_2(buffer, offered, needed, returned);
5702 default:
5703 return ERROR_INVALID_LEVEL;
5707 /****************************************************************************
5708 ****************************************************************************/
5709 static uint32 spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5710 const SPOOL_PRINTER_INFO_LEVEL *info,
5711 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5712 uint32 user_switch, const SPOOL_USER_CTR *user,
5713 POLICY_HND *handle)
5715 NT_PRINTER_INFO_LEVEL *printer = NULL;
5716 fstring name;
5717 int snum;
5719 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5720 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5721 return ERROR_NOT_ENOUGH_MEMORY;
5724 ZERO_STRUCTP(printer);
5726 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5727 convert_printer_info(info, printer, 2);
5729 if (*lp_addprinter_cmd() )
5730 if ( !add_printer_hook(printer) ) {
5731 free_a_printer(&printer,2);
5732 return ERROR_ACCESS_DENIED;
5735 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5736 printer->info_2->sharename);
5738 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5739 free_a_printer(&printer,2);
5740 return ERROR_ACCESS_DENIED;
5743 /* you must be a printer admin to add a new printer */
5744 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5745 free_a_printer(&printer,2);
5746 return ERROR_ACCESS_DENIED;
5750 * Do sanity check on the requested changes for Samba.
5753 if (!check_printer_ok(printer->info_2, snum)) {
5754 free_a_printer(&printer,2);
5755 return ERROR_INVALID_PARAMETER;
5758 /* write the ASCII on disk */
5759 if (add_a_printer(*printer, 2) != 0) {
5760 free_a_printer(&printer,2);
5761 return ERROR_ACCESS_DENIED;
5764 if (!open_printer_hnd(p, handle, name)) {
5765 /* Handle open failed - remove addition. */
5766 del_a_printer(printer->info_2->sharename);
5767 free_a_printer(&printer,2);
5768 return ERROR_ACCESS_DENIED;
5771 free_a_printer(&printer,2);
5773 srv_spoolss_sendnotify(p, handle);
5775 return NT_STATUS_NO_PROBLEMO;
5778 /****************************************************************************
5779 ****************************************************************************/
5781 uint32 _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5783 UNISTR2 *uni_srv_name = &q_u->server_name;
5784 uint32 level = q_u->level;
5785 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5786 uint32 unk0 = q_u->unk0;
5787 uint32 unk1 = q_u->unk1;
5788 uint32 unk2 = q_u->unk2;
5789 uint32 unk3 = q_u->unk3;
5790 uint32 user_switch = q_u->user_switch;
5791 SPOOL_USER_CTR *user = &q_u->user_ctr;
5792 POLICY_HND *handle = &r_u->handle;
5794 switch (level) {
5795 case 1:
5796 /* we don't handle yet */
5797 /* but I know what to do ... */
5798 return ERROR_INVALID_LEVEL;
5799 case 2:
5800 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5801 unk0, unk1, unk2, unk3,
5802 user_switch, user, handle);
5803 default:
5804 return ERROR_INVALID_LEVEL;
5808 /****************************************************************************
5809 ****************************************************************************/
5811 uint32 _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5813 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5814 uint32 level = q_u->level;
5815 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5817 uint32 err = NT_STATUS_NO_PROBLEMO;
5818 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5819 struct current_user user;
5821 ZERO_STRUCT(driver);
5823 get_current_user(&user, p);
5825 convert_printer_driver_info(info, &driver, level);
5827 DEBUG(5,("Cleaning driver's information\n"));
5828 if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5829 goto done;
5831 DEBUG(5,("Moving driver to final destination\n"));
5832 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5833 if (err == 0)
5834 err = ERROR_ACCESS_DENIED;
5835 goto done;
5838 if (add_a_printer_driver(driver, level)!=0) {
5839 err = ERROR_ACCESS_DENIED;
5840 goto done;
5843 done:
5844 free_a_printer_driver(driver, level);
5845 return err;
5848 /****************************************************************************
5849 ****************************************************************************/
5850 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5852 init_unistr(&info->name, name);
5855 /****************************************************************************
5856 ****************************************************************************/
5857 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5859 pstring path;
5860 pstring long_archi;
5861 pstring short_archi;
5862 DRIVER_DIRECTORY_1 *info=NULL;
5864 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5866 if (get_short_archi(short_archi, long_archi)==FALSE)
5867 return ERROR_INVALID_ENVIRONMENT;
5869 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5870 return ERROR_NOT_ENOUGH_MEMORY;
5872 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5874 DEBUG(4,("printer driver directory: [%s]\n", path));
5876 fill_driverdir_1(info, path);
5878 *needed += spoolss_size_driverdir_info_1(info);
5880 if (!alloc_buffer_size(buffer, *needed)) {
5881 safe_free(info);
5882 return ERROR_INSUFFICIENT_BUFFER;
5885 smb_io_driverdir_1("", buffer, info, 0);
5887 safe_free(info);
5889 if (*needed > offered)
5890 return ERROR_INSUFFICIENT_BUFFER;
5891 else
5892 return NT_STATUS_NO_PROBLEMO;
5895 /****************************************************************************
5896 ****************************************************************************/
5898 uint32 _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
5900 UNISTR2 *name = &q_u->name;
5901 UNISTR2 *uni_environment = &q_u->environment;
5902 uint32 level = q_u->level;
5903 NEW_BUFFER *buffer = NULL;
5904 uint32 offered = q_u->offered;
5905 uint32 *needed = &r_u->needed;
5907 /* that's an [in out] buffer */
5908 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5909 buffer = r_u->buffer;
5911 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5913 *needed=0;
5915 switch(level) {
5916 case 1:
5917 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5918 default:
5919 return ERROR_INVALID_LEVEL;
5923 /****************************************************************************
5924 ****************************************************************************/
5926 uint32 _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
5928 POLICY_HND *handle = &q_u->handle;
5929 uint32 idx = q_u->index;
5930 uint32 in_value_len = q_u->valuesize;
5931 uint32 in_data_len = q_u->datasize;
5932 uint32 *out_max_value_len = &r_u->valuesize;
5933 uint16 **out_value = &r_u->value;
5934 uint32 *out_value_len = &r_u->realvaluesize;
5935 uint32 *out_type = &r_u->type;
5936 uint32 *out_max_data_len = &r_u->datasize;
5937 uint8 **data_out = &r_u->data;
5938 uint32 *out_data_len = &r_u->realdatasize;
5940 NT_PRINTER_INFO_LEVEL *printer = NULL;
5942 fstring value;
5944 uint32 param_index;
5945 uint32 biggest_valuesize;
5946 uint32 biggest_datasize;
5947 uint32 data_len;
5948 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5949 int snum;
5950 uint8 *data=NULL;
5951 uint32 type;
5953 ZERO_STRUCT(printer);
5955 *out_max_value_len=0;
5956 *out_value=NULL;
5957 *out_value_len=0;
5959 *out_type=0;
5961 *out_max_data_len=0;
5962 *data_out=NULL;
5963 *out_data_len=0;
5965 DEBUG(5,("spoolss_enumprinterdata\n"));
5967 if (!Printer) {
5968 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5969 return ERROR_INVALID_HANDLE;
5972 if (!get_printer_snum(p,handle, &snum))
5973 return ERROR_INVALID_HANDLE;
5975 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5976 return ERROR_INVALID_HANDLE;
5979 * The NT machine wants to know the biggest size of value and data
5981 * cf: MSDN EnumPrinterData remark section
5983 if ( (in_value_len==0) && (in_data_len==0) ) {
5984 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5986 #if 0
5988 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5989 * if this parameter size doesn't exist.
5990 * Ok - my opinion here is that the client is not asking for the greatest
5991 * possible size of all the parameters, but is asking specifically for the size needed
5992 * for this specific parameter. In that case we can remove the loop below and
5993 * simplify this lookup code considerably. JF - comments welcome. JRA.
5996 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5997 safe_free(data);
5998 free_a_printer(&printer, 2);
5999 return ERROR_NO_MORE_ITEMS;
6001 #endif
6003 safe_free(data);
6004 data = NULL;
6006 param_index=0;
6007 biggest_valuesize=0;
6008 biggest_datasize=0;
6010 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6011 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6012 if (data_len > biggest_datasize) biggest_datasize=data_len;
6014 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6016 safe_free(data);
6017 data = NULL;
6018 param_index++;
6022 * I think this is correct, it doesn't break APW and
6023 * allows Gerald's Win32 test programs to work correctly,
6024 * but may need altering.... JRA.
6027 if (param_index == 0) {
6028 /* No parameters found. */
6029 free_a_printer(&printer, 2);
6030 return ERROR_NO_MORE_ITEMS;
6033 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6034 *out_value_len=2*(1+biggest_valuesize);
6035 *out_data_len=biggest_datasize;
6037 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6039 free_a_printer(&printer, 2);
6040 return NT_STATUS_NO_PROBLEMO;
6044 * the value len is wrong in NT sp3
6045 * that's the number of bytes not the number of unicode chars
6048 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6049 safe_free(data);
6050 free_a_printer(&printer, 2);
6051 return ERROR_NO_MORE_ITEMS;
6054 free_a_printer(&printer, 2);
6057 * the value is:
6058 * - counted in bytes in the request
6059 * - counted in UNICODE chars in the max reply
6060 * - counted in bytes in the real size
6062 * take a pause *before* coding not *during* coding
6065 *out_max_value_len=(in_value_len/sizeof(uint16));
6066 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6067 safe_free(data);
6068 return ERROR_NOT_ENOUGH_MEMORY;
6071 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
6073 *out_type=type;
6075 /* the data is counted in bytes */
6076 *out_max_data_len=in_data_len;
6077 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6078 safe_free(data);
6079 return ERROR_NOT_ENOUGH_MEMORY;
6082 memcpy(*data_out, data, (size_t)data_len);
6083 *out_data_len=data_len;
6085 safe_free(data);
6087 return NT_STATUS_NO_PROBLEMO;
6090 /****************************************************************************
6091 ****************************************************************************/
6093 uint32 _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6095 POLICY_HND *handle = &q_u->handle;
6096 UNISTR2 *value = &q_u->value;
6097 uint32 type = q_u->type;
6098 /* uint32 max_len = q_u->max_len; - notused. */
6099 uint8 *data = q_u->data;
6100 uint32 real_len = q_u->real_len;
6101 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6103 NT_PRINTER_INFO_LEVEL *printer = NULL;
6104 NT_PRINTER_PARAM *param = NULL, old_param;
6105 int snum=0;
6106 uint32 status = 0x0;
6107 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6109 DEBUG(5,("spoolss_setprinterdata\n"));
6111 if (!Printer) {
6112 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6113 return ERROR_INVALID_HANDLE;
6116 if (!get_printer_snum(p,handle, &snum))
6117 return ERROR_INVALID_HANDLE;
6119 status = get_a_printer(&printer, 2, lp_servicename(snum));
6120 if (status != 0x0)
6121 return ERROR_INVALID_NAME;
6123 convert_specific_param(&param, value , type, data, real_len);
6125 /* Check if we are making any changes or not. Return true if
6126 nothing is actually changing. */
6128 ZERO_STRUCT(old_param);
6130 if (get_specific_param(*printer, 2, param->value, &old_param.data,
6131 &old_param.type, (uint32 *)&old_param.data_len)) {
6133 if (param->type == old_param.type &&
6134 param->data_len == old_param.data_len &&
6135 memcmp(param->data, old_param.data,
6136 old_param.data_len) == 0) {
6138 DEBUG(3, ("setprinterdata hasn't changed\n"));
6139 status = NT_STATUS_NO_PROBLEMO;
6140 goto done;
6144 /* Access check */
6146 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6147 DEBUG(3, ("security descriptor change denied by existing "
6148 "security descriptor\n"));
6149 status = ERROR_ACCESS_DENIED;
6150 goto done;
6153 unlink_specific_param_if_exist(printer->info_2, param);
6155 add_a_specific_param(printer->info_2, &param);
6156 status = mod_a_printer(*printer, 2);
6158 done:
6159 free_a_printer(&printer, 2);
6160 if (param)
6161 free_nt_printer_param(&param);
6162 safe_free(old_param.data);
6164 return status;
6167 /****************************************************************************
6168 ****************************************************************************/
6170 uint32 _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6172 POLICY_HND *handle = &q_u->handle;
6173 UNISTR2 *value = &q_u->valuename;
6175 NT_PRINTER_INFO_LEVEL *printer = NULL;
6176 NT_PRINTER_PARAM param;
6177 int snum=0;
6178 uint32 status = 0x0;
6179 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6181 DEBUG(5,("spoolss_deleteprinterdata\n"));
6183 if (!Printer) {
6184 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6185 return ERROR_INVALID_HANDLE;
6188 if (!get_printer_snum(p, handle, &snum))
6189 return ERROR_INVALID_HANDLE;
6191 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6192 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6193 "change denied by existing security descriptor\n"));
6194 return ERROR_ACCESS_DENIED;
6197 status = get_a_printer(&printer, 2, lp_servicename(snum));
6198 if (status != 0x0)
6199 return ERROR_INVALID_NAME;
6201 ZERO_STRUCTP(&param);
6202 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6204 if(!unlink_specific_param_if_exist(printer->info_2, &param))
6205 status = ERROR_INVALID_PARAMETER;
6206 else
6207 status = mod_a_printer(*printer, 2);
6209 free_a_printer(&printer, 2);
6210 return status;
6213 /****************************************************************************
6214 ****************************************************************************/
6216 uint32 _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6218 POLICY_HND *handle = &q_u->handle;
6219 /* uint32 level = q_u->level; - notused. */
6220 FORM *form = &q_u->form;
6221 nt_forms_struct tmpForm;
6223 int count=0;
6224 nt_forms_struct *list=NULL;
6225 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6227 DEBUG(5,("spoolss_addform\n"));
6229 if (!Printer) {
6230 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6231 return ERROR_INVALID_HANDLE;
6234 /* can't add if builtin */
6235 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6236 return ERROR_INVALID_PARAMETER;
6239 count=get_ntforms(&list);
6240 if(!add_a_form(&list, form, &count))
6241 return ERROR_NOT_ENOUGH_MEMORY;
6242 write_ntforms(&list, count);
6244 safe_free(list);
6246 return 0x0;
6249 /****************************************************************************
6250 ****************************************************************************/
6252 uint32 _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6254 POLICY_HND *handle = &q_u->handle;
6255 UNISTR2 *form_name = &q_u->name;
6256 nt_forms_struct tmpForm;
6257 int count=0;
6258 uint32 ret = 0;
6259 nt_forms_struct *list=NULL;
6260 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6262 DEBUG(5,("spoolss_deleteform\n"));
6264 if (!Printer) {
6265 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6266 return ERROR_INVALID_HANDLE;
6269 /* can't delete if builtin */
6270 if (get_a_builtin_ntform(form_name,&tmpForm)) {
6271 return ERROR_INVALID_PARAMETER;
6274 count = get_ntforms(&list);
6275 if(!delete_a_form(&list, form_name, &count, &ret))
6276 return ERROR_INVALID_PARAMETER;
6278 safe_free(list);
6280 return ret;
6283 /****************************************************************************
6284 ****************************************************************************/
6286 uint32 _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6288 POLICY_HND *handle = &q_u->handle;
6289 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6290 /* uint32 level = q_u->level; - notused. */
6291 FORM *form = &q_u->form;
6292 nt_forms_struct tmpForm;
6294 int count=0;
6295 nt_forms_struct *list=NULL;
6296 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6298 DEBUG(5,("spoolss_setform\n"));
6300 if (!Printer) {
6301 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6302 return ERROR_INVALID_HANDLE;
6304 /* can't set if builtin */
6305 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6306 return ERROR_INVALID_PARAMETER;
6309 count=get_ntforms(&list);
6310 update_a_form(&list, form, count);
6311 write_ntforms(&list, count);
6313 safe_free(list);
6315 return 0x0;
6318 /****************************************************************************
6319 enumprintprocessors level 1.
6320 ****************************************************************************/
6321 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6323 PRINTPROCESSOR_1 *info_1=NULL;
6325 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6326 return ERROR_NOT_ENOUGH_MEMORY;
6328 (*returned) = 0x1;
6330 init_unistr(&info_1->name, "winprint");
6332 *needed += spoolss_size_printprocessor_info_1(info_1);
6334 if (!alloc_buffer_size(buffer, *needed))
6335 return ERROR_INSUFFICIENT_BUFFER;
6337 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6339 safe_free(info_1);
6341 if (*needed > offered) {
6342 *returned=0;
6343 return ERROR_INSUFFICIENT_BUFFER;
6345 else
6346 return NT_STATUS_NO_PROBLEMO;
6349 /****************************************************************************
6350 ****************************************************************************/
6352 uint32 _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6354 /* UNISTR2 *name = &q_u->name; - notused. */
6355 /* UNISTR2 *environment = &q_u->environment; - notused. */
6356 uint32 level = q_u->level;
6357 NEW_BUFFER *buffer = NULL;
6358 uint32 offered = q_u->offered;
6359 uint32 *needed = &r_u->needed;
6360 uint32 *returned = &r_u->returned;
6362 /* that's an [in out] buffer */
6363 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6364 buffer = r_u->buffer;
6366 DEBUG(5,("spoolss_enumprintprocessors\n"));
6369 * Enumerate the print processors ...
6371 * Just reply with "winprint", to keep NT happy
6372 * and I can use my nice printer checker.
6375 *returned=0;
6376 *needed=0;
6378 switch (level) {
6379 case 1:
6380 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6381 default:
6382 return ERROR_INVALID_LEVEL;
6386 /****************************************************************************
6387 enumprintprocdatatypes level 1.
6388 ****************************************************************************/
6389 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6391 PRINTPROCDATATYPE_1 *info_1=NULL;
6393 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6394 return ERROR_NOT_ENOUGH_MEMORY;
6396 (*returned) = 0x1;
6398 init_unistr(&info_1->name, "RAW");
6400 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6402 if (!alloc_buffer_size(buffer, *needed))
6403 return ERROR_INSUFFICIENT_BUFFER;
6405 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6407 safe_free(info_1);
6409 if (*needed > offered) {
6410 *returned=0;
6411 return ERROR_INSUFFICIENT_BUFFER;
6413 else
6414 return NT_STATUS_NO_PROBLEMO;
6417 /****************************************************************************
6418 ****************************************************************************/
6420 uint32 _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6422 /* UNISTR2 *name = &q_u->name; - notused. */
6423 /* UNISTR2 *processor = &q_u->processor; - notused. */
6424 uint32 level = q_u->level;
6425 NEW_BUFFER *buffer = NULL;
6426 uint32 offered = q_u->offered;
6427 uint32 *needed = &r_u->needed;
6428 uint32 *returned = &r_u->returned;
6430 /* that's an [in out] buffer */
6431 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6432 buffer = r_u->buffer;
6434 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6436 *returned=0;
6437 *needed=0;
6439 switch (level) {
6440 case 1:
6441 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6442 default:
6443 return ERROR_INVALID_LEVEL;
6447 /****************************************************************************
6448 enumprintmonitors level 1.
6449 ****************************************************************************/
6451 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6453 PRINTMONITOR_1 *info_1=NULL;
6455 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6456 return ERROR_NOT_ENOUGH_MEMORY;
6458 (*returned) = 0x1;
6460 init_unistr(&info_1->name, "Local Port");
6462 *needed += spoolss_size_printmonitor_info_1(info_1);
6464 if (!alloc_buffer_size(buffer, *needed))
6465 return ERROR_INSUFFICIENT_BUFFER;
6467 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6469 safe_free(info_1);
6471 if (*needed > offered) {
6472 *returned=0;
6473 return ERROR_INSUFFICIENT_BUFFER;
6475 else
6476 return NT_STATUS_NO_PROBLEMO;
6479 /****************************************************************************
6480 enumprintmonitors level 2.
6481 ****************************************************************************/
6482 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6484 PRINTMONITOR_2 *info_2=NULL;
6486 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6487 return ERROR_NOT_ENOUGH_MEMORY;
6489 (*returned) = 0x1;
6491 init_unistr(&info_2->name, "Local Port");
6492 init_unistr(&info_2->environment, "Windows NT X86");
6493 init_unistr(&info_2->dll_name, "localmon.dll");
6495 *needed += spoolss_size_printmonitor_info_2(info_2);
6497 if (!alloc_buffer_size(buffer, *needed))
6498 return ERROR_INSUFFICIENT_BUFFER;
6500 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6502 safe_free(info_2);
6504 if (*needed > offered) {
6505 *returned=0;
6506 return ERROR_INSUFFICIENT_BUFFER;
6508 else
6509 return NT_STATUS_NO_PROBLEMO;
6512 /****************************************************************************
6513 ****************************************************************************/
6515 uint32 _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6517 /* UNISTR2 *name = &q_u->name; - notused. */
6518 uint32 level = q_u->level;
6519 NEW_BUFFER *buffer = NULL;
6520 uint32 offered = q_u->offered;
6521 uint32 *needed = &r_u->needed;
6522 uint32 *returned = &r_u->returned;
6524 /* that's an [in out] buffer */
6525 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6526 buffer = r_u->buffer;
6528 DEBUG(5,("spoolss_enumprintmonitors\n"));
6531 * Enumerate the print monitors ...
6533 * Just reply with "Local Port", to keep NT happy
6534 * and I can use my nice printer checker.
6537 *returned=0;
6538 *needed=0;
6540 switch (level) {
6541 case 1:
6542 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6543 case 2:
6544 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6545 default:
6546 return ERROR_INVALID_LEVEL;
6550 /****************************************************************************
6551 ****************************************************************************/
6552 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6554 int i=0;
6555 BOOL found=False;
6556 JOB_INFO_1 *info_1=NULL;
6558 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6560 if (info_1 == NULL) {
6561 safe_free(queue);
6562 return ERROR_NOT_ENOUGH_MEMORY;
6565 for (i=0; i<count && found==False; i++) {
6566 if (queue[i].job==(int)jobid)
6567 found=True;
6570 if (found==False) {
6571 safe_free(queue);
6572 safe_free(info_1);
6573 /* I shoud reply something else ... I can't find the good one */
6574 return NT_STATUS_NO_PROBLEMO;
6577 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6579 safe_free(queue);
6581 *needed += spoolss_size_job_info_1(info_1);
6583 if (!alloc_buffer_size(buffer, *needed)) {
6584 safe_free(info_1);
6585 return ERROR_INSUFFICIENT_BUFFER;
6588 smb_io_job_info_1("", buffer, info_1, 0);
6590 safe_free(info_1);
6592 if (*needed > offered)
6593 return ERROR_INSUFFICIENT_BUFFER;
6594 else
6595 return NT_STATUS_NO_PROBLEMO;
6599 /****************************************************************************
6600 ****************************************************************************/
6601 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6603 int i=0;
6604 BOOL found=False;
6605 JOB_INFO_2 *info_2;
6606 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6608 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6610 ZERO_STRUCTP(info_2);
6612 if (info_2 == NULL) {
6613 safe_free(queue);
6614 return ERROR_NOT_ENOUGH_MEMORY;
6617 for (i=0; i<count && found==False; i++) {
6618 if (queue[i].job==(int)jobid)
6619 found=True;
6622 if (found==False) {
6623 safe_free(queue);
6624 safe_free(info_2);
6625 /* I shoud reply something else ... I can't find the good one */
6626 return NT_STATUS_NO_PROBLEMO;
6629 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6630 safe_free(queue);
6631 return ERROR_NOT_ENOUGH_MEMORY;
6634 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6636 free_a_printer(&ntprinter, 2);
6637 safe_free(queue);
6639 *needed += spoolss_size_job_info_2(info_2);
6641 if (!alloc_buffer_size(buffer, *needed)) {
6642 safe_free(info_2);
6643 return ERROR_INSUFFICIENT_BUFFER;
6646 smb_io_job_info_2("", buffer, info_2, 0);
6648 free_job_info_2(info_2);
6649 free(info_2);
6651 if (*needed > offered)
6652 return ERROR_INSUFFICIENT_BUFFER;
6653 else
6654 return NT_STATUS_NO_PROBLEMO;
6657 /****************************************************************************
6658 ****************************************************************************/
6660 uint32 _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6662 POLICY_HND *handle = &q_u->handle;
6663 uint32 jobid = q_u->jobid;
6664 uint32 level = q_u->level;
6665 NEW_BUFFER *buffer = NULL;
6666 uint32 offered = q_u->offered;
6667 uint32 *needed = &r_u->needed;
6669 int snum;
6670 int count;
6671 print_queue_struct *queue=NULL;
6672 print_status_struct prt_status;
6674 /* that's an [in out] buffer */
6675 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6676 buffer = r_u->buffer;
6678 DEBUG(5,("spoolss_getjob\n"));
6680 memset(&prt_status, 0, sizeof(prt_status));
6682 *needed=0;
6684 if (!get_printer_snum(p, handle, &snum))
6685 return ERROR_INVALID_HANDLE;
6687 count = print_queue_status(snum, &queue, &prt_status);
6689 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6690 count, prt_status.status, prt_status.message));
6692 switch (level) {
6693 case 1:
6694 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6695 case 2:
6696 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6697 default:
6698 safe_free(queue);
6699 return ERROR_INVALID_LEVEL;