merge from APPLIANCE_HEAD
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob02f708511980b133cabdfbdc0bbb657b68d94c70
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.
9 * Copyright (C) Gerald Carter 2000-2001.
10 * Copyright (C) Tim Potter 2001.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
30 #include "includes.h"
32 #ifndef MAX_OPEN_PRINTER_EXS
33 #define MAX_OPEN_PRINTER_EXS 50
34 #endif
36 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
37 #define PRINTER_HANDLE_IS_PRINTER 0
38 #define PRINTER_HANDLE_IS_PRINTSERVER 1
40 struct table_node {
41 char *long_archi;
42 char *short_archi;
43 int version;
47 /* structure to store the printer handles */
48 /* and a reference to what it's pointing to */
49 /* and the notify info asked about */
50 /* that's the central struct */
51 typedef struct _Printer{
52 BOOL document_started;
53 BOOL page_started;
54 int jobid; /* jobid in printing backend */
55 BOOL printer_type;
56 union {
57 fstring handlename;
58 fstring printerservername;
59 } dev;
60 uint32 type;
61 uint32 access;
62 struct {
63 uint32 flags;
64 uint32 options;
65 fstring localmachine;
66 uint32 printerlocal;
67 SPOOL_NOTIFY_OPTION *option;
68 POLICY_HND client_hnd;
69 uint32 client_connected;
70 } notify;
71 struct {
72 fstring machine;
73 fstring user;
74 } client;
75 } Printer_entry;
77 typedef struct _counter_printer_0 {
78 ubi_dlNode Next;
79 ubi_dlNode Prev;
81 int snum;
82 uint32 counter;
83 } counter_printer_0;
85 static ubi_dlList counter_list;
87 static struct cli_state cli;
88 static uint32 smb_connections=0;
90 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
92 /* translate between internal status numbers and NT status numbers */
93 static int nt_printj_status(int v)
95 switch (v) {
96 case LPQ_QUEUED:
97 return 0;
98 case LPQ_PAUSED:
99 return JOB_STATUS_PAUSED;
100 case LPQ_SPOOLING:
101 return JOB_STATUS_SPOOLING;
102 case LPQ_PRINTING:
103 return JOB_STATUS_PRINTING;
104 case LPQ_ERROR:
105 return JOB_STATUS_ERROR;
106 case LPQ_DELETING:
107 return JOB_STATUS_DELETING;
108 case LPQ_OFFLINE:
109 return JOB_STATUS_OFFLINE;
110 case LPQ_PAPEROUT:
111 return JOB_STATUS_PAPEROUT;
112 case LPQ_PRINTED:
113 return JOB_STATUS_PRINTED;
114 case LPQ_DELETED:
115 return JOB_STATUS_DELETED;
116 case LPQ_BLOCKED:
117 return JOB_STATUS_BLOCKED;
118 case LPQ_USER_INTERVENTION:
119 return JOB_STATUS_USER_INTERVENTION;
121 return 0;
124 static int nt_printq_status(int v)
126 switch (v) {
127 case LPQ_PAUSED:
128 return PRINTER_STATUS_PAUSED;
129 case LPQ_QUEUED:
130 case LPQ_SPOOLING:
131 case LPQ_PRINTING:
132 return 0;
134 return 0;
137 /****************************************************************************
138 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
139 ****************************************************************************/
141 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
143 if (*pp == NULL)
144 return;
146 SAFE_FREE((*pp)->ctr.type);
147 SAFE_FREE(*pp);
150 /***************************************************************************
151 Disconnect from the client
152 ****************************************************************************/
154 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
156 WERROR status;
158 /* weird if the test succeds !!! */
159 if (smb_connections==0) {
160 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
161 return;
164 if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
165 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
167 /* if it's the last connection, deconnect the IPC$ share */
168 if (smb_connections==1) {
169 if(!spoolss_disconnect_from_client(&cli))
170 return;
172 message_deregister(MSG_PRINTER_NOTIFY);
175 smb_connections--;
178 /****************************************************************************
179 Functions to free a printer entry datastruct.
180 ****************************************************************************/
182 static void free_printer_entry(void *ptr)
184 Printer_entry *Printer = (Printer_entry *)ptr;
186 if (Printer->notify.client_connected==True)
187 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
189 Printer->notify.flags=0;
190 Printer->notify.options=0;
191 Printer->notify.localmachine[0]='\0';
192 Printer->notify.printerlocal=0;
193 free_spool_notify_option(&Printer->notify.option);
194 Printer->notify.option=NULL;
195 Printer->notify.client_connected=False;
197 SAFE_FREE(Printer);
200 /****************************************************************************
201 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
202 ****************************************************************************/
204 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
206 SPOOL_NOTIFY_OPTION *new_sp = NULL;
208 if (!sp)
209 return NULL;
211 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
212 if (!new_sp)
213 return NULL;
215 *new_sp = *sp;
217 if (sp->ctr.count) {
218 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
220 if (!new_sp->ctr.type) {
221 SAFE_FREE(new_sp);
222 return NULL;
226 return new_sp;
229 /****************************************************************************
230 find printer index by handle
231 ****************************************************************************/
233 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
235 Printer_entry *find_printer = NULL;
237 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
238 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
239 return NULL;
242 return find_printer;
245 /****************************************************************************
246 close printer index by handle
247 ****************************************************************************/
249 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
251 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
253 if (!Printer) {
254 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
255 return False;
258 close_policy_hnd(p, hnd);
260 return True;
263 /****************************************************************************
264 delete a printer given a handle
265 ****************************************************************************/
266 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
268 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
270 if (!Printer) {
271 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
272 return WERR_BADFID;
275 if (del_a_printer(Printer->dev.handlename) != 0) {
276 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
277 return WERR_BADFID;
280 /* Check calling user has permission to delete printer. Note that
281 since we set the snum parameter to -1 only administrators can
282 delete the printer. This stops people with the Full Control
283 permission from deleting the printer. */
285 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
286 DEBUG(3, ("printer delete denied by security descriptor\n"));
287 return WERR_ACCESS_DENIED;
290 if (*lp_deleteprinter_cmd()) {
292 char *cmd = lp_deleteprinter_cmd();
293 pstring command;
294 int ret;
295 int i;
297 /* Printer->dev.handlename equals portname equals sharename */
298 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
299 Printer->dev.handlename);
301 DEBUG(10,("Running [%s]\n", command));
302 ret = smbrun(command, NULL);
303 if (ret != 0) {
304 return WERR_BADFID; /* What to return here? */
306 DEBUGADD(10,("returned [%d]\n", ret));
308 /* Send SIGHUP to process group... is there a better way? */
309 kill(0, SIGHUP);
311 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
312 lp_killservice( i );
313 return WERR_OK;
314 } else
315 return WERR_ACCESS_DENIED;
318 return WERR_OK;
321 /****************************************************************************
322 return the snum of a printer corresponding to an handle
323 ****************************************************************************/
324 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
326 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
328 if (!Printer) {
329 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
330 return False;
333 switch (Printer->printer_type) {
334 case PRINTER_HANDLE_IS_PRINTER:
335 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
336 *number = print_queue_snum(Printer->dev.handlename);
337 return (*number != -1);
338 case PRINTER_HANDLE_IS_PRINTSERVER:
339 return False;
340 default:
341 return False;
345 /****************************************************************************
346 set printer handle type.
347 ****************************************************************************/
348 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
350 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
352 if (!Printer) {
353 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
354 return False;
357 DEBUG(4,("Setting printer access=%x\n", access_required));
358 Printer->access = access_required;
359 return True;
362 /****************************************************************************
363 Set printer handle type.
364 Check if it's \\server or \\server\printer
365 ****************************************************************************/
367 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
369 DEBUG(3,("Setting printer type=%s\n", handlename));
371 if ( strlen(handlename) < 3 ) {
372 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
373 return False;
376 /* it's a print server */
377 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
378 DEBUGADD(4,("Printer is a print server\n"));
379 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
381 /* it's a printer */
382 else {
383 DEBUGADD(4,("Printer is a printer\n"));
384 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
387 return True;
390 /****************************************************************************
391 Set printer handle name.
392 ****************************************************************************/
394 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
396 NT_PRINTER_INFO_LEVEL *printer = NULL;
397 int snum;
398 int n_services=lp_numservices();
399 char *aprinter;
400 BOOL found=False;
402 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
404 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
405 ZERO_STRUCT(Printer->dev.printerservername);
406 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
407 return True;
410 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
411 return False;
413 if (*handlename=='\\') {
414 aprinter=strchr_m(handlename+2, '\\');
415 aprinter++;
417 else {
418 aprinter=handlename;
421 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
424 * store the Samba share name in it
425 * in back we have the long printer name
426 * need to iterate all the snum and do a
427 * get_a_printer each time to find the printer
428 * faster to do it here than later.
431 for (snum=0;snum<n_services && found==False;snum++) {
432 char *printername;
434 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
435 continue;
437 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
439 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
440 continue;
442 printername=strchr_m(printer->info_2->printername+2, '\\');
443 printername++;
445 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
446 printer->info_2->printername, aprinter ));
448 if ( strlen(printername) != strlen(aprinter) ) {
449 free_a_printer(&printer, 2);
450 continue;
453 if ( strncasecmp(printername, aprinter, strlen(aprinter))) {
454 free_a_printer(&printer, 2);
455 continue;
458 found=True;
462 * if we haven't found a printer with the given handlename
463 * then it can be a share name as you can open both \\server\printer and
464 * \\server\share
468 * we still check if the printer description file exists as NT won't be happy
469 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
472 if (found==False) {
473 DEBUGADD(5,("Printer not found, checking for share now\n"));
475 for (snum=0;snum<n_services && found==False;snum++) {
477 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
478 continue;
480 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
482 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
483 continue;
485 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
486 printer->info_2->printername, aprinter ));
488 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
489 free_a_printer(&printer, 2);
490 continue;
493 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
494 free_a_printer(&printer, 2);
495 continue;
498 found=True;
502 if (found==False) {
503 DEBUGADD(4,("Printer not found\n"));
504 return False;
507 snum--;
508 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
509 printer->info_2->printername, lp_servicename(snum),snum));
511 ZERO_STRUCT(Printer->dev.handlename);
512 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
514 free_a_printer(&printer, 2);
516 return True;
519 /****************************************************************************
520 find first available printer slot. creates a printer handle for you.
521 ****************************************************************************/
523 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
525 Printer_entry *new_printer;
527 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
529 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
530 return False;
532 ZERO_STRUCTP(new_printer);
534 new_printer->notify.option=NULL;
536 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
537 SAFE_FREE(new_printer);
538 return False;
541 if (!set_printer_hnd_printertype(new_printer, name)) {
542 close_printer_handle(p, hnd);
543 return False;
546 if (!set_printer_hnd_name(new_printer, name)) {
547 close_printer_handle(p, hnd);
548 return False;
551 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
553 return True;
556 /********************************************************************
557 Return True is the handle is a print server.
558 ********************************************************************/
560 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
562 Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
564 if (!Printer)
565 return False;
567 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
568 return False;
570 return True;
573 /****************************************************************************
574 allocate more memory for a BUFFER.
575 ****************************************************************************/
576 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
578 prs_struct *ps;
579 uint32 extra_space;
580 uint32 old_offset;
582 ps= &buffer->prs;
584 /* damn, I'm doing the reverse operation of prs_grow() :) */
585 if (buffer_size < prs_data_size(ps))
586 extra_space=0;
587 else
588 extra_space = buffer_size - prs_data_size(ps);
591 * save the offset and move to the end of the buffer
592 * prs_grow() checks the extra_space against the offset
594 old_offset=prs_offset(ps);
595 prs_set_offset(ps, prs_data_size(ps));
597 if (!prs_grow(ps, extra_space))
598 return False;
600 prs_set_offset(ps, old_offset);
602 buffer->string_at_end=prs_data_size(ps);
604 return True;
607 /***************************************************************************
608 receive the notify message
609 ****************************************************************************/
611 static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
613 fstring printer;
614 WERROR status;
615 struct pipes_struct *p;
616 struct policy *pol;
617 struct handle_list *hl;
619 *printer = '\0';
620 fstrcpy(printer,buf);
622 if (len == 0) {
623 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
624 return;
627 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
630 * We need to enumerate all printers. The handle list is shared
631 * across pipes of the same name, so just find the first open
632 * spoolss pipe.
635 hl = NULL;
636 for ( p = get_first_internal_pipe(); p; get_next_internal_pipe(p)) {
637 if (strequal(p->name, "spoolss")) {
638 hl = p->pipe_handles;
639 break;
643 if (!hl) {
644 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
645 return;
648 /* Iterate the printer list on this pipe. */
649 for (pol = hl->Policy; pol; pol = pol->next ) {
650 Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
652 if (!find_printer)
653 continue;
656 * if the entry is the given printer or if it's a printerserver
657 * we send the message
660 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
661 if (strcmp(find_printer->dev.handlename, printer))
662 continue;
664 if (find_printer->notify.client_connected==True)
665 cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
669 /***************************************************************************
670 send a notify event
671 ****************************************************************************/
672 static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle)
674 fstring printer;
676 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
678 if (!Printer) {
679 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
680 return False;
683 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
684 fstrcpy(printer, Printer->dev.handlename);
685 else
686 fstrcpy(printer, "");
688 /*srv_spoolss_receive_message(printer);*/
689 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
691 broadcast_printer_notify(printer);
693 return True;
696 /********************************************************************
697 * spoolss_open_printer
699 * called from the spoolss dispatcher
700 ********************************************************************/
702 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
704 #if 0
705 WERROR result = WERR_OK;
706 #endif
708 UNISTR2 *printername = NULL;
709 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
710 /* uint32 user_switch = q_u->user_switch; - notused */
711 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
712 POLICY_HND *handle = &r_u->handle;
714 fstring name;
715 int snum;
716 struct current_user user;
718 if (q_u->printername_ptr != 0)
719 printername = &q_u->printername;
721 if (printername == NULL)
722 return WERR_INVALID_PRINTER_NAME;
724 /* some sanity check because you can open a printer or a print server */
725 /* aka: \\server\printer or \\server */
726 unistr2_to_ascii(name, printername, sizeof(name)-1);
728 DEBUGADD(3,("checking name: %s\n",name));
730 if (!open_printer_hnd(p, handle, name))
731 return WERR_INVALID_PRINTER_NAME;
734 if (printer_default->datatype_ptr != NULL)
736 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
737 set_printer_hnd_datatype(handle, datatype);
739 else
740 set_printer_hnd_datatype(handle, "");
743 if (!set_printer_hnd_accesstype(p, handle, printer_default->access_required)) {
744 close_printer_handle(p, handle);
745 return WERR_ACCESS_DENIED;
749 First case: the user is opening the print server:
751 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
752 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
754 Then both Win2k and WinNT clients try an OpenPrinterEx with
755 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
756 or if the user is listed in the smb.conf printer admin parameter.
758 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
759 client view printer folder, but does not show the MSAPW.
761 Note: this test needs code to check access rights here too. Jeremy
762 could you look at this?
765 Second case: the user is opening a printer:
766 NT doesn't let us connect to a printer if the connecting user
767 doesn't have print permission.
771 get_current_user(&user, p);
773 if (handle_is_printserver(p, handle)) {
774 if (printer_default->access_required == 0) {
775 return WERR_OK;
777 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
779 /* Printserver handles use global struct... */
780 snum = -1;
782 if (!lp_ms_add_printer_wizard()) {
783 close_printer_handle(p, handle);
784 return WERR_ACCESS_DENIED;
786 else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
787 return WERR_OK;
789 else {
790 close_printer_handle(p, handle);
791 return WERR_ACCESS_DENIED;
795 else
797 /* NT doesn't let us connect to a printer if the connecting user
798 doesn't have print permission. */
800 if (!get_printer_snum(p, handle, &snum))
801 return WERR_BADFID;
803 /* map an empty access mask to the minimum access mask */
804 if (printer_default->access_required == 0x0)
805 printer_default->access_required = PRINTER_ACCESS_USE;
809 * If we are not serving the printer driver for this printer,
810 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
811 * will keep NT clients happy --jerry
814 if (lp_use_client_driver(snum)
815 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
817 printer_default->access_required = PRINTER_ACCESS_USE;
820 if (!print_access_check(&user, snum, printer_default->access_required)) {
821 DEBUG(3, ("access DENIED for printer open\n"));
822 close_printer_handle(p, handle);
823 return WERR_ACCESS_DENIED;
827 * If we have a default device pointer in the
828 * printer_default struct, then we need to get
829 * the printer info from the tdb and if there is
830 * no default devicemode there then we do a *SET*
831 * here ! This is insanity.... JRA.
835 * If the openprinterex rpc call contains a devmode,
836 * it's a per-user one. This per-user devmode is derivated
837 * from the global devmode. Openprinterex() contains a per-user
838 * devmode for when you do EMF printing and spooling.
839 * In the EMF case, the NT workstation is only doing half the job
840 * of rendering the page. The other half is done by running the printer
841 * driver on the server.
842 * The EMF file doesn't contain the page description (paper size, orientation, ...).
843 * The EMF file only contains what is to be printed on the page.
844 * So in order for the server to know how to print, the NT client sends
845 * a devicemode attached to the openprinterex call.
846 * But this devicemode is short lived, it's only valid for the current print job.
848 * If Samba would have supported EMF spooling, this devicemode would
849 * have been attached to the handle, to sent it to the driver to correctly
850 * rasterize the EMF file.
852 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
853 * we just act as a pass-thru between windows and the printer.
855 * In order to know that Samba supports only RAW spooling, NT has to call
856 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
857 * and until NT sends a RAW job, we refuse it.
859 * But to call getprinter() or startdoc(), you first need a valid handle,
860 * and to get an handle you have to call openprintex(). Hence why you have
861 * a devicemode in the openprinterex() call.
864 * Differences between NT4 and NT 2000.
865 * NT4:
866 * ---
867 * On NT4, you only have a global devicemode. This global devicemode can be changed
868 * by the administrator (or by a user with enough privs). Everytime a user
869 * wants to print, the devicemode is resetted to the default. In Word, everytime
870 * you print, the printer's characteristics are always reset to the global devicemode.
872 * NT 2000:
873 * -------
874 * In W2K, there is the notion of per-user devicemode. The first time you use
875 * a printer, a per-user devicemode is build from the global devicemode.
876 * If you change your per-user devicemode, it is saved in the registry, under the
877 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
878 * printer preferences available.
880 * To change the per-user devicemode: it's the "Printing Preferences ..." button
881 * on the General Tab of the printer properties windows.
883 * To change the global devicemode: it's the "Printing Defaults..." button
884 * on the Advanced Tab of the printer properties window.
886 * JFM.
891 #if 0
892 if (printer_default->devmode_cont.devmode != NULL) {
893 result = printer_write_default_dev( snum, printer_default);
894 if (result != 0) {
895 close_printer_handle(p, handle);
896 return result;
899 #endif
902 return WERR_OK;
905 /****************************************************************************
906 ****************************************************************************/
907 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
908 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
910 BOOL ret = True;
912 switch (level) {
913 case 2:
914 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
915 break;
916 default:
917 break;
920 return ret;
923 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
924 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
926 BOOL result = True;
928 switch (level) {
929 case 3:
930 printer->info_3=NULL;
931 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
932 result = False;
933 break;
934 case 6:
935 printer->info_6=NULL;
936 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
937 result = False;
938 break;
939 default:
940 break;
943 return result;
946 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
947 NT_DEVICEMODE **pp_nt_devmode)
949 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
952 * Ensure nt_devmode is a valid pointer
953 * as we will be overwriting it.
956 if (nt_devmode == NULL) {
957 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
958 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
959 return False;
962 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
963 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
965 nt_devmode->specversion=devmode->specversion;
966 nt_devmode->driverversion=devmode->driverversion;
967 nt_devmode->size=devmode->size;
968 nt_devmode->fields=devmode->fields;
969 nt_devmode->orientation=devmode->orientation;
970 nt_devmode->papersize=devmode->papersize;
971 nt_devmode->paperlength=devmode->paperlength;
972 nt_devmode->paperwidth=devmode->paperwidth;
973 nt_devmode->scale=devmode->scale;
974 nt_devmode->copies=devmode->copies;
975 nt_devmode->defaultsource=devmode->defaultsource;
976 nt_devmode->printquality=devmode->printquality;
977 nt_devmode->color=devmode->color;
978 nt_devmode->duplex=devmode->duplex;
979 nt_devmode->yresolution=devmode->yresolution;
980 nt_devmode->ttoption=devmode->ttoption;
981 nt_devmode->collate=devmode->collate;
983 nt_devmode->logpixels=devmode->logpixels;
984 nt_devmode->bitsperpel=devmode->bitsperpel;
985 nt_devmode->pelswidth=devmode->pelswidth;
986 nt_devmode->pelsheight=devmode->pelsheight;
987 nt_devmode->displayflags=devmode->displayflags;
988 nt_devmode->displayfrequency=devmode->displayfrequency;
989 nt_devmode->icmmethod=devmode->icmmethod;
990 nt_devmode->icmintent=devmode->icmintent;
991 nt_devmode->mediatype=devmode->mediatype;
992 nt_devmode->dithertype=devmode->dithertype;
993 nt_devmode->reserved1=devmode->reserved1;
994 nt_devmode->reserved2=devmode->reserved2;
995 nt_devmode->panningwidth=devmode->panningwidth;
996 nt_devmode->panningheight=devmode->panningheight;
999 * Only change private and driverextra if the incoming devmode
1000 * has a new one. JRA.
1003 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1004 SAFE_FREE(nt_devmode->private);
1005 nt_devmode->driverextra=devmode->driverextra;
1006 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1007 return False;
1008 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1011 *pp_nt_devmode = nt_devmode;
1013 return True;
1016 /********************************************************************
1017 * _spoolss_enddocprinter_internal.
1018 ********************************************************************/
1020 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1022 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1024 if (!Printer) {
1025 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1026 return WERR_BADFID;
1029 Printer->document_started=False;
1030 print_job_end(Printer->jobid,True);
1031 /* error codes unhandled so far ... */
1033 return WERR_OK;
1036 /********************************************************************
1037 * api_spoolss_closeprinter
1038 ********************************************************************/
1040 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1042 POLICY_HND *handle = &q_u->handle;
1044 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1046 if (Printer && Printer->document_started)
1047 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1049 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1051 if (!close_printer_handle(p, handle))
1052 return WERR_BADFID;
1054 return WERR_OK;
1057 /********************************************************************
1058 * api_spoolss_deleteprinter
1060 ********************************************************************/
1062 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1064 POLICY_HND *handle = &q_u->handle;
1065 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1066 WERROR result;
1068 if (Printer && Printer->document_started)
1069 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1071 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1073 result = delete_printer_handle(p, handle);
1075 if (W_ERROR_IS_OK(result)) {
1076 srv_spoolss_sendnotify(p, handle);
1079 return result;
1082 /*******************************************************************
1083 * static function to lookup the version id corresponding to an
1084 * long architecture string
1085 ******************************************************************/
1086 static int get_version_id (char * arch)
1088 int i;
1089 struct table_node archi_table[]= {
1091 {"Windows 4.0", "WIN40", 0 },
1092 {"Windows NT x86", "W32X86", 2 },
1093 {"Windows NT R4000", "W32MIPS", 2 },
1094 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1095 {"Windows NT PowerPC", "W32PPC", 2 },
1096 {NULL, "", -1 }
1099 for (i=0; archi_table[i].long_archi != NULL; i++)
1101 if (strcmp(arch, archi_table[i].long_archi) == 0)
1102 return (archi_table[i].version);
1105 return -1;
1108 /********************************************************************
1109 * _spoolss_deleteprinterdriver
1111 * We currently delete the driver for the architecture only.
1112 * This can leave the driver for other archtectures. However,
1113 * since every printer associates a "Windows NT x86" driver name
1114 * and we cannot delete that one while it is in use, **and** since
1115 * it is impossible to assign a driver to a Samba printer without
1116 * having the "Windows NT x86" driver installed,...
1118 * ....we should not get into trouble here.
1120 * --jerry
1121 ********************************************************************/
1123 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
1124 SPOOL_R_DELETEPRINTERDRIVER *r_u)
1126 fstring driver;
1127 fstring arch;
1128 NT_PRINTER_DRIVER_INFO_LEVEL info;
1129 int version;
1131 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1132 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1134 /* check that we have a valid driver name first */
1135 if ((version=get_version_id(arch)) == -1) {
1136 /* this is what NT returns */
1137 return WERR_INVALID_ENVIRONMENT;
1140 ZERO_STRUCT(info);
1141 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1142 return WERR_UNKNOWN_PRINTER_DRIVER;
1146 if (printer_driver_in_use(arch, driver))
1148 return WERR_PRINTER_DRIVER_IN_USE;
1151 return delete_printer_driver(info.info_3);
1155 /********************************************************************
1156 GetPrinterData on a printer server Handle.
1157 ********************************************************************/
1158 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1160 int i;
1162 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1164 if (!strcmp(value, "BeepEnabled")) {
1165 *type = 0x4;
1166 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1167 return False;
1168 SIVAL(*data, 0, 0x01);
1169 *needed = 0x4;
1170 return True;
1173 if (!strcmp(value, "EventLog")) {
1174 *type = 0x4;
1175 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1176 return False;
1177 SIVAL(*data, 0, 0x1B);
1178 *needed = 0x4;
1179 return True;
1182 if (!strcmp(value, "NetPopup")) {
1183 *type = 0x4;
1184 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1185 return False;
1186 SIVAL(*data, 0, 0x01);
1187 *needed = 0x4;
1188 return True;
1191 if (!strcmp(value, "MajorVersion")) {
1192 *type = 0x4;
1193 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1194 return False;
1195 SIVAL(*data, 0, 0x02);
1196 *needed = 0x4;
1197 return True;
1200 if (!strcmp(value, "DefaultSpoolDirectory")) {
1201 pstring string="You are using a Samba server";
1202 *type = 0x1;
1203 *needed = 2*(strlen(string)+1);
1204 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1205 return False;
1206 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1208 /* it's done by hand ready to go on the wire */
1209 for (i=0; i<strlen(string); i++) {
1210 (*data)[2*i]=string[i];
1211 (*data)[2*i+1]='\0';
1213 return True;
1216 if (!strcmp(value, "Architecture")) {
1217 pstring string="Windows NT x86";
1218 *type = 0x1;
1219 *needed = 2*(strlen(string)+1);
1220 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1221 return False;
1222 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1223 for (i=0; i<strlen(string); i++) {
1224 (*data)[2*i]=string[i];
1225 (*data)[2*i+1]='\0';
1227 return True;
1230 return False;
1233 /********************************************************************
1234 GetPrinterData on a printer Handle.
1235 ********************************************************************/
1236 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1237 fstring value, uint32 *type,
1238 uint8 **data, uint32 *needed, uint32 in_size )
1240 NT_PRINTER_INFO_LEVEL *printer = NULL;
1241 int snum=0;
1242 uint8 *idata=NULL;
1243 uint32 len;
1244 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1246 DEBUG(5,("getprinterdata_printer\n"));
1248 if (!Printer) {
1249 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1250 return False;
1253 if(!get_printer_snum(p, handle, &snum))
1254 return False;
1256 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
1257 return False;
1259 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1260 free_a_printer(&printer, 2);
1261 return False;
1264 free_a_printer(&printer, 2);
1266 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1268 if (in_size) {
1269 if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1270 return False;
1273 memset(*data, 0, in_size *sizeof(uint8));
1274 /* copy the min(in_size, len) */
1275 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1276 } else {
1277 *data = NULL;
1280 *needed = len;
1282 DEBUG(5,("getprinterdata_printer:copy done\n"));
1284 SAFE_FREE(idata);
1286 return True;
1289 /********************************************************************
1290 * spoolss_getprinterdata
1291 ********************************************************************/
1293 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1295 POLICY_HND *handle = &q_u->handle;
1296 UNISTR2 *valuename = &q_u->valuename;
1297 uint32 in_size = q_u->size;
1298 uint32 *type = &r_u->type;
1299 uint32 *out_size = &r_u->size;
1300 uint8 **data = &r_u->data;
1301 uint32 *needed = &r_u->needed;
1303 fstring value;
1304 BOOL found=False;
1305 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1308 * Reminder: when it's a string, the length is in BYTES
1309 * even if UNICODE is negociated.
1311 * JFM, 4/19/1999
1314 *out_size=in_size;
1316 /* in case of problem, return some default values */
1317 *needed=0;
1318 *type=0;
1320 DEBUG(4,("_spoolss_getprinterdata\n"));
1322 if (!Printer) {
1323 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
1324 return WERR_NOMEM;
1325 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1326 return WERR_BADFID;
1329 unistr2_to_ascii(value, valuename, sizeof(value)-1);
1331 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1332 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1333 else
1334 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1336 if (found==False) {
1337 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1338 /* reply this param doesn't exist */
1339 if (*out_size) {
1340 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1341 return WERR_NOMEM;
1342 } else {
1343 *data = NULL;
1346 return WERR_INVALID_PARAM;
1349 if (*needed > *out_size)
1350 return WERR_STATUS_MORE_ENTRIES;
1351 else
1352 return WERR_OK;
1355 /***************************************************************************
1356 connect to the client
1357 ****************************************************************************/
1358 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1360 WERROR status;
1363 * If it's the first connection, contact the client
1364 * and connect to the IPC$ share anonumously
1366 if (smb_connections==0) {
1367 fstring unix_printer;
1369 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
1371 if(!spoolss_connect_to_client(&cli, unix_printer))
1372 return False;
1373 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1377 smb_connections++;
1379 if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1380 return False;
1382 return True;
1385 /********************************************************************
1386 * _spoolss_rffpcnex
1387 * ReplyFindFirstPrinterChangeNotifyEx
1389 * jfmxxxx: before replying OK: status=0
1390 * should do a rpc call to the workstation asking ReplyOpenPrinter
1391 * have to code it, later.
1393 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1394 * called from api_spoolss_rffpcnex
1395 ********************************************************************/
1397 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1399 POLICY_HND *handle = &q_u->handle;
1400 uint32 flags = q_u->flags;
1401 uint32 options = q_u->options;
1402 UNISTR2 *localmachine = &q_u->localmachine;
1403 uint32 printerlocal = q_u->printerlocal;
1404 SPOOL_NOTIFY_OPTION *option = q_u->option;
1406 /* store the notify value in the printer struct */
1408 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1410 if (!Printer) {
1411 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1412 return WERR_BADFID;
1415 Printer->notify.flags=flags;
1416 Printer->notify.options=options;
1417 Printer->notify.printerlocal=printerlocal;
1419 if (Printer->notify.option)
1420 free_spool_notify_option(&Printer->notify.option);
1422 Printer->notify.option=dup_spool_notify_option(option);
1424 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1426 /* connect to the client machine and send a ReplyOpenPrinter */
1427 if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1428 Printer->notify.printerlocal, 1,
1429 &Printer->notify.client_hnd))
1430 Printer->notify.client_connected=True;
1432 return WERR_OK;
1435 /*******************************************************************
1436 * fill a notify_info_data with the servername
1437 ********************************************************************/
1439 static void spoolss_notify_server_name(int snum,
1440 SPOOL_NOTIFY_INFO_DATA *data,
1441 print_queue_struct *queue,
1442 NT_PRINTER_INFO_LEVEL *printer,
1443 TALLOC_CTX *mem_ctx)
1445 pstring temp_name, temp;
1446 uint32 len;
1448 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
1450 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
1452 data->notify_data.data.length = len / 2;
1453 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1455 if (!data->notify_data.data.string) {
1456 data->notify_data.data.length = 0;
1457 return;
1460 memcpy(data->notify_data.data.string, temp, len);
1463 /*******************************************************************
1464 * fill a notify_info_data with the printername (not including the servername).
1465 ********************************************************************/
1466 static void spoolss_notify_printer_name(int snum,
1467 SPOOL_NOTIFY_INFO_DATA *data,
1468 print_queue_struct *queue,
1469 NT_PRINTER_INFO_LEVEL *printer,
1470 TALLOC_CTX *mem_ctx)
1472 pstring temp;
1473 uint32 len;
1475 /* the notify name should not contain the \\server\ part */
1476 char *p = strrchr_m(printer->info_2->printername, '\\');
1478 if (!p) {
1479 p = printer->info_2->printername;
1480 } else {
1481 p++;
1484 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
1485 data->notify_data.data.length = len / 2;
1486 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1488 if (!data->notify_data.data.string) {
1489 data->notify_data.data.length = 0;
1490 return;
1493 memcpy(data->notify_data.data.string, temp, len);
1496 /*******************************************************************
1497 * fill a notify_info_data with the servicename
1498 ********************************************************************/
1499 static void spoolss_notify_share_name(int snum,
1500 SPOOL_NOTIFY_INFO_DATA *data,
1501 print_queue_struct *queue,
1502 NT_PRINTER_INFO_LEVEL *printer,
1503 TALLOC_CTX *mem_ctx)
1505 pstring temp;
1506 uint32 len;
1508 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
1510 data->notify_data.data.length = len / 2;
1511 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1513 if (!data->notify_data.data.string) {
1514 data->notify_data.data.length = 0;
1515 return;
1518 memcpy(data->notify_data.data.string, temp, len);
1521 /*******************************************************************
1522 * fill a notify_info_data with the port name
1523 ********************************************************************/
1524 static void spoolss_notify_port_name(int snum,
1525 SPOOL_NOTIFY_INFO_DATA *data,
1526 print_queue_struct *queue,
1527 NT_PRINTER_INFO_LEVEL *printer,
1528 TALLOC_CTX *mem_ctx)
1530 pstring temp;
1531 uint32 len;
1533 /* even if it's strange, that's consistant in all the code */
1535 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
1537 data->notify_data.data.length = len / 2;
1538 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1540 if (!data->notify_data.data.string) {
1541 data->notify_data.data.length = 0;
1542 return;
1545 memcpy(data->notify_data.data.string, temp, len);
1548 /*******************************************************************
1549 * fill a notify_info_data with the printername
1550 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1551 * but it doesn't exist, have to see what to do
1552 ********************************************************************/
1553 static void spoolss_notify_driver_name(int snum,
1554 SPOOL_NOTIFY_INFO_DATA *data,
1555 print_queue_struct *queue,
1556 NT_PRINTER_INFO_LEVEL *printer,
1557 TALLOC_CTX *mem_ctx)
1559 pstring temp;
1560 uint32 len;
1562 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
1563 data->notify_data.data.length = len / 2;
1564 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1566 if (!data->notify_data.data.string) {
1567 data->notify_data.data.length = 0;
1568 return;
1571 memcpy(data->notify_data.data.string, temp, len);
1574 /*******************************************************************
1575 * fill a notify_info_data with the comment
1576 ********************************************************************/
1577 static void spoolss_notify_comment(int snum,
1578 SPOOL_NOTIFY_INFO_DATA *data,
1579 print_queue_struct *queue,
1580 NT_PRINTER_INFO_LEVEL *printer,
1581 TALLOC_CTX *mem_ctx)
1583 pstring temp;
1584 uint32 len;
1586 if (*printer->info_2->comment == '\0')
1587 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
1589 else
1590 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
1592 data->notify_data.data.length = len / 2;
1593 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1595 if (!data->notify_data.data.string) {
1596 data->notify_data.data.length = 0;
1597 return;
1600 memcpy(data->notify_data.data.string, temp, len);
1603 /*******************************************************************
1604 * fill a notify_info_data with the comment
1605 * jfm:xxxx incorrect, have to create a new smb.conf option
1606 * location = "Room 1, floor 2, building 3"
1607 ********************************************************************/
1608 static void spoolss_notify_location(int snum,
1609 SPOOL_NOTIFY_INFO_DATA *data,
1610 print_queue_struct *queue,
1611 NT_PRINTER_INFO_LEVEL *printer,
1612 TALLOC_CTX *mem_ctx)
1614 pstring temp;
1615 uint32 len;
1617 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
1619 data->notify_data.data.length = len / 2;
1620 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1622 if (!data->notify_data.data.string) {
1623 data->notify_data.data.length = 0;
1624 return;
1627 memcpy(data->notify_data.data.string, temp, len);
1630 /*******************************************************************
1631 * fill a notify_info_data with the device mode
1632 * jfm:xxxx don't to it for know but that's a real problem !!!
1633 ********************************************************************/
1634 static void spoolss_notify_devmode(int snum,
1635 SPOOL_NOTIFY_INFO_DATA *data,
1636 print_queue_struct *queue,
1637 NT_PRINTER_INFO_LEVEL *printer,
1638 TALLOC_CTX *mem_ctx)
1642 /*******************************************************************
1643 * fill a notify_info_data with the separator file name
1644 * jfm:xxxx just return no file could add an option to smb.conf
1645 * separator file = "separator.txt"
1646 ********************************************************************/
1647 static void spoolss_notify_sepfile(int snum,
1648 SPOOL_NOTIFY_INFO_DATA *data,
1649 print_queue_struct *queue,
1650 NT_PRINTER_INFO_LEVEL *printer,
1651 TALLOC_CTX *mem_ctx)
1653 pstring temp;
1654 uint32 len;
1656 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
1658 data->notify_data.data.length = len / 2;
1659 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1661 if (!data->notify_data.data.string) {
1662 data->notify_data.data.length = 0;
1663 return;
1666 memcpy(data->notify_data.data.string, temp, len);
1669 /*******************************************************************
1670 * fill a notify_info_data with the print processor
1671 * jfm:xxxx return always winprint to indicate we don't do anything to it
1672 ********************************************************************/
1673 static void spoolss_notify_print_processor(int snum,
1674 SPOOL_NOTIFY_INFO_DATA *data,
1675 print_queue_struct *queue,
1676 NT_PRINTER_INFO_LEVEL *printer,
1677 TALLOC_CTX *mem_ctx)
1679 pstring temp;
1680 uint32 len;
1682 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
1684 data->notify_data.data.length = len / 2;
1685 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1687 if (!data->notify_data.data.string) {
1688 data->notify_data.data.length = 0;
1689 return;
1692 memcpy(data->notify_data.data.string, temp, len);
1695 /*******************************************************************
1696 * fill a notify_info_data with the print processor options
1697 * jfm:xxxx send an empty string
1698 ********************************************************************/
1699 static void spoolss_notify_parameters(int snum,
1700 SPOOL_NOTIFY_INFO_DATA *data,
1701 print_queue_struct *queue,
1702 NT_PRINTER_INFO_LEVEL *printer,
1703 TALLOC_CTX *mem_ctx)
1705 pstring temp;
1706 uint32 len;
1708 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
1710 data->notify_data.data.length = len / 2;
1711 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1713 if (!data->notify_data.data.string) {
1714 data->notify_data.data.length = 0;
1715 return;
1718 memcpy(data->notify_data.data.string, temp, len);
1721 /*******************************************************************
1722 * fill a notify_info_data with the data type
1723 * jfm:xxxx always send RAW as data type
1724 ********************************************************************/
1725 static void spoolss_notify_datatype(int snum,
1726 SPOOL_NOTIFY_INFO_DATA *data,
1727 print_queue_struct *queue,
1728 NT_PRINTER_INFO_LEVEL *printer,
1729 TALLOC_CTX *mem_ctx)
1731 pstring temp;
1732 uint32 len;
1734 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
1736 data->notify_data.data.length = len / 2;
1737 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1739 if (!data->notify_data.data.string) {
1740 data->notify_data.data.length = 0;
1741 return;
1744 memcpy(data->notify_data.data.string, temp, len);
1747 /*******************************************************************
1748 * fill a notify_info_data with the security descriptor
1749 * jfm:xxxx send an null pointer to say no security desc
1750 * have to implement security before !
1751 ********************************************************************/
1752 static void spoolss_notify_security_desc(int snum,
1753 SPOOL_NOTIFY_INFO_DATA *data,
1754 print_queue_struct *queue,
1755 NT_PRINTER_INFO_LEVEL *printer,
1756 TALLOC_CTX *mem_ctx)
1758 data->notify_data.data.length=0;
1759 data->notify_data.data.string = NULL;
1762 /*******************************************************************
1763 * fill a notify_info_data with the attributes
1764 * jfm:xxxx a samba printer is always shared
1765 ********************************************************************/
1766 static void spoolss_notify_attributes(int snum,
1767 SPOOL_NOTIFY_INFO_DATA *data,
1768 print_queue_struct *queue,
1769 NT_PRINTER_INFO_LEVEL *printer,
1770 TALLOC_CTX *mem_ctx)
1772 data->notify_data.value[0] = printer->info_2->attributes;
1773 data->notify_data.value[1] = 0;
1776 /*******************************************************************
1777 * fill a notify_info_data with the priority
1778 ********************************************************************/
1779 static void spoolss_notify_priority(int snum,
1780 SPOOL_NOTIFY_INFO_DATA *data,
1781 print_queue_struct *queue,
1782 NT_PRINTER_INFO_LEVEL *printer,
1783 TALLOC_CTX *mem_ctx)
1785 data->notify_data.value[0] = printer->info_2->priority;
1786 data->notify_data.value[1] = 0;
1789 /*******************************************************************
1790 * fill a notify_info_data with the default priority
1791 ********************************************************************/
1792 static void spoolss_notify_default_priority(int snum,
1793 SPOOL_NOTIFY_INFO_DATA *data,
1794 print_queue_struct *queue,
1795 NT_PRINTER_INFO_LEVEL *printer,
1796 TALLOC_CTX *mem_ctx)
1798 data->notify_data.value[0] = printer->info_2->default_priority;
1799 data->notify_data.value[1] = 0;
1802 /*******************************************************************
1803 * fill a notify_info_data with the start time
1804 ********************************************************************/
1805 static void spoolss_notify_start_time(int snum,
1806 SPOOL_NOTIFY_INFO_DATA *data,
1807 print_queue_struct *queue,
1808 NT_PRINTER_INFO_LEVEL *printer,
1809 TALLOC_CTX *mem_ctx)
1811 data->notify_data.value[0] = printer->info_2->starttime;
1812 data->notify_data.value[1] = 0;
1815 /*******************************************************************
1816 * fill a notify_info_data with the until time
1817 ********************************************************************/
1818 static void spoolss_notify_until_time(int snum,
1819 SPOOL_NOTIFY_INFO_DATA *data,
1820 print_queue_struct *queue,
1821 NT_PRINTER_INFO_LEVEL *printer,
1822 TALLOC_CTX *mem_ctx)
1824 data->notify_data.value[0] = printer->info_2->untiltime;
1825 data->notify_data.value[1] = 0;
1828 /*******************************************************************
1829 * fill a notify_info_data with the status
1830 ********************************************************************/
1831 static void spoolss_notify_status(int snum,
1832 SPOOL_NOTIFY_INFO_DATA *data,
1833 print_queue_struct *queue,
1834 NT_PRINTER_INFO_LEVEL *printer,
1835 TALLOC_CTX *mem_ctx)
1837 print_status_struct status;
1839 print_queue_length(snum, &status);
1840 data->notify_data.value[0]=(uint32) status.status;
1841 data->notify_data.value[1] = 0;
1844 /*******************************************************************
1845 * fill a notify_info_data with the number of jobs queued
1846 ********************************************************************/
1847 static void spoolss_notify_cjobs(int snum,
1848 SPOOL_NOTIFY_INFO_DATA *data,
1849 print_queue_struct *queue,
1850 NT_PRINTER_INFO_LEVEL *printer,
1851 TALLOC_CTX *mem_ctx)
1853 data->notify_data.value[0] = print_queue_length(snum, NULL);
1854 data->notify_data.value[1] = 0;
1857 /*******************************************************************
1858 * fill a notify_info_data with the average ppm
1859 ********************************************************************/
1860 static void spoolss_notify_average_ppm(int snum,
1861 SPOOL_NOTIFY_INFO_DATA *data,
1862 print_queue_struct *queue,
1863 NT_PRINTER_INFO_LEVEL *printer,
1864 TALLOC_CTX *mem_ctx)
1866 /* always respond 8 pages per minutes */
1867 /* a little hard ! */
1868 data->notify_data.value[0] = printer->info_2->averageppm;
1869 data->notify_data.value[1] = 0;
1872 /*******************************************************************
1873 * fill a notify_info_data with username
1874 ********************************************************************/
1875 static void spoolss_notify_username(int snum,
1876 SPOOL_NOTIFY_INFO_DATA *data,
1877 print_queue_struct *queue,
1878 NT_PRINTER_INFO_LEVEL *printer,
1879 TALLOC_CTX *mem_ctx)
1881 pstring temp;
1882 uint32 len;
1884 len = rpcstr_push(temp, queue->user, sizeof(temp)-2, STR_TERMINATE);
1887 data->notify_data.data.length = len / 2;
1888 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1890 if (!data->notify_data.data.string) {
1891 data->notify_data.data.length = 0;
1892 return;
1895 memcpy(data->notify_data.data.string, temp, len);
1898 /*******************************************************************
1899 * fill a notify_info_data with job status
1900 ********************************************************************/
1901 static void spoolss_notify_job_status(int snum,
1902 SPOOL_NOTIFY_INFO_DATA *data,
1903 print_queue_struct *queue,
1904 NT_PRINTER_INFO_LEVEL *printer,
1905 TALLOC_CTX *mem_ctx)
1907 data->notify_data.value[0]=nt_printj_status(queue->status);
1908 data->notify_data.value[1] = 0;
1911 /*******************************************************************
1912 * fill a notify_info_data with job name
1913 ********************************************************************/
1914 static void spoolss_notify_job_name(int snum,
1915 SPOOL_NOTIFY_INFO_DATA *data,
1916 print_queue_struct *queue,
1917 NT_PRINTER_INFO_LEVEL *printer,
1918 TALLOC_CTX *mem_ctx)
1920 pstring temp;
1921 uint32 len;
1923 len = rpcstr_push(temp, queue->file, sizeof(temp)-2, STR_TERMINATE);
1925 data->notify_data.data.length = len / 2;
1926 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1928 if (!data->notify_data.data.string) {
1929 data->notify_data.data.length = 0;
1930 return;
1933 memcpy(data->notify_data.data.string, temp, len);
1936 /*******************************************************************
1937 * fill a notify_info_data with job status
1938 ********************************************************************/
1939 static void spoolss_notify_job_status_string(int snum,
1940 SPOOL_NOTIFY_INFO_DATA *data,
1941 print_queue_struct *queue,
1942 NT_PRINTER_INFO_LEVEL *printer,
1943 TALLOC_CTX *mem_ctx)
1946 * Now we're returning job status codes we just return a "" here. JRA.
1949 char *p = "";
1950 pstring temp;
1951 uint32 len;
1953 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1954 p = "unknown";
1956 switch (queue->status) {
1957 case LPQ_QUEUED:
1958 p = "Queued";
1959 break;
1960 case LPQ_PAUSED:
1961 p = ""; /* NT provides the paused string */
1962 break;
1963 case LPQ_SPOOLING:
1964 p = "Spooling";
1965 break;
1966 case LPQ_PRINTING:
1967 p = "Printing";
1968 break;
1970 #endif /* NO LONGER NEEDED. */
1972 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
1974 data->notify_data.data.length = len / 2;
1975 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1977 if (!data->notify_data.data.string) {
1978 data->notify_data.data.length = 0;
1979 return;
1982 memcpy(data->notify_data.data.string, temp, len);
1985 /*******************************************************************
1986 * fill a notify_info_data with job time
1987 ********************************************************************/
1988 static void spoolss_notify_job_time(int snum,
1989 SPOOL_NOTIFY_INFO_DATA *data,
1990 print_queue_struct *queue,
1991 NT_PRINTER_INFO_LEVEL *printer,
1992 TALLOC_CTX *mem_ctx)
1994 data->notify_data.value[0]=0x0;
1995 data->notify_data.value[1]=0;
1998 /*******************************************************************
1999 * fill a notify_info_data with job size
2000 ********************************************************************/
2001 static void spoolss_notify_job_size(int snum,
2002 SPOOL_NOTIFY_INFO_DATA *data,
2003 print_queue_struct *queue,
2004 NT_PRINTER_INFO_LEVEL *printer,
2005 TALLOC_CTX *mem_ctx)
2007 data->notify_data.value[0]=queue->size;
2008 data->notify_data.value[1]=0;
2011 /*******************************************************************
2012 Fill a notify_info_data with job position.
2013 ********************************************************************/
2015 static void spoolss_notify_job_position(int snum,
2016 SPOOL_NOTIFY_INFO_DATA *data,
2017 print_queue_struct *queue,
2018 NT_PRINTER_INFO_LEVEL *printer,
2019 TALLOC_CTX *mem_ctx)
2021 data->notify_data.value[0]=queue->job;
2022 data->notify_data.value[1]=0;
2025 /*******************************************************************
2026 Fill a notify_info_data with submitted time.
2027 ********************************************************************/
2029 static void spoolss_notify_submitted_time(int snum,
2030 SPOOL_NOTIFY_INFO_DATA *data,
2031 print_queue_struct *queue,
2032 NT_PRINTER_INFO_LEVEL *printer,
2033 TALLOC_CTX *mem_ctx)
2035 struct tm *t;
2036 uint32 len;
2037 SYSTEMTIME st;
2038 char *p;
2040 t=gmtime(&queue->time);
2042 len = sizeof(SYSTEMTIME);
2044 data->notify_data.data.length = len;
2045 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2047 if (!data->notify_data.data.string) {
2048 data->notify_data.data.length = 0;
2049 return;
2052 make_systemtime(&st, t);
2055 * Systemtime must be linearized as a set of UINT16's.
2056 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2059 p = (char *)data->notify_data.data.string;
2060 SSVAL(p, 0, st.year);
2061 SSVAL(p, 2, st.month);
2062 SSVAL(p, 4, st.dayofweek);
2063 SSVAL(p, 6, st.day);
2064 SSVAL(p, 8, st.hour);
2065 SSVAL(p, 10, st.minute);
2066 SSVAL(p, 12, st.second);
2067 SSVAL(p, 14, st.milliseconds);
2070 #define END 65535
2072 struct s_notify_info_data_table
2074 uint16 type;
2075 uint16 field;
2076 char *name;
2077 uint32 size;
2078 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
2079 print_queue_struct *queue,
2080 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2083 struct s_notify_info_data_table notify_info_data_table[] =
2085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
2086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
2088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2089 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2090 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
2091 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
2092 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2093 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
2094 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2095 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2096 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2097 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
2098 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
2099 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2100 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
2101 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2102 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2103 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
2104 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
2105 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
2106 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
2107 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
2108 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
2109 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
2110 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
2111 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
2112 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
2113 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
2114 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
2115 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
2116 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
2117 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
2118 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
2119 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
2120 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
2121 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
2122 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
2123 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
2124 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
2125 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
2126 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
2127 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
2128 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
2129 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
2130 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
2131 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
2132 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
2133 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
2134 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
2135 { END, END, "", END, NULL }
2138 /*******************************************************************
2139 return the size of info_data structure
2140 ********************************************************************/
2141 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2143 int i=0;
2145 while (notify_info_data_table[i].type != END)
2147 if ( (notify_info_data_table[i].type == type ) &&
2148 (notify_info_data_table[i].field == field ) )
2150 return (notify_info_data_table[i].size);
2152 i++;
2154 return (65535);
2157 /*******************************************************************
2158 return the type of notify_info_data
2159 ********************************************************************/
2160 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2162 int i=0;
2164 while (notify_info_data_table[i].type != END)
2166 if ( (notify_info_data_table[i].type == type ) &&
2167 (notify_info_data_table[i].field == field ) )
2169 if (notify_info_data_table[i].size == POINTER)
2171 return (False);
2173 else
2175 return (True);
2178 i++;
2180 return (False);
2183 /****************************************************************************
2184 ****************************************************************************/
2185 static int search_notify(uint16 type, uint16 field, int *value)
2187 int j;
2188 BOOL found;
2190 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2192 if ( (notify_info_data_table[j].type == type ) &&
2193 (notify_info_data_table[j].field == field ) )
2194 found=True;
2196 *value=--j;
2198 if ( found && (notify_info_data_table[j].fn != NULL) )
2199 return True;
2200 else
2201 return False;
2204 /****************************************************************************
2205 ****************************************************************************/
2206 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2208 info_data->type = type;
2209 info_data->field = field;
2210 info_data->reserved = 0;
2211 info_data->id = id;
2212 info_data->size = size_of_notify_info_data(type, field);
2213 info_data->enc_type = type_of_notify_info_data(type, field);
2217 /*******************************************************************
2219 * fill a notify_info struct with info asked
2221 ********************************************************************/
2222 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2223 snum, SPOOL_NOTIFY_OPTION_TYPE
2224 *option_type, uint32 id,
2225 TALLOC_CTX *mem_ctx)
2227 int field_num,j;
2228 uint16 type;
2229 uint16 field;
2231 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2232 NT_PRINTER_INFO_LEVEL *printer = NULL;
2233 print_queue_struct *queue=NULL;
2235 type=option_type->type;
2237 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2238 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2239 option_type->count, lp_servicename(snum)));
2241 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2242 return False;
2244 for(field_num=0; field_num<option_type->count; field_num++) {
2245 field = option_type->fields[field_num];
2246 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2248 if (!search_notify(type, field, &j) )
2249 continue;
2251 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2252 DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2253 return False;
2255 else info->data = tid;
2257 current_data=&info->data[info->count];
2259 construct_info_data(current_data, type, field, id);
2261 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2262 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2264 notify_info_data_table[j].fn(snum, current_data, queue,
2265 printer, mem_ctx);
2267 info->count++;
2270 free_a_printer(&printer, 2);
2271 return True;
2274 /*******************************************************************
2276 * fill a notify_info struct with info asked
2278 ********************************************************************/
2279 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2280 SPOOL_NOTIFY_INFO *info,
2281 NT_PRINTER_INFO_LEVEL *printer,
2282 int snum, SPOOL_NOTIFY_OPTION_TYPE
2283 *option_type, uint32 id,
2284 TALLOC_CTX *mem_ctx)
2286 int field_num,j;
2287 uint16 type;
2288 uint16 field;
2290 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
2292 DEBUG(4,("construct_notify_jobs_info\n"));
2294 type = option_type->type;
2296 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2297 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2298 option_type->count));
2300 for(field_num=0; field_num<option_type->count; field_num++) {
2301 field = option_type->fields[field_num];
2303 if (!search_notify(type, field, &j) )
2304 continue;
2306 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2307 DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2308 return False;
2310 else info->data = tid;
2312 current_data=&(info->data[info->count]);
2314 construct_info_data(current_data, type, field, id);
2315 notify_info_data_table[j].fn(snum, current_data, queue,
2316 printer, mem_ctx);
2317 info->count++;
2320 return True;
2324 * JFM: The enumeration is not that simple, it's even non obvious.
2326 * let's take an example: I want to monitor the PRINTER SERVER for
2327 * the printer's name and the number of jobs currently queued.
2328 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2329 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2331 * I have 3 printers on the back of my server.
2333 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2334 * structures.
2335 * Number Data Id
2336 * 1 printer 1 name 1
2337 * 2 printer 1 cjob 1
2338 * 3 printer 2 name 2
2339 * 4 printer 2 cjob 2
2340 * 5 printer 3 name 3
2341 * 6 printer 3 name 3
2343 * that's the print server case, the printer case is even worse.
2346 /*******************************************************************
2348 * enumerate all printers on the printserver
2349 * fill a notify_info struct with info asked
2351 ********************************************************************/
2353 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
2354 SPOOL_NOTIFY_INFO *info,
2355 TALLOC_CTX *mem_ctx)
2357 int snum;
2358 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2359 int n_services=lp_numservices();
2360 int i;
2361 uint32 id;
2362 SPOOL_NOTIFY_OPTION *option;
2363 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2365 DEBUG(4,("printserver_notify_info\n"));
2367 option=Printer->notify.option;
2368 id=1;
2369 info->version=2;
2370 info->data=NULL;
2371 info->count=0;
2373 for (i=0; i<option->count; i++) {
2374 option_type=&(option->ctr.type[i]);
2376 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2377 continue;
2379 for (snum=0; snum<n_services; snum++)
2380 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2381 if (construct_notify_printer_info
2382 (info, snum, option_type, id, mem_ctx))
2383 id++;
2387 * Debugging information, don't delete.
2390 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2391 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2392 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2394 for (i=0; i<info->count; i++) {
2395 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2396 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2397 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2401 return WERR_OK;
2404 /*******************************************************************
2406 * fill a notify_info struct with info asked
2408 ********************************************************************/
2409 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2410 TALLOC_CTX *mem_ctx)
2412 int snum;
2413 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2414 int i;
2415 uint32 id;
2416 SPOOL_NOTIFY_OPTION *option;
2417 SPOOL_NOTIFY_OPTION_TYPE *option_type;
2418 int count,j;
2419 print_queue_struct *queue=NULL;
2420 print_status_struct status;
2422 DEBUG(4,("printer_notify_info\n"));
2424 option=Printer->notify.option;
2425 id=0xffffffff;
2426 info->version=2;
2427 info->data=NULL;
2428 info->count=0;
2430 get_printer_snum(p, hnd, &snum);
2432 for (i=0; i<option->count; i++) {
2433 option_type=&option->ctr.type[i];
2435 switch ( option_type->type ) {
2436 case PRINTER_NOTIFY_TYPE:
2437 if(construct_notify_printer_info(info, snum,
2438 option_type, id,
2439 mem_ctx))
2440 id--;
2441 break;
2443 case JOB_NOTIFY_TYPE: {
2444 NT_PRINTER_INFO_LEVEL *printer = NULL;
2446 count = print_queue_status(snum, &queue, &status);
2448 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
2449 lp_servicename(snum))))
2450 goto done;
2452 for (j=0; j<count; j++) {
2453 construct_notify_jobs_info(&queue[j], info,
2454 printer, snum,
2455 option_type,
2456 queue[j].job,
2457 mem_ctx);
2460 free_a_printer(&printer, 2);
2462 done:
2463 SAFE_FREE(queue);
2464 break;
2470 * Debugging information, don't delete.
2473 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2474 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2475 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2477 for (i=0; i<info->count; i++) {
2478 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2479 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2480 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2483 return WERR_OK;
2486 /********************************************************************
2487 * spoolss_rfnpcnex
2488 ********************************************************************/
2490 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2492 POLICY_HND *handle = &q_u->handle;
2493 /* uint32 change = q_u->change; - notused. */
2494 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2495 SPOOL_NOTIFY_INFO *info = &r_u->info;
2497 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2498 WERROR result = WERR_BADFID;
2500 /* we always have a NOTIFY_INFO struct */
2501 r_u->info_ptr=0x1;
2503 if (!Printer) {
2504 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2505 OUR_HANDLE(handle)));
2506 goto done;
2509 DEBUG(4,("Printer type %x\n",Printer->printer_type));
2511 /* jfm: the change value isn't used right now.
2512 * we will honour it when
2513 * a) we'll be able to send notification to the client
2514 * b) we'll have a way to communicate between the spoolss process.
2516 * same thing for option->flags
2517 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2518 * I don't have a global notification system, I'm sending back all the
2519 * informations even when _NOTHING_ has changed.
2522 /* just ignore the SPOOL_NOTIFY_OPTION */
2524 switch (Printer->printer_type) {
2525 case PRINTER_HANDLE_IS_PRINTSERVER:
2526 result = printserver_notify_info(p, handle, info, p->mem_ctx);
2527 break;
2529 case PRINTER_HANDLE_IS_PRINTER:
2530 result = printer_notify_info(p, handle, info, p->mem_ctx);
2531 break;
2534 done:
2535 return result;
2538 /********************************************************************
2539 * construct_printer_info_0
2540 * fill a printer_info_0 struct
2541 ********************************************************************/
2542 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2544 pstring chaine;
2545 int count;
2546 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2547 counter_printer_0 *session_counter;
2548 uint32 global_counter;
2549 struct tm *t;
2550 time_t setuptime;
2551 print_status_struct status;
2553 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2554 return False;
2556 count = print_queue_length(snum, &status);
2558 /* check if we already have a counter for this printer */
2559 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2561 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2562 if (session_counter->snum == snum)
2563 break;
2566 /* it's the first time, add it to the list */
2567 if (session_counter==NULL) {
2568 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2569 free_a_printer(&ntprinter, 2);
2570 return False;
2572 ZERO_STRUCTP(session_counter);
2573 session_counter->snum=snum;
2574 session_counter->counter=0;
2575 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2578 /* increment it */
2579 session_counter->counter++;
2581 /* JFM:
2582 * the global_counter should be stored in a TDB as it's common to all the clients
2583 * and should be zeroed on samba startup
2585 global_counter=session_counter->counter;
2587 pstrcpy(chaine,ntprinter->info_2->printername);
2589 init_unistr(&printer->printername, chaine);
2591 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
2592 init_unistr(&printer->servername, chaine);
2594 printer->cjobs = count;
2595 printer->total_jobs = 0;
2596 printer->total_bytes = 0;
2598 setuptime = (time_t)ntprinter->info_2->setuptime;
2599 t=gmtime(&setuptime);
2601 printer->year = t->tm_year+1900;
2602 printer->month = t->tm_mon+1;
2603 printer->dayofweek = t->tm_wday;
2604 printer->day = t->tm_mday;
2605 printer->hour = t->tm_hour;
2606 printer->minute = t->tm_min;
2607 printer->second = t->tm_sec;
2608 printer->milliseconds = 0;
2610 printer->global_counter = global_counter;
2611 printer->total_pages = 0;
2612 printer->major_version = 0x0004; /* NT 4 */
2613 printer->build_version = 0x0565; /* build 1381 */
2614 printer->unknown7 = 0x1;
2615 printer->unknown8 = 0x0;
2616 printer->unknown9 = 0x0;
2617 printer->session_counter = session_counter->counter;
2618 printer->unknown11 = 0x0;
2619 printer->printer_errors = 0x0; /* number of print failure */
2620 printer->unknown13 = 0x0;
2621 printer->unknown14 = 0x1;
2622 printer->unknown15 = 0x024a; /* 586 Pentium ? */
2623 printer->unknown16 = 0x0;
2624 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2625 printer->unknown18 = 0x0;
2626 printer->status = nt_printq_status(status.status);
2627 printer->unknown20 = 0x0;
2628 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2629 printer->unknown22 = 0x0;
2630 printer->unknown23 = 0x6; /* 6 ???*/
2631 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
2632 printer->unknown25 = 0;
2633 printer->unknown26 = 0;
2634 printer->unknown27 = 0;
2635 printer->unknown28 = 0;
2636 printer->unknown29 = 0;
2638 free_a_printer(&ntprinter,2);
2639 return (True);
2642 /********************************************************************
2643 * construct_printer_info_1
2644 * fill a printer_info_1 struct
2645 ********************************************************************/
2646 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2648 pstring chaine;
2649 pstring chaine2;
2650 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2652 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2653 return False;
2655 printer->flags=flags;
2657 if (*ntprinter->info_2->comment == '\0') {
2658 init_unistr(&printer->comment, lp_comment(snum));
2659 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
2660 ntprinter->info_2->drivername, lp_comment(snum));
2662 else {
2663 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2664 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
2665 ntprinter->info_2->drivername, ntprinter->info_2->comment);
2668 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2670 init_unistr(&printer->description, chaine);
2671 init_unistr(&printer->name, chaine2);
2673 free_a_printer(&ntprinter,2);
2675 return True;
2678 /****************************************************************************
2679 Free a DEVMODE struct.
2680 ****************************************************************************/
2682 static void free_dev_mode(DEVICEMODE *dev)
2684 if (dev == NULL)
2685 return;
2687 SAFE_FREE(dev->private);
2688 SAFE_FREE(dev);
2691 /****************************************************************************
2692 Create a DEVMODE struct. Returns malloced memory.
2693 ****************************************************************************/
2695 static DEVICEMODE *construct_dev_mode(int snum)
2697 char adevice[32];
2698 char aform[32];
2699 NT_PRINTER_INFO_LEVEL *printer = NULL;
2700 NT_DEVICEMODE *ntdevmode = NULL;
2701 DEVICEMODE *devmode = NULL;
2703 DEBUG(7,("construct_dev_mode\n"));
2705 DEBUGADD(8,("getting printer characteristics\n"));
2707 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2708 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2709 return NULL;
2712 ZERO_STRUCTP(devmode);
2714 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2715 goto fail;
2717 if (printer->info_2->devmode)
2718 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2720 if (ntdevmode == NULL)
2721 goto fail;
2723 DEBUGADD(8,("loading DEVICEMODE\n"));
2725 slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2726 init_unistr(&devmode->devicename, adevice);
2728 slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2729 init_unistr(&devmode->formname, aform);
2731 devmode->specversion = ntdevmode->specversion;
2732 devmode->driverversion = ntdevmode->driverversion;
2733 devmode->size = ntdevmode->size;
2734 devmode->driverextra = ntdevmode->driverextra;
2735 devmode->fields = ntdevmode->fields;
2737 devmode->orientation = ntdevmode->orientation;
2738 devmode->papersize = ntdevmode->papersize;
2739 devmode->paperlength = ntdevmode->paperlength;
2740 devmode->paperwidth = ntdevmode->paperwidth;
2741 devmode->scale = ntdevmode->scale;
2742 devmode->copies = ntdevmode->copies;
2743 devmode->defaultsource = ntdevmode->defaultsource;
2744 devmode->printquality = ntdevmode->printquality;
2745 devmode->color = ntdevmode->color;
2746 devmode->duplex = ntdevmode->duplex;
2747 devmode->yresolution = ntdevmode->yresolution;
2748 devmode->ttoption = ntdevmode->ttoption;
2749 devmode->collate = ntdevmode->collate;
2750 devmode->icmmethod = ntdevmode->icmmethod;
2751 devmode->icmintent = ntdevmode->icmintent;
2752 devmode->mediatype = ntdevmode->mediatype;
2753 devmode->dithertype = ntdevmode->dithertype;
2755 if (ntdevmode->private != NULL) {
2756 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2757 goto fail;
2760 free_nt_devicemode(&ntdevmode);
2761 free_a_printer(&printer,2);
2763 return devmode;
2765 fail:
2767 if (ntdevmode)
2768 free_nt_devicemode(&ntdevmode);
2769 if (printer)
2770 free_a_printer(&printer,2);
2771 free_dev_mode(devmode);
2773 return NULL;
2776 /********************************************************************
2777 * construct_printer_info_2
2778 * fill a printer_info_2 struct
2779 ********************************************************************/
2781 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2783 int count;
2784 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2786 print_status_struct status;
2788 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2789 return False;
2791 count = print_queue_length(snum, &status);
2793 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2794 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2795 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
2796 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
2797 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
2799 if (*ntprinter->info_2->comment == '\0')
2800 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
2801 else
2802 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2804 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
2805 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
2806 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2807 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
2808 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
2810 printer->attributes = ntprinter->info_2->attributes;
2812 printer->priority = ntprinter->info_2->priority; /* priority */
2813 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
2814 printer->starttime = ntprinter->info_2->starttime; /* starttime */
2815 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
2816 printer->status = nt_printq_status(status.status); /* status */
2817 printer->cjobs = count; /* jobs */
2818 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
2820 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2821 DEBUG(8, ("Returning NULL Devicemode!\n"));
2824 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2825 /* steal the printer info sec_desc structure. [badly done]. */
2826 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2827 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2828 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2829 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2831 else {
2832 printer->secdesc = NULL;
2835 free_a_printer(&ntprinter, 2);
2836 return True;
2839 /********************************************************************
2840 * construct_printer_info_3
2841 * fill a printer_info_3 struct
2842 ********************************************************************/
2843 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2845 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2846 PRINTER_INFO_3 *printer = NULL;
2848 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2849 return False;
2851 *pp_printer = NULL;
2852 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2853 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2854 return False;
2857 ZERO_STRUCTP(printer);
2859 printer->flags = 4; /* These are the components of the SD we are returning. */
2860 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2861 /* steal the printer info sec_desc structure. [badly done]. */
2862 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2864 #if 0
2866 * Set the flags for the components we are returning.
2869 if (printer->secdesc->owner_sid)
2870 printer->flags |= OWNER_SECURITY_INFORMATION;
2872 if (printer->secdesc->grp_sid)
2873 printer->flags |= GROUP_SECURITY_INFORMATION;
2875 if (printer->secdesc->dacl)
2876 printer->flags |= DACL_SECURITY_INFORMATION;
2878 if (printer->secdesc->sacl)
2879 printer->flags |= SACL_SECURITY_INFORMATION;
2880 #endif
2882 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2883 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2884 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2887 free_a_printer(&ntprinter, 2);
2889 *pp_printer = printer;
2890 return True;
2893 /********************************************************************
2894 * construct_printer_info_4
2895 * fill a printer_info_4 struct
2896 ********************************************************************/
2898 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
2900 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2902 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2903 return False;
2905 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2906 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2907 printer->attributes = ntprinter->info_2->attributes;
2909 free_a_printer(&ntprinter, 2);
2910 return True;
2913 /********************************************************************
2914 * construct_printer_info_5
2915 * fill a printer_info_5 struct
2916 ********************************************************************/
2918 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
2920 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2922 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
2923 return False;
2925 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
2926 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
2927 printer->attributes = ntprinter->info_2->attributes;
2928 printer->device_not_selected_timeout = 0x3a98;
2929 printer->transmission_retry_timeout = 0xafc8;
2931 free_a_printer(&ntprinter, 2);
2932 return True;
2936 /********************************************************************
2937 Spoolss_enumprinters.
2938 ********************************************************************/
2939 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2941 int snum;
2942 int i;
2943 int n_services=lp_numservices();
2944 PRINTER_INFO_1 *tp, *printers=NULL;
2945 PRINTER_INFO_1 current_prt;
2947 DEBUG(4,("enum_all_printers_info_1\n"));
2949 for (snum=0; snum<n_services; snum++) {
2950 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2951 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2953 if (construct_printer_info_1(flags, &current_prt, snum)) {
2954 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2955 DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2956 SAFE_FREE(printers);
2957 *returned=0;
2958 return WERR_NOMEM;
2960 else printers = tp;
2961 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2962 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
2963 (*returned)++;
2968 /* check the required size. */
2969 for (i=0; i<*returned; i++)
2970 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2972 if (!alloc_buffer_size(buffer, *needed))
2973 return WERR_INSUFFICIENT_BUFFER;
2975 /* fill the buffer with the structures */
2976 for (i=0; i<*returned; i++)
2977 smb_io_printer_info_1("", buffer, &printers[i], 0);
2979 /* clear memory */
2980 SAFE_FREE(printers);
2982 if (*needed > offered) {
2983 *returned=0;
2984 return WERR_INSUFFICIENT_BUFFER;
2986 else
2987 return WERR_OK;
2990 /********************************************************************
2991 enum_all_printers_info_1_local.
2992 *********************************************************************/
2993 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2995 DEBUG(4,("enum_all_printers_info_1_local\n"));
2997 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3000 /********************************************************************
3001 enum_all_printers_info_1_name.
3002 *********************************************************************/
3003 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3005 char *s = name;
3007 DEBUG(4,("enum_all_printers_info_1_name\n"));
3009 if ((name[0] == '\\') && (name[1] == '\\'))
3010 s = name + 2;
3012 if (is_myname_or_ipaddr(s)) {
3013 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
3015 else
3016 return WERR_INVALID_NAME;
3019 /********************************************************************
3020 enum_all_printers_info_1_remote.
3021 *********************************************************************/
3022 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3024 PRINTER_INFO_1 *printer;
3025 fstring printername;
3026 fstring desc;
3027 fstring comment;
3028 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3030 /* JFM: currently it's more a place holder than anything else.
3031 * In the spooler world there is a notion of server registration.
3032 * the print servers are registring (sp ?) on the PDC (in the same domain)
3034 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3037 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3038 return WERR_NOMEM;
3040 *returned=1;
3042 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3043 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
3044 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
3046 init_unistr(&printer->description, desc);
3047 init_unistr(&printer->name, printername);
3048 init_unistr(&printer->comment, comment);
3049 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
3051 /* check the required size. */
3052 *needed += spoolss_size_printer_info_1(printer);
3054 if (!alloc_buffer_size(buffer, *needed)) {
3055 SAFE_FREE(printer);
3056 return WERR_INSUFFICIENT_BUFFER;
3059 /* fill the buffer with the structures */
3060 smb_io_printer_info_1("", buffer, printer, 0);
3062 /* clear memory */
3063 SAFE_FREE(printer);
3065 if (*needed > offered) {
3066 *returned=0;
3067 return WERR_INSUFFICIENT_BUFFER;
3069 else
3070 return WERR_OK;
3073 /********************************************************************
3074 enum_all_printers_info_1_network.
3075 *********************************************************************/
3077 static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3079 DEBUG(4,("enum_all_printers_info_1_network\n"));
3081 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
3084 /********************************************************************
3085 * api_spoolss_enumprinters
3087 * called from api_spoolss_enumprinters (see this to understand)
3088 ********************************************************************/
3090 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3092 int snum;
3093 int i;
3094 int n_services=lp_numservices();
3095 PRINTER_INFO_2 *tp, *printers=NULL;
3096 PRINTER_INFO_2 current_prt;
3098 for (snum=0; snum<n_services; snum++) {
3099 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
3100 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
3102 if (construct_printer_info_2(&current_prt, snum)) {
3103 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
3104 DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3105 SAFE_FREE(printers);
3106 *returned = 0;
3107 return WERR_NOMEM;
3109 else printers = tp;
3110 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
3111 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
3112 (*returned)++;
3117 /* check the required size. */
3118 for (i=0; i<*returned; i++)
3119 (*needed) += spoolss_size_printer_info_2(&printers[i]);
3121 if (!alloc_buffer_size(buffer, *needed)) {
3122 for (i=0; i<*returned; i++) {
3123 free_devmode(printers[i].devmode);
3125 SAFE_FREE(printers);
3126 return WERR_INSUFFICIENT_BUFFER;
3129 /* fill the buffer with the structures */
3130 for (i=0; i<*returned; i++)
3131 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
3133 /* clear memory */
3134 for (i=0; i<*returned; i++) {
3135 free_devmode(printers[i].devmode);
3137 SAFE_FREE(printers);
3139 if (*needed > offered) {
3140 *returned=0;
3141 return WERR_INSUFFICIENT_BUFFER;
3143 else
3144 return WERR_OK;
3147 /********************************************************************
3148 * handle enumeration of printers at level 1
3149 ********************************************************************/
3150 static WERROR enumprinters_level1( uint32 flags, fstring name,
3151 NEW_BUFFER *buffer, uint32 offered,
3152 uint32 *needed, uint32 *returned)
3154 /* Not all the flags are equals */
3156 if (flags & PRINTER_ENUM_LOCAL)
3157 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3159 if (flags & PRINTER_ENUM_NAME)
3160 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3162 if (flags & PRINTER_ENUM_REMOTE)
3163 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3165 if (flags & PRINTER_ENUM_NETWORK)
3166 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3168 return WERR_OK; /* NT4sp5 does that */
3171 /********************************************************************
3172 * handle enumeration of printers at level 2
3173 ********************************************************************/
3174 static WERROR enumprinters_level2( uint32 flags, fstring servername,
3175 NEW_BUFFER *buffer, uint32 offered,
3176 uint32 *needed, uint32 *returned)
3178 char *s = servername;
3180 if (flags & PRINTER_ENUM_LOCAL) {
3181 return enum_all_printers_info_2(buffer, offered, needed, returned);
3184 if (flags & PRINTER_ENUM_NAME) {
3185 if ((servername[0] == '\\') && (servername[1] == '\\'))
3186 s = servername + 2;
3187 if (is_myname_or_ipaddr(s))
3188 return enum_all_printers_info_2(buffer, offered, needed, returned);
3189 else
3190 return WERR_INVALID_NAME;
3193 if (flags & PRINTER_ENUM_REMOTE)
3194 return WERR_UNKNOWN_LEVEL;
3196 return WERR_OK;
3199 /********************************************************************
3200 * handle enumeration of printers at level 5
3201 ********************************************************************/
3202 static WERROR enumprinters_level5( uint32 flags, fstring servername,
3203 NEW_BUFFER *buffer, uint32 offered,
3204 uint32 *needed, uint32 *returned)
3206 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3207 return WERR_OK;
3210 /********************************************************************
3211 * api_spoolss_enumprinters
3213 * called from api_spoolss_enumprinters (see this to understand)
3214 ********************************************************************/
3216 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3218 uint32 flags = q_u->flags;
3219 UNISTR2 *servername = &q_u->servername;
3220 uint32 level = q_u->level;
3221 NEW_BUFFER *buffer = NULL;
3222 uint32 offered = q_u->offered;
3223 uint32 *needed = &r_u->needed;
3224 uint32 *returned = &r_u->returned;
3226 fstring name;
3228 /* that's an [in out] buffer */
3229 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3230 buffer = r_u->buffer;
3232 DEBUG(4,("_spoolss_enumprinters\n"));
3234 *needed=0;
3235 *returned=0;
3238 * Level 1:
3239 * flags==PRINTER_ENUM_NAME
3240 * if name=="" then enumerates all printers
3241 * if name!="" then enumerate the printer
3242 * flags==PRINTER_ENUM_REMOTE
3243 * name is NULL, enumerate printers
3244 * Level 2: name!="" enumerates printers, name can't be NULL
3245 * Level 3: doesn't exist
3246 * Level 4: does a local registry lookup
3247 * Level 5: same as Level 2
3250 unistr2_to_ascii(name, servername, sizeof(name)-1);
3251 strupper(name);
3253 switch (level) {
3254 case 1:
3255 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3256 case 2:
3257 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3258 case 5:
3259 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3260 case 3:
3261 case 4:
3262 break;
3264 return WERR_UNKNOWN_LEVEL;
3267 /****************************************************************************
3268 ****************************************************************************/
3269 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3271 PRINTER_INFO_0 *printer=NULL;
3273 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3274 return WERR_NOMEM;
3276 construct_printer_info_0(printer, snum);
3278 /* check the required size. */
3279 *needed += spoolss_size_printer_info_0(printer);
3281 if (!alloc_buffer_size(buffer, *needed)) {
3282 SAFE_FREE(printer);
3283 return WERR_INSUFFICIENT_BUFFER;
3286 /* fill the buffer with the structures */
3287 smb_io_printer_info_0("", buffer, printer, 0);
3289 /* clear memory */
3290 SAFE_FREE(printer);
3292 if (*needed > offered) {
3293 return WERR_INSUFFICIENT_BUFFER;
3296 return WERR_OK;
3299 /****************************************************************************
3300 ****************************************************************************/
3301 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3303 PRINTER_INFO_1 *printer=NULL;
3305 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3306 return WERR_NOMEM;
3308 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3310 /* check the required size. */
3311 *needed += spoolss_size_printer_info_1(printer);
3313 if (!alloc_buffer_size(buffer, *needed)) {
3314 SAFE_FREE(printer);
3315 return WERR_INSUFFICIENT_BUFFER;
3318 /* fill the buffer with the structures */
3319 smb_io_printer_info_1("", buffer, printer, 0);
3321 /* clear memory */
3322 SAFE_FREE(printer);
3324 if (*needed > offered) {
3325 return WERR_INSUFFICIENT_BUFFER;
3328 return WERR_OK;
3331 /****************************************************************************
3332 ****************************************************************************/
3333 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3335 PRINTER_INFO_2 *printer=NULL;
3337 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3338 return WERR_NOMEM;
3340 construct_printer_info_2(printer, snum);
3342 /* check the required size. */
3343 *needed += spoolss_size_printer_info_2(printer);
3345 if (!alloc_buffer_size(buffer, *needed)) {
3346 free_printer_info_2(printer);
3347 return WERR_INSUFFICIENT_BUFFER;
3350 /* fill the buffer with the structures */
3351 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3352 free_printer_info_2(printer);
3353 return WERR_NOMEM;
3356 /* clear memory */
3357 free_printer_info_2(printer);
3359 if (*needed > offered) {
3360 return WERR_INSUFFICIENT_BUFFER;
3363 return WERR_OK;
3366 /****************************************************************************
3367 ****************************************************************************/
3368 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3370 PRINTER_INFO_3 *printer=NULL;
3372 if (!construct_printer_info_3(&printer, snum))
3373 return WERR_NOMEM;
3375 /* check the required size. */
3376 *needed += spoolss_size_printer_info_3(printer);
3378 if (!alloc_buffer_size(buffer, *needed)) {
3379 free_printer_info_3(printer);
3380 return WERR_INSUFFICIENT_BUFFER;
3383 /* fill the buffer with the structures */
3384 smb_io_printer_info_3("", buffer, printer, 0);
3386 /* clear memory */
3387 free_printer_info_3(printer);
3389 if (*needed > offered) {
3390 return WERR_INSUFFICIENT_BUFFER;
3393 return WERR_OK;
3396 /****************************************************************************
3397 ****************************************************************************/
3398 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3400 PRINTER_INFO_4 *printer=NULL;
3402 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
3403 return WERR_NOMEM;
3405 if (!construct_printer_info_4(printer, snum))
3406 return WERR_NOMEM;
3408 /* check the required size. */
3409 *needed += spoolss_size_printer_info_4(printer);
3411 if (!alloc_buffer_size(buffer, *needed)) {
3412 free_printer_info_4(printer);
3413 return WERR_INSUFFICIENT_BUFFER;
3416 /* fill the buffer with the structures */
3417 smb_io_printer_info_4("", buffer, printer, 0);
3419 /* clear memory */
3420 free_printer_info_4(printer);
3422 if (*needed > offered) {
3423 return WERR_INSUFFICIENT_BUFFER;
3426 return WERR_OK;
3429 /****************************************************************************
3430 ****************************************************************************/
3431 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3433 PRINTER_INFO_5 *printer=NULL;
3435 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
3436 return WERR_NOMEM;
3438 if (!construct_printer_info_5(printer, snum))
3439 return WERR_NOMEM;
3441 /* check the required size. */
3442 *needed += spoolss_size_printer_info_5(printer);
3444 if (!alloc_buffer_size(buffer, *needed)) {
3445 free_printer_info_5(printer);
3446 return WERR_INSUFFICIENT_BUFFER;
3449 /* fill the buffer with the structures */
3450 smb_io_printer_info_5("", buffer, printer, 0);
3452 /* clear memory */
3453 free_printer_info_5(printer);
3455 if (*needed > offered) {
3456 return WERR_INSUFFICIENT_BUFFER;
3459 return WERR_OK;
3462 /****************************************************************************
3463 ****************************************************************************/
3465 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3467 POLICY_HND *handle = &q_u->handle;
3468 uint32 level = q_u->level;
3469 NEW_BUFFER *buffer = NULL;
3470 uint32 offered = q_u->offered;
3471 uint32 *needed = &r_u->needed;
3473 int snum;
3475 /* that's an [in out] buffer */
3476 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3477 buffer = r_u->buffer;
3479 *needed=0;
3481 if (!get_printer_snum(p, handle, &snum))
3482 return WERR_BADFID;
3484 switch (level) {
3485 case 0:
3486 return getprinter_level_0(snum, buffer, offered, needed);
3487 case 1:
3488 return getprinter_level_1(snum, buffer, offered, needed);
3489 case 2:
3490 return getprinter_level_2(snum, buffer, offered, needed);
3491 case 3:
3492 return getprinter_level_3(snum, buffer, offered, needed);
3493 case 4:
3494 return getprinter_level_4(snum, buffer, offered, needed);
3495 case 5:
3496 return getprinter_level_5(snum, buffer, offered, needed);
3498 return WERR_UNKNOWN_LEVEL;
3501 /********************************************************************
3502 * fill a DRIVER_INFO_1 struct
3503 ********************************************************************/
3504 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3506 init_unistr( &info->name, driver.info_3->name);
3509 /********************************************************************
3510 * construct_printer_driver_info_1
3511 ********************************************************************/
3512 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3514 NT_PRINTER_INFO_LEVEL *printer = NULL;
3515 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3517 ZERO_STRUCT(driver);
3519 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3520 return WERR_INVALID_PRINTER_NAME;
3522 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3523 return WERR_UNKNOWN_PRINTER_DRIVER;
3525 fill_printer_driver_info_1(info, driver, servername, architecture);
3527 free_a_printer(&printer,2);
3529 return WERR_OK;
3532 /********************************************************************
3533 * construct_printer_driver_info_2
3534 * fill a printer_info_2 struct
3535 ********************************************************************/
3536 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3538 pstring temp;
3540 info->version=driver.info_3->cversion;
3542 init_unistr( &info->name, driver.info_3->name );
3543 init_unistr( &info->architecture, driver.info_3->environment );
3546 if (strlen(driver.info_3->driverpath)) {
3547 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3548 init_unistr( &info->driverpath, temp );
3549 } else
3550 init_unistr( &info->driverpath, "" );
3552 if (strlen(driver.info_3->datafile)) {
3553 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3554 init_unistr( &info->datafile, temp );
3555 } else
3556 init_unistr( &info->datafile, "" );
3558 if (strlen(driver.info_3->configfile)) {
3559 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3560 init_unistr( &info->configfile, temp );
3561 } else
3562 init_unistr( &info->configfile, "" );
3565 /********************************************************************
3566 * construct_printer_driver_info_2
3567 * fill a printer_info_2 struct
3568 ********************************************************************/
3569 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3571 NT_PRINTER_INFO_LEVEL *printer = NULL;
3572 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3574 ZERO_STRUCT(printer);
3575 ZERO_STRUCT(driver);
3577 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3578 return WERR_INVALID_PRINTER_NAME;
3580 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
3581 return WERR_UNKNOWN_PRINTER_DRIVER;
3583 fill_printer_driver_info_2(info, driver, servername);
3585 free_a_printer(&printer,2);
3587 return WERR_OK;
3590 /********************************************************************
3591 * copy a strings array and convert to UNICODE
3593 * convert an array of ascii string to a UNICODE string
3594 ********************************************************************/
3595 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3597 int i=0;
3598 int j=0;
3599 char *v;
3600 pstring line;
3601 uint16 *tuary;
3603 DEBUG(6,("init_unistr_array\n"));
3604 *uni_array=NULL;
3606 while (1) {
3607 if (char_array == NULL)
3608 v = "";
3609 else {
3610 v = char_array[i];
3611 if (!v) v = ""; /* hack to handle null lists */
3613 if (strlen(v) == 0) break;
3614 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3615 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3616 if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3617 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3618 return;
3620 else *uni_array = tuary;
3621 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
3622 i++;
3625 if (*uni_array) {
3626 (*uni_array)[j]=0x0000;
3629 DEBUGADD(6,("last one:done\n"));
3632 /********************************************************************
3633 * construct_printer_info_3
3634 * fill a printer_info_3 struct
3635 ********************************************************************/
3636 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3638 pstring temp;
3640 ZERO_STRUCTP(info);
3642 info->version=driver.info_3->cversion;
3644 init_unistr( &info->name, driver.info_3->name );
3645 init_unistr( &info->architecture, driver.info_3->environment );
3647 if (strlen(driver.info_3->driverpath)) {
3648 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3649 init_unistr( &info->driverpath, temp );
3650 } else
3651 init_unistr( &info->driverpath, "" );
3653 if (strlen(driver.info_3->datafile)) {
3654 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3655 init_unistr( &info->datafile, temp );
3656 } else
3657 init_unistr( &info->datafile, "" );
3659 if (strlen(driver.info_3->configfile)) {
3660 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3661 init_unistr( &info->configfile, temp );
3662 } else
3663 init_unistr( &info->configfile, "" );
3665 if (strlen(driver.info_3->helpfile)) {
3666 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3667 init_unistr( &info->helpfile, temp );
3668 } else
3669 init_unistr( &info->helpfile, "" );
3671 init_unistr( &info->monitorname, driver.info_3->monitorname );
3672 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3674 info->dependentfiles=NULL;
3675 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3678 /********************************************************************
3679 * construct_printer_info_3
3680 * fill a printer_info_3 struct
3681 ********************************************************************/
3682 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3684 NT_PRINTER_INFO_LEVEL *printer = NULL;
3685 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3686 WERROR status;
3687 ZERO_STRUCT(driver);
3689 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3690 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3691 if (!W_ERROR_IS_OK(status))
3692 return WERR_INVALID_PRINTER_NAME;
3694 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3695 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status)));
3696 if (!W_ERROR_IS_OK(status)) {
3697 free_a_printer(&printer,2);
3698 return WERR_UNKNOWN_PRINTER_DRIVER;
3701 fill_printer_driver_info_3(info, driver, servername);
3703 free_a_printer(&printer,2);
3705 return WERR_OK;
3708 /********************************************************************
3709 * construct_printer_info_6
3710 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3711 ********************************************************************/
3713 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3715 pstring temp;
3716 fstring nullstr;
3718 ZERO_STRUCTP(info);
3719 memset(&nullstr, '\0', sizeof(fstring));
3721 info->version=driver.info_3->cversion;
3723 init_unistr( &info->name, driver.info_3->name );
3724 init_unistr( &info->architecture, driver.info_3->environment );
3726 if (strlen(driver.info_3->driverpath)) {
3727 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3728 init_unistr( &info->driverpath, temp );
3729 } else
3730 init_unistr( &info->driverpath, "" );
3732 if (strlen(driver.info_3->datafile)) {
3733 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3734 init_unistr( &info->datafile, temp );
3735 } else
3736 init_unistr( &info->datafile, "" );
3738 if (strlen(driver.info_3->configfile)) {
3739 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3740 init_unistr( &info->configfile, temp );
3741 } else
3742 init_unistr( &info->configfile, "" );
3744 if (strlen(driver.info_3->helpfile)) {
3745 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3746 init_unistr( &info->helpfile, temp );
3747 } else
3748 init_unistr( &info->helpfile, "" );
3750 init_unistr( &info->monitorname, driver.info_3->monitorname );
3751 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3753 info->dependentfiles=NULL;
3754 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3756 info->previousdrivernames=NULL;
3757 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3759 info->driver_date.low=0;
3760 info->driver_date.high=0;
3762 info->padding=0;
3763 info->driver_version_low=0;
3764 info->driver_version_high=0;
3766 init_unistr( &info->mfgname, "");
3767 init_unistr( &info->oem_url, "");
3768 init_unistr( &info->hardware_id, "");
3769 init_unistr( &info->provider, "");
3772 /********************************************************************
3773 * construct_printer_info_6
3774 * fill a printer_info_6 struct
3775 ********************************************************************/
3776 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3778 NT_PRINTER_INFO_LEVEL *printer = NULL;
3779 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3780 WERROR status;
3781 ZERO_STRUCT(driver);
3783 status=get_a_printer(&printer, 2, lp_servicename(snum) );
3784 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3785 if (!W_ERROR_IS_OK(status))
3786 return WERR_INVALID_PRINTER_NAME;
3788 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3789 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3790 if (!W_ERROR_IS_OK(status)) {
3792 * Is this a W2k client ?
3795 if (version < 3) {
3796 free_a_printer(&printer,2);
3797 return WERR_UNKNOWN_PRINTER_DRIVER;
3800 /* Yes - try again with a WinNT driver. */
3801 version = 2;
3802 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
3803 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status)));
3804 if (!W_ERROR_IS_OK(status)) {
3805 free_a_printer(&printer,2);
3806 return WERR_UNKNOWN_PRINTER_DRIVER;
3810 fill_printer_driver_info_6(info, driver, servername);
3812 free_a_printer(&printer,2);
3814 return WERR_OK;
3817 /****************************************************************************
3818 ****************************************************************************/
3820 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3822 SAFE_FREE(info->dependentfiles);
3825 /****************************************************************************
3826 ****************************************************************************/
3828 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3830 SAFE_FREE(info->dependentfiles);
3834 /****************************************************************************
3835 ****************************************************************************/
3836 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3838 DRIVER_INFO_1 *info=NULL;
3839 WERROR status;
3841 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3842 return WERR_NOMEM;
3844 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3845 if (!W_ERROR_IS_OK(status)) {
3846 SAFE_FREE(info);
3847 return status;
3850 /* check the required size. */
3851 *needed += spoolss_size_printer_driver_info_1(info);
3853 if (!alloc_buffer_size(buffer, *needed)) {
3854 SAFE_FREE(info);
3855 return WERR_INSUFFICIENT_BUFFER;
3858 /* fill the buffer with the structures */
3859 smb_io_printer_driver_info_1("", buffer, info, 0);
3861 /* clear memory */
3862 SAFE_FREE(info);
3864 if (*needed > offered)
3865 return WERR_INSUFFICIENT_BUFFER;
3867 return WERR_OK;
3870 /****************************************************************************
3871 ****************************************************************************/
3872 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3874 DRIVER_INFO_2 *info=NULL;
3875 WERROR status;
3877 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3878 return WERR_NOMEM;
3880 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3881 if (!W_ERROR_IS_OK(status)) {
3882 SAFE_FREE(info);
3883 return status;
3886 /* check the required size. */
3887 *needed += spoolss_size_printer_driver_info_2(info);
3889 if (!alloc_buffer_size(buffer, *needed)) {
3890 SAFE_FREE(info);
3891 return WERR_INSUFFICIENT_BUFFER;
3894 /* fill the buffer with the structures */
3895 smb_io_printer_driver_info_2("", buffer, info, 0);
3897 /* clear memory */
3898 SAFE_FREE(info);
3900 if (*needed > offered)
3901 return WERR_INSUFFICIENT_BUFFER;
3903 return WERR_OK;
3906 /****************************************************************************
3907 ****************************************************************************/
3908 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3910 DRIVER_INFO_3 info;
3911 WERROR status;
3913 ZERO_STRUCT(info);
3915 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3916 if (!W_ERROR_IS_OK(status)) {
3917 return status;
3920 /* check the required size. */
3921 *needed += spoolss_size_printer_driver_info_3(&info);
3923 if (!alloc_buffer_size(buffer, *needed)) {
3924 free_printer_driver_info_3(&info);
3925 return WERR_INSUFFICIENT_BUFFER;
3928 /* fill the buffer with the structures */
3929 smb_io_printer_driver_info_3("", buffer, &info, 0);
3931 free_printer_driver_info_3(&info);
3933 if (*needed > offered)
3934 return WERR_INSUFFICIENT_BUFFER;
3936 return WERR_OK;
3939 /****************************************************************************
3940 ****************************************************************************/
3941 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3943 DRIVER_INFO_6 info;
3944 WERROR status;
3946 ZERO_STRUCT(info);
3948 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3949 if (!W_ERROR_IS_OK(status)) {
3950 return status;
3953 /* check the required size. */
3954 *needed += spoolss_size_printer_driver_info_6(&info);
3956 if (!alloc_buffer_size(buffer, *needed)) {
3957 free_printer_driver_info_6(&info);
3958 return WERR_INSUFFICIENT_BUFFER;
3961 /* fill the buffer with the structures */
3962 smb_io_printer_driver_info_6("", buffer, &info, 0);
3964 free_printer_driver_info_6(&info);
3966 if (*needed > offered)
3967 return WERR_INSUFFICIENT_BUFFER;
3969 return WERR_OK;
3972 /****************************************************************************
3973 ****************************************************************************/
3975 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3977 POLICY_HND *handle = &q_u->handle;
3978 UNISTR2 *uni_arch = &q_u->architecture;
3979 uint32 level = q_u->level;
3980 uint32 clientmajorversion = q_u->clientmajorversion;
3981 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3982 NEW_BUFFER *buffer = NULL;
3983 uint32 offered = q_u->offered;
3984 uint32 *needed = &r_u->needed;
3985 uint32 *servermajorversion = &r_u->servermajorversion;
3986 uint32 *serverminorversion = &r_u->serverminorversion;
3988 fstring servername;
3989 fstring architecture;
3990 int snum;
3992 /* that's an [in out] buffer */
3993 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3994 buffer = r_u->buffer;
3996 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3998 *needed=0;
3999 *servermajorversion=0;
4000 *serverminorversion=0;
4002 pstrcpy(servername, get_called_name());
4003 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
4005 if (!get_printer_snum(p, handle, &snum))
4006 return WERR_BADFID;
4008 switch (level) {
4009 case 1:
4010 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4011 case 2:
4012 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4013 case 3:
4014 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4015 case 6:
4016 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
4019 return WERR_UNKNOWN_LEVEL;
4022 /****************************************************************************
4023 ****************************************************************************/
4025 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
4027 POLICY_HND *handle = &q_u->handle;
4029 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4031 if (!Printer) {
4032 DEBUG(3,("Error in startpageprinter printer handle\n"));
4033 return WERR_BADFID;
4036 Printer->page_started=True;
4037 return WERR_OK;
4040 /****************************************************************************
4041 ****************************************************************************/
4043 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
4045 POLICY_HND *handle = &q_u->handle;
4047 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4049 if (!Printer) {
4050 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
4051 return WERR_BADFID;
4054 Printer->page_started=False;
4056 return WERR_OK;
4059 /********************************************************************
4060 * api_spoolss_getprinter
4061 * called from the spoolss dispatcher
4063 ********************************************************************/
4065 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
4067 POLICY_HND *handle = &q_u->handle;
4068 /* uint32 level = q_u->doc_info_container.level; - notused. */
4069 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
4070 uint32 *jobid = &r_u->jobid;
4072 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
4073 int snum;
4074 pstring jobname;
4075 fstring datatype;
4076 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4077 struct current_user user;
4079 if (!Printer) {
4080 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4081 return WERR_BADFID;
4084 get_current_user(&user, p);
4087 * a nice thing with NT is it doesn't listen to what you tell it.
4088 * when asked to send _only_ RAW datas, it tries to send datas
4089 * in EMF format.
4091 * So I add checks like in NT Server ...
4093 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4094 * there's a bug in NT client-side code, so we'll fix it in the
4095 * server-side code. *nnnnnggggh!*
4098 if (info_1->p_datatype != 0) {
4099 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
4100 if (strcmp(datatype, "RAW") != 0) {
4101 (*jobid)=0;
4102 return WERR_INVALID_DATATYPE;
4106 /* get the share number of the printer */
4107 if (!get_printer_snum(p, handle, &snum)) {
4108 return WERR_BADFID;
4111 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
4113 Printer->jobid = print_job_start(&user, snum, jobname);
4115 /* An error occured in print_job_start() so return an appropriate
4116 NT error code. */
4118 if (Printer->jobid == -1) {
4119 return map_werror_from_unix(errno);
4122 Printer->document_started=True;
4123 (*jobid) = Printer->jobid;
4125 return WERR_OK;
4128 /********************************************************************
4129 * api_spoolss_getprinter
4130 * called from the spoolss dispatcher
4132 ********************************************************************/
4134 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
4136 POLICY_HND *handle = &q_u->handle;
4138 return _spoolss_enddocprinter_internal(p, handle);
4141 /****************************************************************************
4142 ****************************************************************************/
4144 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
4146 POLICY_HND *handle = &q_u->handle;
4147 uint32 buffer_size = q_u->buffer_size;
4148 uint8 *buffer = q_u->buffer;
4149 uint32 *buffer_written = &q_u->buffer_size2;
4151 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4153 if (!Printer) {
4154 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
4155 r_u->buffer_written = q_u->buffer_size2;
4156 return WERR_BADFID;
4159 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
4162 r_u->buffer_written = q_u->buffer_size2;
4164 return WERR_OK;
4167 /********************************************************************
4168 * api_spoolss_getprinter
4169 * called from the spoolss dispatcher
4171 ********************************************************************/
4172 static WERROR control_printer(POLICY_HND *handle, uint32 command,
4173 pipes_struct *p)
4175 struct current_user user;
4176 int snum;
4177 WERROR errcode = WERR_BADFUNC;
4178 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4180 get_current_user(&user, p);
4182 if (!Printer) {
4183 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4184 return WERR_BADFID;
4187 if (!get_printer_snum(p, handle, &snum))
4188 return WERR_BADFID;
4190 switch (command) {
4191 case PRINTER_CONTROL_PAUSE:
4192 if (print_queue_pause(&user, snum, &errcode)) {
4193 errcode = WERR_OK;
4195 break;
4196 case PRINTER_CONTROL_RESUME:
4197 case PRINTER_CONTROL_UNPAUSE:
4198 if (print_queue_resume(&user, snum, &errcode)) {
4199 errcode = WERR_OK;
4201 break;
4202 case PRINTER_CONTROL_PURGE:
4203 if (print_queue_purge(&user, snum, &errcode)) {
4204 errcode = WERR_OK;
4206 break;
4207 default:
4208 return WERR_UNKNOWN_LEVEL;
4211 return errcode;
4214 /********************************************************************
4215 * api_spoolss_abortprinter
4216 ********************************************************************/
4218 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4220 POLICY_HND *handle = &q_u->handle;
4222 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4225 /********************************************************************
4226 * called by spoolss_api_setprinter
4227 * when updating a printer description
4228 ********************************************************************/
4229 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
4230 const SPOOL_PRINTER_INFO_LEVEL *info,
4231 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4233 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4234 struct current_user user;
4235 WERROR result;
4236 int snum;
4238 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4240 if (!Printer || !get_printer_snum(p, handle, &snum)) {
4241 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4242 OUR_HANDLE(handle)));
4244 result = WERR_BADFID;
4245 goto done;
4248 /* NT seems to like setting the security descriptor even though
4249 nothing may have actually changed. This causes annoying
4250 dialog boxes when the user doesn't have permission to change
4251 the security descriptor. */
4253 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4255 if (DEBUGLEVEL >= 10) {
4256 SEC_ACL *the_acl;
4257 int i;
4259 the_acl = old_secdesc_ctr->sec->dacl;
4260 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4261 PRINTERNAME(snum), the_acl->num_aces));
4263 for (i = 0; i < the_acl->num_aces; i++) {
4264 fstring sid_str;
4266 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4268 DEBUG(10, ("%s 0x%08x\n", sid_str,
4269 the_acl->ace[i].info.mask));
4272 the_acl = secdesc_ctr->sec->dacl;
4274 if (the_acl) {
4275 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4276 PRINTERNAME(snum), the_acl->num_aces));
4278 for (i = 0; i < the_acl->num_aces; i++) {
4279 fstring sid_str;
4281 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4283 DEBUG(10, ("%s 0x%08x\n", sid_str,
4284 the_acl->ace[i].info.mask));
4286 } else {
4287 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4291 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4293 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4294 result = WERR_OK;
4295 goto done;
4298 /* Work out which user is performing the operation */
4300 get_current_user(&user, p);
4302 /* Check the user has permissions to change the security
4303 descriptor. By experimentation with two NT machines, the user
4304 requires Full Access to the printer to change security
4305 information. */
4307 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4308 result = WERR_ACCESS_DENIED;
4309 goto done;
4312 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4314 done:
4316 return result;
4319 /********************************************************************
4320 Do Samba sanity checks on a printer info struct.
4321 this has changed purpose: it now "canonicalises" printer
4322 info from a client rather than just checking it is correct
4323 ********************************************************************/
4325 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4327 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4328 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4330 /* we force some elements to "correct" values */
4331 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
4332 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4333 get_called_name(), lp_servicename(snum));
4334 fstrcpy(info->sharename, lp_servicename(snum));
4335 info->attributes = PRINTER_ATTRIBUTE_SHARED \
4336 | PRINTER_ATTRIBUTE_LOCAL \
4337 | PRINTER_ATTRIBUTE_RAW_ONLY \
4338 | PRINTER_ATTRIBUTE_QUEUED ;
4340 return True;
4343 /****************************************************************************
4344 ****************************************************************************/
4345 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4347 char *cmd = lp_addprinter_cmd();
4348 char **qlines;
4349 pstring command;
4350 pstring driverlocation;
4351 int numlines;
4352 int ret;
4353 int fd;
4355 /* build driver path... only 9X architecture is needed for legacy reasons */
4356 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4357 get_called_name());
4358 /* change \ to \\ for the shell */
4359 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4361 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4362 cmd, printer->info_2->printername, printer->info_2->sharename,
4363 printer->info_2->portname, printer->info_2->drivername,
4364 printer->info_2->location, driverlocation);
4366 DEBUG(10,("Running [%s]\n", command));
4367 ret = smbrun(command, &fd);
4368 DEBUGADD(10,("returned [%d]\n", ret));
4370 if ( ret != 0 ) {
4371 if (fd != -1)
4372 close(fd);
4373 return False;
4376 numlines = 0;
4377 /* Get lines and convert them back to dos-codepage */
4378 qlines = fd_lines_load(fd, &numlines);
4379 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4380 close(fd);
4382 if(numlines) {
4383 /* Set the portname to what the script says the portname should be. */
4384 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4385 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4387 /* Send SIGHUP to process group... is there a better way? */
4388 kill(0, SIGHUP);
4389 add_all_printers();
4392 file_lines_free(qlines);
4393 return True;
4396 /* Return true if two devicemodes are equal */
4398 #define DEVMODE_CHECK_INT(field) \
4399 if (d1->field != d2->field) { \
4400 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4401 d1->field, d2->field)); \
4402 return False; \
4405 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4407 if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
4409 if (!d1 ^ !d2) {
4410 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4411 return False; /* if either is exclusively NULL are not equal */
4414 if (!strequal(d1->devicename, d2->devicename)) {
4415 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4416 return False;
4419 if (!strequal(d1->formname, d2->formname)) {
4420 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4421 return False;
4424 DEVMODE_CHECK_INT(specversion);
4425 DEVMODE_CHECK_INT(driverversion);
4426 DEVMODE_CHECK_INT(driverextra);
4427 DEVMODE_CHECK_INT(orientation);
4428 DEVMODE_CHECK_INT(papersize);
4429 DEVMODE_CHECK_INT(paperlength);
4430 DEVMODE_CHECK_INT(paperwidth);
4431 DEVMODE_CHECK_INT(scale);
4432 DEVMODE_CHECK_INT(copies);
4433 DEVMODE_CHECK_INT(defaultsource);
4434 DEVMODE_CHECK_INT(printquality);
4435 DEVMODE_CHECK_INT(color);
4436 DEVMODE_CHECK_INT(duplex);
4437 DEVMODE_CHECK_INT(yresolution);
4438 DEVMODE_CHECK_INT(ttoption);
4439 DEVMODE_CHECK_INT(collate);
4440 DEVMODE_CHECK_INT(logpixels);
4442 DEVMODE_CHECK_INT(fields);
4443 DEVMODE_CHECK_INT(bitsperpel);
4444 DEVMODE_CHECK_INT(pelswidth);
4445 DEVMODE_CHECK_INT(pelsheight);
4446 DEVMODE_CHECK_INT(displayflags);
4447 DEVMODE_CHECK_INT(displayfrequency);
4448 DEVMODE_CHECK_INT(icmmethod);
4449 DEVMODE_CHECK_INT(icmintent);
4450 DEVMODE_CHECK_INT(mediatype);
4451 DEVMODE_CHECK_INT(dithertype);
4452 DEVMODE_CHECK_INT(reserved1);
4453 DEVMODE_CHECK_INT(reserved2);
4454 DEVMODE_CHECK_INT(panningwidth);
4455 DEVMODE_CHECK_INT(panningheight);
4457 /* compare the private data if it exists */
4458 if (!d1->driverextra && !d2->driverextra) goto equal;
4461 DEVMODE_CHECK_INT(driverextra);
4463 if (memcmp(d1->private, d2->private, d1->driverextra)) {
4464 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4465 return False;
4468 equal:
4469 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4470 return True;
4473 /* Return true if two NT_PRINTER_PARAM structures are equal */
4475 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4476 NT_PRINTER_PARAM *p2)
4478 if (!p1 && !p2) goto equal;
4480 if ((!p1 && p2) || (p1 && !p2)) {
4481 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4482 return False;
4485 /* Compare lists of printer parameters */
4487 while (p1) {
4488 BOOL found = False;
4489 NT_PRINTER_PARAM *q = p1;
4491 /* Find the parameter in the second structure */
4493 while(q) {
4495 if (strequal(p1->value, q->value)) {
4497 if (p1->type != q->type) {
4498 DEBUG(10, ("nt_printer_param_equal():"
4499 "types for %s differ (%d != %d)\n",
4500 p1->value, p1->type,
4501 q->type));
4502 break;
4505 if (p1->data_len != q->data_len) {
4506 DEBUG(10, ("nt_printer_param_equal():"
4507 "len for %s differs (%d != %d)\n",
4508 p1->value, p1->data_len,
4509 q->data_len));
4510 break;
4513 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4514 found = True;
4515 } else {
4516 DEBUG(10, ("nt_printer_param_equal():"
4517 "data for %s differs\n", p1->value));
4520 break;
4523 q = q->next;
4526 if (!found) {
4527 DEBUG(10, ("nt_printer_param_equal(): param %s "
4528 "does not exist\n", p1->value));
4529 return False;
4532 p1 = p1->next;
4535 equal:
4537 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4538 return True;
4541 /********************************************************************
4542 * Called by update_printer when trying to work out whether to
4543 * actually update printer info.
4544 ********************************************************************/
4546 #define PI_CHECK_INT(field) \
4547 if (pi1->field != pi2->field) { \
4548 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4549 pi1->field, pi2->field)); \
4550 return False; \
4553 #define PI_CHECK_STR(field) \
4554 if (!strequal(pi1->field, pi2->field)) { \
4555 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4556 pi1->field, pi2->field)); \
4557 return False; \
4560 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4561 NT_PRINTER_INFO_LEVEL *p2)
4563 NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4565 /* Trivial conditions */
4567 if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4568 goto equal;
4571 if ((!p1 && p2) || (p1 && !p2) ||
4572 (!p1->info_2 && p2->info_2) ||
4573 (p1->info_2 && !p2->info_2)) {
4574 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4575 "differ\n"));
4576 return False;
4579 /* Compare two nt_printer_info_level structures. Don't compare
4580 status or cjobs as they seem to have something to do with the
4581 printer queue. */
4583 pi1 = p1->info_2;
4584 pi2 = p2->info_2;
4586 /* Don't check the attributes as we stomp on the value in
4587 check_printer_ok() anyway. */
4589 #if 0
4590 PI_CHECK_INT(attributes);
4591 #endif
4593 PI_CHECK_INT(priority);
4594 PI_CHECK_INT(default_priority);
4595 PI_CHECK_INT(starttime);
4596 PI_CHECK_INT(untiltime);
4597 PI_CHECK_INT(averageppm);
4599 /* Yuck - don't check the printername or servername as the
4600 mod_a_printer() code plays games with them. You can't
4601 change the printername or the sharename through this interface
4602 in Samba. */
4604 PI_CHECK_STR(sharename);
4605 PI_CHECK_STR(portname);
4606 PI_CHECK_STR(drivername);
4607 PI_CHECK_STR(comment);
4608 PI_CHECK_STR(location);
4610 if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4611 return False;
4614 PI_CHECK_STR(sepfile);
4615 PI_CHECK_STR(printprocessor);
4616 PI_CHECK_STR(datatype);
4617 PI_CHECK_STR(parameters);
4619 if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4620 return False;
4623 if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4624 return False;
4627 PI_CHECK_INT(changeid);
4628 PI_CHECK_INT(c_setprinter);
4629 PI_CHECK_INT(setuptime);
4631 equal:
4632 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4633 return True;
4636 /********************************************************************
4637 * called by spoolss_api_setprinter
4638 * when updating a printer description
4639 ********************************************************************/
4641 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4642 const SPOOL_PRINTER_INFO_LEVEL *info,
4643 DEVICEMODE *devmode)
4645 int snum;
4646 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4647 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4648 WERROR result;
4650 DEBUG(8,("update_printer\n"));
4652 result = WERR_OK;
4654 if (level!=2) {
4655 DEBUG(0,("Send a mail to samba@samba.org\n"));
4656 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4657 result = WERR_UNKNOWN_LEVEL;
4658 goto done;
4661 if (!Printer) {
4662 result = WERR_BADFID;
4663 goto done;
4666 if (!get_printer_snum(p, handle, &snum)) {
4667 result = WERR_BADFID;
4668 goto done;
4671 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
4672 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
4673 result = WERR_BADFID;
4674 goto done;
4677 DEBUGADD(8,("Converting info_2 struct\n"));
4680 * convert_printer_info converts the incoming
4681 * info from the client and overwrites the info
4682 * just read from the tdb in the pointer 'printer'.
4685 if (!convert_printer_info(info, printer, level)) {
4686 result = WERR_NOMEM;
4687 goto done;
4690 if (info->info_2->devmode_ptr != 0) {
4691 /* we have a valid devmode
4692 convert it and link it*/
4694 DEBUGADD(8,("Converting the devicemode struct\n"));
4695 if (!convert_devicemode(printer->info_2->printername, devmode,
4696 &printer->info_2->devmode)) {
4697 result = WERR_NOMEM;
4698 goto done;
4702 /* Do sanity check on the requested changes for Samba */
4704 if (!check_printer_ok(printer->info_2, snum)) {
4705 result = WERR_INVALID_PARAM;
4706 goto done;
4709 /* NT likes to call this function even though nothing has actually
4710 changed. Check this so the user doesn't end up with an
4711 annoying permission denied dialog box. */
4713 if (nt_printer_info_level_equal(printer, old_printer)) {
4714 DEBUG(3, ("printer info has not changed\n"));
4715 result = WERR_OK;
4716 goto done;
4719 /* Check calling user has permission to update printer description */
4721 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4722 DEBUG(3, ("printer property change denied by security "
4723 "descriptor\n"));
4724 result = WERR_ACCESS_DENIED;
4725 goto done;
4728 /* Call addprinter hook */
4730 if (*lp_addprinter_cmd()) {
4731 if (!add_printer_hook(printer)) {
4732 result = WERR_ACCESS_DENIED;
4733 goto done;
4737 /* Update printer info */
4738 result = mod_a_printer(*printer, 2);
4740 done:
4741 free_a_printer(&printer, 2);
4742 free_a_printer(&old_printer, 2);
4744 srv_spoolss_sendnotify(p, handle);
4746 return result;
4749 /****************************************************************************
4750 ****************************************************************************/
4752 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4754 POLICY_HND *handle = &q_u->handle;
4755 uint32 level = q_u->level;
4756 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4757 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4758 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4759 uint32 command = q_u->command;
4761 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4763 if (!Printer) {
4764 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4765 return WERR_BADFID;
4768 /* check the level */
4769 switch (level) {
4770 case 0:
4771 return control_printer(handle, command, p);
4772 case 2:
4773 return update_printer(p, handle, level, info, devmode_ctr.devmode);
4774 case 3:
4775 return update_printer_sec(handle, level, info, p,
4776 secdesc_ctr);
4777 default:
4778 return WERR_UNKNOWN_LEVEL;
4782 /****************************************************************************
4783 ****************************************************************************/
4785 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4787 POLICY_HND *handle = &q_u->handle;
4789 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4791 if (!Printer) {
4792 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4793 return WERR_BADFID;
4796 if (Printer->notify.client_connected==True)
4797 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4799 Printer->notify.flags=0;
4800 Printer->notify.options=0;
4801 Printer->notify.localmachine[0]='\0';
4802 Printer->notify.printerlocal=0;
4803 if (Printer->notify.option)
4804 free_spool_notify_option(&Printer->notify.option);
4805 Printer->notify.client_connected=False;
4807 return WERR_OK;
4810 /****************************************************************************
4811 ****************************************************************************/
4813 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4815 /* that's an [in out] buffer (despite appearences to the contrary) */
4816 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4818 r_u->needed = 0;
4819 return WERR_INVALID_PARAM; /* this is what a NT server
4820 returns for AddJob. AddJob
4821 must fail on non-local
4822 printers */
4825 /****************************************************************************
4826 ****************************************************************************/
4827 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4828 int position, int snum)
4830 pstring temp_name;
4832 struct tm *t;
4834 t=gmtime(&queue->time);
4835 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
4837 job_info->jobid=queue->job;
4838 init_unistr(&job_info->printername, lp_servicename(snum));
4839 init_unistr(&job_info->machinename, temp_name);
4840 init_unistr(&job_info->username, queue->user);
4841 init_unistr(&job_info->document, queue->file);
4842 init_unistr(&job_info->datatype, "RAW");
4843 init_unistr(&job_info->text_status, "");
4844 job_info->status=nt_printj_status(queue->status);
4845 job_info->priority=queue->priority;
4846 job_info->position=position;
4847 job_info->totalpages=0;
4848 job_info->pagesprinted=0;
4850 make_systemtime(&job_info->submitted, t);
4853 /****************************************************************************
4854 ****************************************************************************/
4855 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4856 int position, int snum,
4857 NT_PRINTER_INFO_LEVEL *ntprinter)
4859 pstring temp_name;
4860 pstring chaine;
4861 struct tm *t;
4863 t=gmtime(&queue->time);
4864 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
4866 job_info->jobid=queue->job;
4868 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
4870 init_unistr(&job_info->printername, chaine);
4872 init_unistr(&job_info->machinename, temp_name);
4873 init_unistr(&job_info->username, queue->user);
4874 init_unistr(&job_info->document, queue->file);
4875 init_unistr(&job_info->notifyname, queue->user);
4876 init_unistr(&job_info->datatype, "RAW");
4877 init_unistr(&job_info->printprocessor, "winprint");
4878 init_unistr(&job_info->parameters, "");
4879 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4880 init_unistr(&job_info->text_status, "");
4882 /* and here the security descriptor */
4884 job_info->status=nt_printj_status(queue->status);
4885 job_info->priority=queue->priority;
4886 job_info->position=position;
4887 job_info->starttime=0;
4888 job_info->untiltime=0;
4889 job_info->totalpages=0;
4890 job_info->size=queue->size;
4891 make_systemtime(&(job_info->submitted), t);
4892 job_info->timeelapsed=0;
4893 job_info->pagesprinted=0;
4895 if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4896 return False;
4899 return (True);
4902 /****************************************************************************
4903 Enumjobs at level 1.
4904 ****************************************************************************/
4905 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
4906 NEW_BUFFER *buffer, uint32 offered,
4907 uint32 *needed, uint32 *returned)
4909 JOB_INFO_1 *info;
4910 int i;
4912 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4913 if (info==NULL) {
4914 SAFE_FREE(queue);
4915 *returned=0;
4916 return WERR_NOMEM;
4919 for (i=0; i<*returned; i++)
4920 fill_job_info_1(&info[i], &queue[i], i, snum);
4922 SAFE_FREE(queue);
4924 /* check the required size. */
4925 for (i=0; i<*returned; i++)
4926 (*needed) += spoolss_size_job_info_1(&info[i]);
4928 if (!alloc_buffer_size(buffer, *needed)) {
4929 SAFE_FREE(info);
4930 return WERR_INSUFFICIENT_BUFFER;
4933 /* fill the buffer with the structures */
4934 for (i=0; i<*returned; i++)
4935 smb_io_job_info_1("", buffer, &info[i], 0);
4937 /* clear memory */
4938 SAFE_FREE(info);
4940 if (*needed > offered) {
4941 *returned=0;
4942 return WERR_INSUFFICIENT_BUFFER;
4945 return WERR_OK;
4948 /****************************************************************************
4949 Enumjobs at level 2.
4950 ****************************************************************************/
4951 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
4952 NEW_BUFFER *buffer, uint32 offered,
4953 uint32 *needed, uint32 *returned)
4955 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4956 JOB_INFO_2 *info;
4957 int i;
4958 WERROR result;
4960 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4961 if (info==NULL) {
4962 *returned=0;
4963 return WERR_NOMEM;
4966 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
4967 if (!W_ERROR_IS_OK(result)) {
4968 *returned = 0;
4969 return result;
4972 for (i=0; i<*returned; i++)
4973 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4975 free_a_printer(&ntprinter, 2);
4976 SAFE_FREE(queue);
4978 /* check the required size. */
4979 for (i=0; i<*returned; i++)
4980 (*needed) += spoolss_size_job_info_2(&info[i]);
4982 if (!alloc_buffer_size(buffer, *needed)) {
4983 SAFE_FREE(info);
4984 return WERR_INSUFFICIENT_BUFFER;
4987 /* fill the buffer with the structures */
4988 for (i=0; i<*returned; i++)
4989 smb_io_job_info_2("", buffer, &info[i], 0);
4991 /* clear memory */
4992 for (i = 0; i < *returned; i++)
4993 free_job_info_2(&info[i]);
4995 SAFE_FREE(info);
4997 if (*needed > offered) {
4998 *returned=0;
4999 return WERR_INSUFFICIENT_BUFFER;
5002 return WERR_OK;
5005 /****************************************************************************
5006 Enumjobs.
5007 ****************************************************************************/
5009 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
5011 POLICY_HND *handle = &q_u->handle;
5012 /* uint32 firstjob = q_u->firstjob; - notused. */
5013 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5014 uint32 level = q_u->level;
5015 NEW_BUFFER *buffer = NULL;
5016 uint32 offered = q_u->offered;
5017 uint32 *needed = &r_u->needed;
5018 uint32 *returned = &r_u->returned;
5020 int snum;
5021 print_status_struct prt_status;
5022 print_queue_struct *queue=NULL;
5024 /* that's an [in out] buffer */
5025 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5026 buffer = r_u->buffer;
5028 DEBUG(4,("_spoolss_enumjobs\n"));
5030 *needed=0;
5031 *returned=0;
5033 if (!get_printer_snum(p, handle, &snum))
5034 return WERR_BADFID;
5036 *returned = print_queue_status(snum, &queue, &prt_status);
5037 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
5039 if (*returned == 0) {
5040 SAFE_FREE(queue);
5041 return WERR_OK;
5044 switch (level) {
5045 case 1:
5046 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
5047 case 2:
5048 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
5049 default:
5050 SAFE_FREE(queue);
5051 *returned=0;
5052 return WERR_UNKNOWN_LEVEL;
5056 /****************************************************************************
5057 ****************************************************************************/
5059 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
5061 return WERR_OK;
5064 /****************************************************************************
5065 ****************************************************************************/
5067 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
5069 POLICY_HND *handle = &q_u->handle;
5070 uint32 jobid = q_u->jobid;
5071 /* uint32 level = q_u->level; - notused. */
5072 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5073 uint32 command = q_u->command;
5075 struct current_user user;
5076 int snum;
5077 WERROR errcode = WERR_BADFUNC;
5079 if (!get_printer_snum(p, handle, &snum)) {
5080 return WERR_BADFID;
5083 if (!print_job_exists(jobid)) {
5084 return WERR_INVALID_PRINTER_NAME;
5087 get_current_user(&user, p);
5089 switch (command) {
5090 case JOB_CONTROL_CANCEL:
5091 case JOB_CONTROL_DELETE:
5092 if (print_job_delete(&user, jobid, &errcode)) {
5093 errcode = WERR_OK;
5095 break;
5096 case JOB_CONTROL_PAUSE:
5097 if (print_job_pause(&user, jobid, &errcode)) {
5098 errcode = WERR_OK;
5100 break;
5101 case JOB_CONTROL_RESTART:
5102 case JOB_CONTROL_RESUME:
5103 if (print_job_resume(&user, jobid, &errcode)) {
5104 errcode = WERR_OK;
5106 break;
5107 default:
5108 return WERR_UNKNOWN_LEVEL;
5111 return errcode;
5114 /****************************************************************************
5115 Enumerates all printer drivers at level 1.
5116 ****************************************************************************/
5117 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5119 int i;
5120 int ndrivers;
5121 uint32 version;
5122 fstring *list = NULL;
5124 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5125 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
5127 *returned=0;
5129 #define MAX_VERSION 4
5131 for (version=0; version<MAX_VERSION; version++) {
5132 list=NULL;
5133 ndrivers=get_ntdrivers(&list, architecture, version);
5134 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5136 if(ndrivers == -1)
5137 return WERR_NOMEM;
5139 if(ndrivers != 0) {
5140 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
5141 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5142 SAFE_FREE(driver_info_1);
5143 SAFE_FREE(list);
5144 return WERR_NOMEM;
5146 else driver_info_1 = tdi1;
5149 for (i=0; i<ndrivers; i++) {
5150 WERROR status;
5151 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5152 ZERO_STRUCT(driver);
5153 status = get_a_printer_driver(&driver, 3, list[i],
5154 architecture, version);
5155 if (!W_ERROR_IS_OK(status)) {
5156 SAFE_FREE(list);
5157 return status;
5159 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
5160 free_a_printer_driver(driver, 3);
5163 *returned+=ndrivers;
5164 SAFE_FREE(list);
5167 /* check the required size. */
5168 for (i=0; i<*returned; i++) {
5169 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5170 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
5173 if (!alloc_buffer_size(buffer, *needed)) {
5174 SAFE_FREE(driver_info_1);
5175 return WERR_INSUFFICIENT_BUFFER;
5178 /* fill the buffer with the driver structures */
5179 for (i=0; i<*returned; i++) {
5180 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5181 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
5184 SAFE_FREE(driver_info_1);
5186 if (*needed > offered) {
5187 *returned=0;
5188 return WERR_INSUFFICIENT_BUFFER;
5191 return WERR_OK;
5194 /****************************************************************************
5195 Enumerates all printer drivers at level 2.
5196 ****************************************************************************/
5197 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5199 int i;
5200 int ndrivers;
5201 uint32 version;
5202 fstring *list = NULL;
5204 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5205 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
5207 *returned=0;
5209 #define MAX_VERSION 4
5211 for (version=0; version<MAX_VERSION; version++) {
5212 list=NULL;
5213 ndrivers=get_ntdrivers(&list, architecture, version);
5214 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5216 if(ndrivers == -1)
5217 return WERR_NOMEM;
5219 if(ndrivers != 0) {
5220 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5221 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5222 SAFE_FREE(driver_info_2);
5223 SAFE_FREE(list);
5224 return WERR_NOMEM;
5226 else driver_info_2 = tdi2;
5229 for (i=0; i<ndrivers; i++) {
5230 WERROR status;
5232 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5233 ZERO_STRUCT(driver);
5234 status = get_a_printer_driver(&driver, 3, list[i],
5235 architecture, version);
5236 if (!W_ERROR_IS_OK(status)) {
5237 SAFE_FREE(list);
5238 return status;
5240 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
5241 free_a_printer_driver(driver, 3);
5244 *returned+=ndrivers;
5245 SAFE_FREE(list);
5248 /* check the required size. */
5249 for (i=0; i<*returned; i++) {
5250 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5251 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5254 if (!alloc_buffer_size(buffer, *needed)) {
5255 SAFE_FREE(driver_info_2);
5256 return WERR_INSUFFICIENT_BUFFER;
5259 /* fill the buffer with the form structures */
5260 for (i=0; i<*returned; i++) {
5261 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5262 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5265 SAFE_FREE(driver_info_2);
5267 if (*needed > offered) {
5268 *returned=0;
5269 return WERR_INSUFFICIENT_BUFFER;
5272 return WERR_OK;
5275 /****************************************************************************
5276 Enumerates all printer drivers at level 3.
5277 ****************************************************************************/
5278 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5280 int i;
5281 int ndrivers;
5282 uint32 version;
5283 fstring *list = NULL;
5285 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5286 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
5288 *returned=0;
5290 #define MAX_VERSION 4
5292 for (version=0; version<MAX_VERSION; version++) {
5293 list=NULL;
5294 ndrivers=get_ntdrivers(&list, architecture, version);
5295 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5297 if(ndrivers == -1)
5298 return WERR_NOMEM;
5300 if(ndrivers != 0) {
5301 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5302 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5303 SAFE_FREE(driver_info_3);
5304 SAFE_FREE(list);
5305 return WERR_NOMEM;
5307 else driver_info_3 = tdi3;
5310 for (i=0; i<ndrivers; i++) {
5311 WERROR status;
5313 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5314 ZERO_STRUCT(driver);
5315 status = get_a_printer_driver(&driver, 3, list[i],
5316 architecture, version);
5317 if (!W_ERROR_IS_OK(status)) {
5318 SAFE_FREE(list);
5319 return status;
5321 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
5322 free_a_printer_driver(driver, 3);
5325 *returned+=ndrivers;
5326 SAFE_FREE(list);
5329 /* check the required size. */
5330 for (i=0; i<*returned; i++) {
5331 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5332 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5335 if (!alloc_buffer_size(buffer, *needed)) {
5336 SAFE_FREE(driver_info_3);
5337 return WERR_INSUFFICIENT_BUFFER;
5340 /* fill the buffer with the driver structures */
5341 for (i=0; i<*returned; i++) {
5342 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5343 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5346 for (i=0; i<*returned; i++)
5347 SAFE_FREE(driver_info_3[i].dependentfiles);
5349 SAFE_FREE(driver_info_3);
5351 if (*needed > offered) {
5352 *returned=0;
5353 return WERR_INSUFFICIENT_BUFFER;
5356 return WERR_OK;
5359 /****************************************************************************
5360 Enumerates all printer drivers.
5361 ****************************************************************************/
5363 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5365 /* UNISTR2 *name = &q_u->name; - notused. */
5366 UNISTR2 *environment = &q_u->environment;
5367 uint32 level = q_u->level;
5368 NEW_BUFFER *buffer = NULL;
5369 uint32 offered = q_u->offered;
5370 uint32 *needed = &r_u->needed;
5371 uint32 *returned = &r_u->returned;
5373 fstring *list = NULL;
5374 fstring servername;
5375 fstring architecture;
5377 /* that's an [in out] buffer */
5378 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5379 buffer = r_u->buffer;
5381 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5382 fstrcpy(servername, get_called_name());
5383 *needed=0;
5384 *returned=0;
5386 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5388 switch (level) {
5389 case 1:
5390 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5391 case 2:
5392 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5393 case 3:
5394 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5395 default:
5396 *returned=0;
5397 SAFE_FREE(list);
5398 return WERR_UNKNOWN_LEVEL;
5402 /****************************************************************************
5403 ****************************************************************************/
5405 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5407 form->flag=list->flag;
5408 init_unistr(&form->name, list->name);
5409 form->width=list->width;
5410 form->length=list->length;
5411 form->left=list->left;
5412 form->top=list->top;
5413 form->right=list->right;
5414 form->bottom=list->bottom;
5417 /****************************************************************************
5418 ****************************************************************************/
5420 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5422 /* POLICY_HND *handle = &q_u->handle; - notused. */
5423 uint32 level = q_u->level;
5424 NEW_BUFFER *buffer = NULL;
5425 uint32 offered = q_u->offered;
5426 uint32 *needed = &r_u->needed;
5427 uint32 *numofforms = &r_u->numofforms;
5428 uint32 numbuiltinforms;
5430 nt_forms_struct *list=NULL;
5431 nt_forms_struct *builtinlist=NULL;
5432 FORM_1 *forms_1;
5433 int buffer_size=0;
5434 int i;
5436 /* that's an [in out] buffer */
5437 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5438 buffer = r_u->buffer;
5440 DEBUG(4,("_spoolss_enumforms\n"));
5441 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5442 DEBUGADD(5,("Info level [%d]\n", level));
5444 numbuiltinforms = get_builtin_ntforms(&builtinlist);
5445 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
5446 *numofforms = get_ntforms(&list);
5447 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
5448 *numofforms += numbuiltinforms;
5450 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
5452 switch (level) {
5453 case 1:
5454 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5455 *numofforms=0;
5456 return WERR_NOMEM;
5459 /* construct the list of form structures */
5460 for (i=0; i<numbuiltinforms; i++) {
5461 DEBUGADD(6,("Filling form number [%d]\n",i));
5462 fill_form_1(&forms_1[i], &builtinlist[i]);
5465 SAFE_FREE(builtinlist);
5467 for (; i<*numofforms; i++) {
5468 DEBUGADD(6,("Filling form number [%d]\n",i));
5469 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5472 SAFE_FREE(list);
5474 /* check the required size. */
5475 for (i=0; i<numbuiltinforms; i++) {
5476 DEBUGADD(6,("adding form [%d]'s size\n",i));
5477 buffer_size += spoolss_size_form_1(&forms_1[i]);
5479 for (; i<*numofforms; i++) {
5480 DEBUGADD(6,("adding form [%d]'s size\n",i));
5481 buffer_size += spoolss_size_form_1(&forms_1[i]);
5484 *needed=buffer_size;
5486 if (!alloc_buffer_size(buffer, buffer_size)){
5487 SAFE_FREE(forms_1);
5488 return WERR_INSUFFICIENT_BUFFER;
5491 /* fill the buffer with the form structures */
5492 for (i=0; i<numbuiltinforms; i++) {
5493 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5494 smb_io_form_1("", buffer, &forms_1[i], 0);
5496 for (; i<*numofforms; i++) {
5497 DEBUGADD(6,("adding form [%d] to buffer\n",i));
5498 smb_io_form_1("", buffer, &forms_1[i], 0);
5501 SAFE_FREE(forms_1);
5503 if (*needed > offered) {
5504 *numofforms=0;
5505 return WERR_INSUFFICIENT_BUFFER;
5507 else
5508 return WERR_OK;
5510 default:
5511 SAFE_FREE(list);
5512 SAFE_FREE(builtinlist);
5513 return WERR_UNKNOWN_LEVEL;
5518 /****************************************************************************
5519 ****************************************************************************/
5521 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5523 /* POLICY_HND *handle = &q_u->handle; - notused. */
5524 uint32 level = q_u->level;
5525 UNISTR2 *uni_formname = &q_u->formname;
5526 NEW_BUFFER *buffer = NULL;
5527 uint32 offered = q_u->offered;
5528 uint32 *needed = &r_u->needed;
5530 nt_forms_struct *list=NULL;
5531 nt_forms_struct builtin_form;
5532 BOOL foundBuiltin;
5533 FORM_1 form_1;
5534 fstring form_name;
5535 int buffer_size=0;
5536 int numofforms=0, i=0;
5538 /* that's an [in out] buffer */
5539 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5540 buffer = r_u->buffer;
5542 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5544 DEBUG(4,("_spoolss_getform\n"));
5545 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5546 DEBUGADD(5,("Info level [%d]\n", level));
5548 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5549 if (!foundBuiltin) {
5550 numofforms = get_ntforms(&list);
5551 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
5553 if (numofforms == 0)
5554 return WERR_BADFID;
5557 switch (level) {
5558 case 1:
5559 if (foundBuiltin) {
5560 fill_form_1(&form_1, &builtin_form);
5561 } else {
5563 /* Check if the requested name is in the list of form structures */
5564 for (i=0; i<numofforms; i++) {
5566 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5568 if (strequal(form_name, list[i].name)) {
5569 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5570 fill_form_1(&form_1, &list[i]);
5571 break;
5575 SAFE_FREE(list);
5576 if (i == numofforms) {
5577 return WERR_BADFID;
5580 /* check the required size. */
5582 *needed=spoolss_size_form_1(&form_1);
5584 if (!alloc_buffer_size(buffer, buffer_size)){
5585 return WERR_INSUFFICIENT_BUFFER;
5588 if (*needed > offered) {
5589 return WERR_INSUFFICIENT_BUFFER;
5592 /* fill the buffer with the form structures */
5593 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5594 smb_io_form_1("", buffer, &form_1, 0);
5596 return WERR_OK;
5598 default:
5599 SAFE_FREE(list);
5600 return WERR_UNKNOWN_LEVEL;
5604 /****************************************************************************
5605 ****************************************************************************/
5606 static void fill_port_1(PORT_INFO_1 *port, char *name)
5608 init_unistr(&port->port_name, name);
5611 /****************************************************************************
5612 ****************************************************************************/
5613 static void fill_port_2(PORT_INFO_2 *port, char *name)
5615 init_unistr(&port->port_name, name);
5616 init_unistr(&port->monitor_name, "Local Monitor");
5617 init_unistr(&port->description, "Local Port");
5618 #define PORT_TYPE_WRITE 1
5619 port->port_type=PORT_TYPE_WRITE;
5620 port->reserved=0x0;
5623 /****************************************************************************
5624 enumports level 1.
5625 ****************************************************************************/
5626 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5628 PORT_INFO_1 *ports=NULL;
5629 int i=0;
5631 if (*lp_enumports_cmd()) {
5632 char *cmd = lp_enumports_cmd();
5633 char **qlines;
5634 pstring command;
5635 int numlines;
5636 int ret;
5637 int fd;
5639 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5641 DEBUG(10,("Running [%s]\n", command));
5642 ret = smbrun(command, &fd);
5643 DEBUG(10,("Returned [%d]\n", ret));
5644 if (ret != 0) {
5645 if (fd != -1)
5646 close(fd);
5647 /* Is this the best error to return here? */
5648 return WERR_ACCESS_DENIED;
5651 numlines = 0;
5652 qlines = fd_lines_load(fd, &numlines);
5653 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5654 close(fd);
5656 if(numlines) {
5657 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5658 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
5659 werror_str(WERR_NOMEM)));
5660 file_lines_free(qlines);
5661 return WERR_NOMEM;
5664 for (i=0; i<numlines; i++) {
5665 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5666 fill_port_1(&ports[i], qlines[i]);
5669 file_lines_free(qlines);
5672 *returned = numlines;
5674 } else {
5675 *returned = 1; /* Sole Samba port returned. */
5677 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5678 return WERR_NOMEM;
5680 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5682 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5685 /* check the required size. */
5686 for (i=0; i<*returned; i++) {
5687 DEBUGADD(6,("adding port [%d]'s size\n", i));
5688 *needed += spoolss_size_port_info_1(&ports[i]);
5691 if (!alloc_buffer_size(buffer, *needed)) {
5692 SAFE_FREE(ports);
5693 return WERR_INSUFFICIENT_BUFFER;
5696 /* fill the buffer with the ports structures */
5697 for (i=0; i<*returned; i++) {
5698 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5699 smb_io_port_1("", buffer, &ports[i], 0);
5702 SAFE_FREE(ports);
5704 if (*needed > offered) {
5705 *returned=0;
5706 return WERR_INSUFFICIENT_BUFFER;
5709 return WERR_OK;
5712 /****************************************************************************
5713 enumports level 2.
5714 ****************************************************************************/
5716 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5718 PORT_INFO_2 *ports=NULL;
5719 int i=0;
5721 if (*lp_enumports_cmd()) {
5722 char *cmd = lp_enumports_cmd();
5723 char *path;
5724 char **qlines;
5725 pstring tmp_file;
5726 pstring command;
5727 int numlines;
5728 int ret;
5729 int fd;
5731 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5732 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5733 else
5734 path = lp_lockdir();
5736 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
5737 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5739 unlink(tmp_file);
5740 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5741 ret = smbrun(command, &fd);
5742 DEBUGADD(10,("returned [%d]\n", ret));
5743 if (ret != 0) {
5744 if (fd != -1)
5745 close(fd);
5746 /* Is this the best error to return here? */
5747 return WERR_ACCESS_DENIED;
5750 numlines = 0;
5751 qlines = fd_lines_load(fd, &numlines);
5752 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5753 close(fd);
5755 if(numlines) {
5756 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5757 file_lines_free(qlines);
5758 return WERR_NOMEM;
5761 for (i=0; i<numlines; i++) {
5762 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5763 fill_port_2(&(ports[i]), qlines[i]);
5766 file_lines_free(qlines);
5769 *returned = numlines;
5771 } else {
5773 *returned = 1;
5775 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5776 return WERR_NOMEM;
5778 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5780 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5783 /* check the required size. */
5784 for (i=0; i<*returned; i++) {
5785 DEBUGADD(6,("adding port [%d]'s size\n", i));
5786 *needed += spoolss_size_port_info_2(&ports[i]);
5789 if (!alloc_buffer_size(buffer, *needed)) {
5790 SAFE_FREE(ports);
5791 return WERR_INSUFFICIENT_BUFFER;
5794 /* fill the buffer with the ports structures */
5795 for (i=0; i<*returned; i++) {
5796 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5797 smb_io_port_2("", buffer, &ports[i], 0);
5800 SAFE_FREE(ports);
5802 if (*needed > offered) {
5803 *returned=0;
5804 return WERR_INSUFFICIENT_BUFFER;
5807 return WERR_OK;
5810 /****************************************************************************
5811 enumports.
5812 ****************************************************************************/
5814 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5816 /* UNISTR2 *name = &q_u->name; - notused. */
5817 uint32 level = q_u->level;
5818 NEW_BUFFER *buffer = NULL;
5819 uint32 offered = q_u->offered;
5820 uint32 *needed = &r_u->needed;
5821 uint32 *returned = &r_u->returned;
5823 /* that's an [in out] buffer */
5824 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5825 buffer = r_u->buffer;
5827 DEBUG(4,("_spoolss_enumports\n"));
5829 *returned=0;
5830 *needed=0;
5832 switch (level) {
5833 case 1:
5834 return enumports_level_1(buffer, offered, needed, returned);
5835 case 2:
5836 return enumports_level_2(buffer, offered, needed, returned);
5837 default:
5838 return WERR_UNKNOWN_LEVEL;
5842 /****************************************************************************
5843 ****************************************************************************/
5844 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5845 const SPOOL_PRINTER_INFO_LEVEL *info,
5846 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
5847 uint32 user_switch, const SPOOL_USER_CTR *user,
5848 POLICY_HND *handle)
5850 NT_PRINTER_INFO_LEVEL *printer = NULL;
5851 fstring name;
5852 int snum;
5853 WERROR err = WERR_OK;
5855 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5856 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5857 return WERR_NOMEM;
5860 ZERO_STRUCTP(printer);
5862 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5863 if (!convert_printer_info(info, printer, 2)) {
5864 free_a_printer(&printer, 2);
5865 return WERR_NOMEM;
5868 /* check to see if the printer already exists */
5870 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
5871 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
5872 printer->info_2->sharename));
5873 free_a_printer(&printer, 2);
5874 return WERR_PRINTER_ALREADY_EXISTS;
5877 if (*lp_addprinter_cmd() )
5878 if ( !add_printer_hook(printer) ) {
5879 free_a_printer(&printer,2);
5880 return WERR_ACCESS_DENIED;
5883 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
5884 printer->info_2->sharename);
5886 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5887 free_a_printer(&printer,2);
5888 return WERR_ACCESS_DENIED;
5891 /* you must be a printer admin to add a new printer */
5892 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5893 free_a_printer(&printer,2);
5894 return WERR_ACCESS_DENIED;
5898 * Do sanity check on the requested changes for Samba.
5901 if (!check_printer_ok(printer->info_2, snum)) {
5902 free_a_printer(&printer,2);
5903 return WERR_INVALID_PARAM;
5907 * When a printer is created, the drivername bound to the printer is used
5908 * to lookup previously saved driver initialization info, which is then
5909 * bound to the new printer, simulating what happens in the Windows arch.
5911 set_driver_init(printer, 2);
5913 /* write the ASCII on disk */
5914 err = mod_a_printer(*printer, 2);
5915 if (!W_ERROR_IS_OK(err)) {
5916 free_a_printer(&printer,2);
5917 return err;
5920 if (!open_printer_hnd(p, handle, name)) {
5921 /* Handle open failed - remove addition. */
5922 del_a_printer(printer->info_2->sharename);
5923 free_a_printer(&printer,2);
5924 return WERR_ACCESS_DENIED;
5927 free_a_printer(&printer,2);
5929 srv_spoolss_sendnotify(p, handle);
5931 return WERR_OK;
5934 /****************************************************************************
5935 ****************************************************************************/
5937 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5939 UNISTR2 *uni_srv_name = &q_u->server_name;
5940 uint32 level = q_u->level;
5941 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5942 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
5943 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
5944 uint32 user_switch = q_u->user_switch;
5945 SPOOL_USER_CTR *user = &q_u->user_ctr;
5946 POLICY_HND *handle = &r_u->handle;
5948 switch (level) {
5949 case 1:
5950 /* we don't handle yet */
5951 /* but I know what to do ... */
5952 return WERR_UNKNOWN_LEVEL;
5953 case 2:
5954 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5955 devmode, sdb,
5956 user_switch, user, handle);
5957 default:
5958 return WERR_UNKNOWN_LEVEL;
5962 /****************************************************************************
5963 ****************************************************************************/
5965 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5967 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5968 uint32 level = q_u->level;
5969 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5970 WERROR err = WERR_OK;
5971 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5972 struct current_user user;
5974 ZERO_STRUCT(driver);
5976 get_current_user(&user, p);
5978 if (!convert_printer_driver_info(info, &driver, level)) {
5979 err = WERR_NOMEM;
5980 goto done;
5983 DEBUG(5,("Cleaning driver's information\n"));
5984 err = clean_up_driver_struct(driver, level, &user);
5985 if (!W_ERROR_IS_OK(err))
5986 goto done;
5988 DEBUG(5,("Moving driver to final destination\n"));
5989 if(!move_driver_to_download_area(driver, level, &user, &err)) {
5990 if (W_ERROR_IS_OK(err))
5991 err = WERR_ACCESS_DENIED;
5992 goto done;
5995 if (add_a_printer_driver(driver, level)!=0) {
5996 err = WERR_ACCESS_DENIED;
5997 goto done;
6000 done:
6001 free_a_printer_driver(driver, level);
6002 return err;
6005 /****************************************************************************
6006 ****************************************************************************/
6007 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
6009 init_unistr(&info->name, name);
6012 /****************************************************************************
6013 ****************************************************************************/
6014 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6016 pstring path;
6017 pstring long_archi;
6018 pstring short_archi;
6019 DRIVER_DIRECTORY_1 *info=NULL;
6021 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
6023 if (get_short_archi(short_archi, long_archi)==False)
6024 return WERR_INVALID_ENVIRONMENT;
6026 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
6027 return WERR_NOMEM;
6029 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
6031 DEBUG(4,("printer driver directory: [%s]\n", path));
6033 fill_driverdir_1(info, path);
6035 *needed += spoolss_size_driverdir_info_1(info);
6037 if (!alloc_buffer_size(buffer, *needed)) {
6038 SAFE_FREE(info);
6039 return WERR_INSUFFICIENT_BUFFER;
6042 smb_io_driverdir_1("", buffer, info, 0);
6044 SAFE_FREE(info);
6046 if (*needed > offered)
6047 return WERR_INSUFFICIENT_BUFFER;
6049 return WERR_OK;
6052 /****************************************************************************
6053 ****************************************************************************/
6055 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
6057 UNISTR2 *name = &q_u->name;
6058 UNISTR2 *uni_environment = &q_u->environment;
6059 uint32 level = q_u->level;
6060 NEW_BUFFER *buffer = NULL;
6061 uint32 offered = q_u->offered;
6062 uint32 *needed = &r_u->needed;
6064 /* that's an [in out] buffer */
6065 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6066 buffer = r_u->buffer;
6068 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6070 *needed=0;
6072 switch(level) {
6073 case 1:
6074 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
6075 default:
6076 return WERR_UNKNOWN_LEVEL;
6080 /****************************************************************************
6081 ****************************************************************************/
6083 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
6085 POLICY_HND *handle = &q_u->handle;
6086 uint32 idx = q_u->index;
6087 uint32 in_value_len = q_u->valuesize;
6088 uint32 in_data_len = q_u->datasize;
6089 uint32 *out_max_value_len = &r_u->valuesize;
6090 uint16 **out_value = &r_u->value;
6091 uint32 *out_value_len = &r_u->realvaluesize;
6092 uint32 *out_type = &r_u->type;
6093 uint32 *out_max_data_len = &r_u->datasize;
6094 uint8 **data_out = &r_u->data;
6095 uint32 *out_data_len = &r_u->realdatasize;
6097 NT_PRINTER_INFO_LEVEL *printer = NULL;
6099 fstring value;
6101 uint32 param_index;
6102 uint32 biggest_valuesize;
6103 uint32 biggest_datasize;
6104 uint32 data_len;
6105 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6106 int snum;
6107 uint8 *data=NULL;
6108 uint32 type;
6109 WERROR result;
6111 ZERO_STRUCT(printer);
6113 *out_type=0;
6115 *out_max_data_len=0;
6116 *data_out=NULL;
6117 *out_data_len=0;
6119 DEBUG(5,("spoolss_enumprinterdata\n"));
6121 if (!Printer) {
6122 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6123 return WERR_BADFID;
6126 if (!get_printer_snum(p,handle, &snum))
6127 return WERR_BADFID;
6129 result = get_a_printer(&printer, 2, lp_servicename(snum));
6130 if (!W_ERROR_IS_OK(result))
6131 return result;
6134 * The NT machine wants to know the biggest size of value and data
6136 * cf: MSDN EnumPrinterData remark section
6138 if ( (in_value_len==0) && (in_data_len==0) ) {
6139 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6141 #if 0
6143 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6144 * if this parameter size doesn't exist.
6145 * Ok - my opinion here is that the client is not asking for the greatest
6146 * possible size of all the parameters, but is asking specifically for the size needed
6147 * for this specific parameter. In that case we can remove the loop below and
6148 * simplify this lookup code considerably. JF - comments welcome. JRA.
6151 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6152 SAFE_FREE(data);
6153 free_a_printer(&printer, 2);
6154 return WERR_NO_MORE_ITEMS;
6156 #endif
6158 SAFE_FREE(data);
6160 param_index=0;
6161 biggest_valuesize=0;
6162 biggest_datasize=0;
6164 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
6165 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
6166 if (data_len > biggest_datasize) biggest_datasize=data_len;
6168 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
6170 SAFE_FREE(data);
6171 param_index++;
6174 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6175 *out_value_len=2*(1+biggest_valuesize);
6176 *out_data_len=biggest_datasize;
6178 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
6180 free_a_printer(&printer, 2);
6181 return WERR_OK;
6185 * the value len is wrong in NT sp3
6186 * that's the number of bytes not the number of unicode chars
6189 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
6191 SAFE_FREE(data);
6192 free_a_printer(&printer, 2);
6194 /* out_value should default to "" or else NT4 has
6195 problems unmarshalling the response */
6197 *out_max_value_len=(in_value_len/sizeof(uint16));
6198 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL)
6199 return WERR_NOMEM;
6201 ZERO_STRUCTP(*out_value);
6202 *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
6204 /* the data is counted in bytes */
6205 *out_max_data_len = in_data_len;
6206 *out_data_len = in_data_len;
6207 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL)
6208 return WERR_NOMEM;
6210 memset(*data_out,'\0',in_data_len);
6212 return WERR_NO_MORE_ITEMS;
6215 free_a_printer(&printer, 2);
6218 * the value is:
6219 * - counted in bytes in the request
6220 * - counted in UNICODE chars in the max reply
6221 * - counted in bytes in the real size
6223 * take a pause *before* coding not *during* coding
6226 *out_max_value_len=(in_value_len/sizeof(uint16));
6227 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6228 SAFE_FREE(data);
6229 return WERR_NOMEM;
6232 *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
6234 *out_type=type;
6236 /* the data is counted in bytes */
6237 *out_max_data_len=in_data_len;
6238 if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6239 SAFE_FREE(data);
6240 return WERR_NOMEM;
6243 memcpy(*data_out, data, (size_t)data_len);
6244 *out_data_len=data_len;
6246 SAFE_FREE(data);
6248 return WERR_OK;
6251 /****************************************************************************
6252 ****************************************************************************/
6254 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6256 POLICY_HND *handle = &q_u->handle;
6257 UNISTR2 *value = &q_u->value;
6258 uint32 type = q_u->type;
6259 /* uint32 max_len = q_u->max_len; - notused. */
6260 uint8 *data = q_u->data;
6261 uint32 real_len = q_u->real_len;
6262 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6264 NT_PRINTER_INFO_LEVEL *printer = NULL;
6265 NT_PRINTER_PARAM *param = NULL, old_param;
6266 int snum=0;
6267 WERROR status = WERR_OK;
6268 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6270 DEBUG(5,("spoolss_setprinterdata\n"));
6272 if (!Printer) {
6273 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6274 return WERR_BADFID;
6277 if (!get_printer_snum(p,handle, &snum))
6278 return WERR_BADFID;
6280 ZERO_STRUCT(old_param);
6283 * Access check : NT returns "access denied" if you make a
6284 * SetPrinterData call without the necessary privildge.
6285 * we were originally returning OK if nothing changed
6286 * which made Win2k issue **a lot** of SetPrinterData
6287 * when connecting to a printer --jerry
6290 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6291 DEBUG(3, ("security descriptor change denied by existing "
6292 "security descriptor\n"));
6293 status = WERR_ACCESS_DENIED;
6294 goto done;
6297 /* Check if we are making any changes or not. Return true if
6298 nothing is actually changing. This is not needed anymore but
6299 has been left in as an optimization to keep from from
6300 writing to disk as often --jerry */
6302 status = get_a_printer(&printer, 2, lp_servicename(snum));
6303 if (!W_ERROR_IS_OK(status))
6304 return status;
6306 convert_specific_param(&param, value , type, data, real_len);
6308 #if 0
6309 if (get_specific_param(*printer, 2, param->value, &old_param.data,
6310 &old_param.type, (uint32 *)&old_param.data_len)) {
6312 if (param->type == old_param.type &&
6313 param->data_len == old_param.data_len &&
6314 memcmp(param->data, old_param.data,
6315 old_param.data_len) == 0) {
6317 DEBUG(3, ("setprinterdata hasn't changed\n"));
6318 status = WERR_OK;
6319 goto done;
6322 #endif
6324 unlink_specific_param_if_exist(printer->info_2, param);
6327 * When client side code sets a magic printer data key, detect it and save
6328 * the current printer data and the magic key's data (its the DEVMODE) for
6329 * future printer/driver initializations.
6331 if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
6333 * Set devmode and printer initialization info
6335 status = save_driver_init(printer, 2, param);
6337 else {
6338 add_a_specific_param(printer->info_2, &param);
6339 status = mod_a_printer(*printer, 2);
6342 done:
6343 free_a_printer(&printer, 2);
6344 if (param)
6345 free_nt_printer_param(&param);
6346 SAFE_FREE(old_param.data);
6348 return status;
6351 /****************************************************************************
6352 ****************************************************************************/
6354 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6356 POLICY_HND *handle = &q_u->handle;
6357 UNISTR2 *value = &q_u->valuename;
6359 NT_PRINTER_INFO_LEVEL *printer = NULL;
6360 NT_PRINTER_PARAM param;
6361 int snum=0;
6362 WERROR status = WERR_OK;
6363 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6365 DEBUG(5,("spoolss_deleteprinterdata\n"));
6367 if (!Printer) {
6368 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6369 return WERR_BADFID;
6372 if (!get_printer_snum(p, handle, &snum))
6373 return WERR_BADFID;
6375 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6376 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6377 "change denied by existing security descriptor\n"));
6378 return WERR_ACCESS_DENIED;
6381 status = get_a_printer(&printer, 2, lp_servicename(snum));
6382 if (!W_ERROR_IS_OK(status))
6383 return status;
6385 ZERO_STRUCTP(&param);
6386 unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6388 if(!unlink_specific_param_if_exist(printer->info_2, &param))
6389 status = WERR_INVALID_PARAM;
6390 else
6391 status = mod_a_printer(*printer, 2);
6393 free_a_printer(&printer, 2);
6394 return status;
6397 /****************************************************************************
6398 ****************************************************************************/
6400 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6402 POLICY_HND *handle = &q_u->handle;
6403 /* uint32 level = q_u->level; - notused. */
6404 FORM *form = &q_u->form;
6405 nt_forms_struct tmpForm;
6407 int count=0;
6408 nt_forms_struct *list=NULL;
6409 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6411 DEBUG(5,("spoolss_addform\n"));
6413 if (!Printer) {
6414 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6415 return WERR_BADFID;
6419 * FIXME!! Feels like there should be an access check here, but haven't
6420 * had time to verify. --jerry
6423 /* can't add if builtin */
6424 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6425 return WERR_INVALID_PARAM;
6428 count=get_ntforms(&list);
6429 if(!add_a_form(&list, form, &count))
6430 return WERR_NOMEM;
6431 write_ntforms(&list, count);
6433 SAFE_FREE(list);
6435 return WERR_OK;
6438 /****************************************************************************
6439 ****************************************************************************/
6441 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6443 POLICY_HND *handle = &q_u->handle;
6444 UNISTR2 *form_name = &q_u->name;
6445 nt_forms_struct tmpForm;
6446 int count=0;
6447 WERROR ret = WERR_OK;
6448 nt_forms_struct *list=NULL;
6449 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6451 DEBUG(5,("spoolss_deleteform\n"));
6453 if (!Printer) {
6454 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6455 return WERR_BADFID;
6458 /* can't delete if builtin */
6459 if (get_a_builtin_ntform(form_name,&tmpForm)) {
6460 return WERR_INVALID_PARAM;
6463 count = get_ntforms(&list);
6464 if(!delete_a_form(&list, form_name, &count, &ret))
6465 return WERR_INVALID_PARAM;
6467 SAFE_FREE(list);
6469 return ret;
6472 /****************************************************************************
6473 ****************************************************************************/
6475 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6477 POLICY_HND *handle = &q_u->handle;
6478 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6479 /* uint32 level = q_u->level; - notused. */
6480 FORM *form = &q_u->form;
6481 nt_forms_struct tmpForm;
6483 int count=0;
6484 nt_forms_struct *list=NULL;
6485 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6487 DEBUG(5,("spoolss_setform\n"));
6489 if (!Printer) {
6490 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6491 return WERR_BADFID;
6493 /* can't set if builtin */
6494 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6495 return WERR_INVALID_PARAM;
6498 count=get_ntforms(&list);
6499 update_a_form(&list, form, count);
6500 write_ntforms(&list, count);
6502 SAFE_FREE(list);
6504 return WERR_OK;
6507 /****************************************************************************
6508 enumprintprocessors level 1.
6509 ****************************************************************************/
6510 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6512 PRINTPROCESSOR_1 *info_1=NULL;
6514 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6515 return WERR_NOMEM;
6517 (*returned) = 0x1;
6519 init_unistr(&info_1->name, "winprint");
6521 *needed += spoolss_size_printprocessor_info_1(info_1);
6523 if (!alloc_buffer_size(buffer, *needed))
6524 return WERR_INSUFFICIENT_BUFFER;
6526 smb_io_printprocessor_info_1("", buffer, info_1, 0);
6528 SAFE_FREE(info_1);
6530 if (*needed > offered) {
6531 *returned=0;
6532 return WERR_INSUFFICIENT_BUFFER;
6535 return WERR_OK;
6538 /****************************************************************************
6539 ****************************************************************************/
6541 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6543 /* UNISTR2 *name = &q_u->name; - notused. */
6544 /* UNISTR2 *environment = &q_u->environment; - notused. */
6545 uint32 level = q_u->level;
6546 NEW_BUFFER *buffer = NULL;
6547 uint32 offered = q_u->offered;
6548 uint32 *needed = &r_u->needed;
6549 uint32 *returned = &r_u->returned;
6551 /* that's an [in out] buffer */
6552 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6553 buffer = r_u->buffer;
6555 DEBUG(5,("spoolss_enumprintprocessors\n"));
6558 * Enumerate the print processors ...
6560 * Just reply with "winprint", to keep NT happy
6561 * and I can use my nice printer checker.
6564 *returned=0;
6565 *needed=0;
6567 switch (level) {
6568 case 1:
6569 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6570 default:
6571 return WERR_UNKNOWN_LEVEL;
6575 /****************************************************************************
6576 enumprintprocdatatypes level 1.
6577 ****************************************************************************/
6578 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6580 PRINTPROCDATATYPE_1 *info_1=NULL;
6582 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6583 return WERR_NOMEM;
6585 (*returned) = 0x1;
6587 init_unistr(&info_1->name, "RAW");
6589 *needed += spoolss_size_printprocdatatype_info_1(info_1);
6591 if (!alloc_buffer_size(buffer, *needed))
6592 return WERR_INSUFFICIENT_BUFFER;
6594 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6596 SAFE_FREE(info_1);
6598 if (*needed > offered) {
6599 *returned=0;
6600 return WERR_INSUFFICIENT_BUFFER;
6603 return WERR_OK;
6606 /****************************************************************************
6607 ****************************************************************************/
6609 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6611 /* UNISTR2 *name = &q_u->name; - notused. */
6612 /* UNISTR2 *processor = &q_u->processor; - notused. */
6613 uint32 level = q_u->level;
6614 NEW_BUFFER *buffer = NULL;
6615 uint32 offered = q_u->offered;
6616 uint32 *needed = &r_u->needed;
6617 uint32 *returned = &r_u->returned;
6619 /* that's an [in out] buffer */
6620 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6621 buffer = r_u->buffer;
6623 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6625 *returned=0;
6626 *needed=0;
6628 switch (level) {
6629 case 1:
6630 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6631 default:
6632 return WERR_UNKNOWN_LEVEL;
6636 /****************************************************************************
6637 enumprintmonitors level 1.
6638 ****************************************************************************/
6640 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6642 PRINTMONITOR_1 *info_1=NULL;
6644 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6645 return WERR_NOMEM;
6647 (*returned) = 0x1;
6649 init_unistr(&info_1->name, "Local Port");
6651 *needed += spoolss_size_printmonitor_info_1(info_1);
6653 if (!alloc_buffer_size(buffer, *needed))
6654 return WERR_INSUFFICIENT_BUFFER;
6656 smb_io_printmonitor_info_1("", buffer, info_1, 0);
6658 SAFE_FREE(info_1);
6660 if (*needed > offered) {
6661 *returned=0;
6662 return WERR_INSUFFICIENT_BUFFER;
6665 return WERR_OK;
6668 /****************************************************************************
6669 enumprintmonitors level 2.
6670 ****************************************************************************/
6671 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6673 PRINTMONITOR_2 *info_2=NULL;
6675 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6676 return WERR_NOMEM;
6678 (*returned) = 0x1;
6680 init_unistr(&info_2->name, "Local Port");
6681 init_unistr(&info_2->environment, "Windows NT X86");
6682 init_unistr(&info_2->dll_name, "localmon.dll");
6684 *needed += spoolss_size_printmonitor_info_2(info_2);
6686 if (!alloc_buffer_size(buffer, *needed))
6687 return WERR_INSUFFICIENT_BUFFER;
6689 smb_io_printmonitor_info_2("", buffer, info_2, 0);
6691 SAFE_FREE(info_2);
6693 if (*needed > offered) {
6694 *returned=0;
6695 return WERR_INSUFFICIENT_BUFFER;
6698 return WERR_OK;
6701 /****************************************************************************
6702 ****************************************************************************/
6704 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6706 /* UNISTR2 *name = &q_u->name; - notused. */
6707 uint32 level = q_u->level;
6708 NEW_BUFFER *buffer = NULL;
6709 uint32 offered = q_u->offered;
6710 uint32 *needed = &r_u->needed;
6711 uint32 *returned = &r_u->returned;
6713 /* that's an [in out] buffer */
6714 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6715 buffer = r_u->buffer;
6717 DEBUG(5,("spoolss_enumprintmonitors\n"));
6720 * Enumerate the print monitors ...
6722 * Just reply with "Local Port", to keep NT happy
6723 * and I can use my nice printer checker.
6726 *returned=0;
6727 *needed=0;
6729 switch (level) {
6730 case 1:
6731 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6732 case 2:
6733 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6734 default:
6735 return WERR_UNKNOWN_LEVEL;
6739 /****************************************************************************
6740 ****************************************************************************/
6741 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6743 int i=0;
6744 BOOL found=False;
6745 JOB_INFO_1 *info_1=NULL;
6747 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6749 if (info_1 == NULL) {
6750 SAFE_FREE(queue);
6751 return WERR_NOMEM;
6754 for (i=0; i<count && found==False; i++) {
6755 if (queue[i].job==(int)jobid)
6756 found=True;
6759 if (found==False) {
6760 SAFE_FREE(queue);
6761 SAFE_FREE(info_1);
6762 /* NT treats not found as bad param... yet another bad choice */
6763 return WERR_INVALID_PARAM;
6766 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6768 SAFE_FREE(queue);
6770 *needed += spoolss_size_job_info_1(info_1);
6772 if (!alloc_buffer_size(buffer, *needed)) {
6773 SAFE_FREE(info_1);
6774 return WERR_INSUFFICIENT_BUFFER;
6777 smb_io_job_info_1("", buffer, info_1, 0);
6779 SAFE_FREE(info_1);
6781 if (*needed > offered)
6782 return WERR_INSUFFICIENT_BUFFER;
6784 return WERR_OK;
6788 /****************************************************************************
6789 ****************************************************************************/
6790 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6792 int i=0;
6793 BOOL found=False;
6794 JOB_INFO_2 *info_2;
6795 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6796 WERROR ret;
6798 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6800 ZERO_STRUCTP(info_2);
6802 if (info_2 == NULL) {
6803 SAFE_FREE(queue);
6804 return WERR_NOMEM;
6807 for (i=0; i<count && found==False; i++) {
6808 if (queue[i].job==(int)jobid)
6809 found=True;
6812 if (found==False) {
6813 SAFE_FREE(queue);
6814 SAFE_FREE(info_2);
6815 /* NT treats not found as bad param... yet another bad choice */
6816 return WERR_INVALID_PARAM;
6819 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6820 if (!W_ERROR_IS_OK(ret)) {
6821 SAFE_FREE(queue);
6822 return ret;
6825 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6827 free_a_printer(&ntprinter, 2);
6828 SAFE_FREE(queue);
6830 *needed += spoolss_size_job_info_2(info_2);
6832 if (!alloc_buffer_size(buffer, *needed)) {
6833 SAFE_FREE(info_2);
6834 return WERR_INSUFFICIENT_BUFFER;
6837 smb_io_job_info_2("", buffer, info_2, 0);
6839 free_job_info_2(info_2);
6840 SAFE_FREE(info_2);
6842 if (*needed > offered)
6843 return WERR_INSUFFICIENT_BUFFER;
6845 return WERR_OK;
6848 /****************************************************************************
6849 ****************************************************************************/
6851 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6853 POLICY_HND *handle = &q_u->handle;
6854 uint32 jobid = q_u->jobid;
6855 uint32 level = q_u->level;
6856 NEW_BUFFER *buffer = NULL;
6857 uint32 offered = q_u->offered;
6858 uint32 *needed = &r_u->needed;
6860 int snum;
6861 int count;
6862 print_queue_struct *queue=NULL;
6863 print_status_struct prt_status;
6865 /* that's an [in out] buffer */
6866 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6867 buffer = r_u->buffer;
6869 DEBUG(5,("spoolss_getjob\n"));
6871 *needed=0;
6873 if (!get_printer_snum(p, handle, &snum))
6874 return WERR_BADFID;
6876 count = print_queue_status(snum, &queue, &prt_status);
6878 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6879 count, prt_status.status, prt_status.message));
6881 switch (level) {
6882 case 1:
6883 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6884 case 2:
6885 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6886 default:
6887 SAFE_FREE(queue);
6888 return WERR_UNKNOWN_LEVEL;
6892 /********************************************************************
6893 * spoolss_getprinterdataex
6894 ********************************************************************/
6896 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
6898 POLICY_HND *handle = &q_u->handle;
6899 uint32 in_size = q_u->size;
6900 uint32 *type = &r_u->type;
6901 uint32 *out_size = &r_u->size;
6902 uint8 **data = &r_u->data;
6903 uint32 *needed = &r_u->needed;
6905 fstring key, value;
6906 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6907 BOOL found = False;
6909 DEBUG(4,("_spoolss_getprinterdataex\n"));
6911 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
6912 unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
6914 /* in case of problem, return some default values */
6915 *needed=0;
6916 *type=0;
6917 *out_size=0;
6920 if (!Printer) {
6921 if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
6922 return WERR_NOMEM;
6923 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6924 return WERR_BADFID;
6928 /* Is the handle to a printer or to the server? */
6930 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6932 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
6933 return WERR_INVALID_PARAM;
6935 else
6938 * From MSDN documentation of GetPrinterDataEx: pass request
6939 * to GetPrinterData if key is "PrinterDriverData". This is
6940 * the only key we really support. Other keys to implement:
6941 * (a) DsDriver
6942 * (b) DsSpooler
6943 * (c) PnPData
6946 if (strcmp(key, "PrinterDriverData") != 0)
6947 return WERR_INVALID_PARAM;
6949 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
6950 found = getprinterdata_printer(p, p->mem_ctx, handle, value,
6951 type, data, needed, in_size);
6955 if (!found) {
6956 DEBUG(5, ("value not found, allocating %d\n", *out_size));
6958 /* reply this param doesn't exist */
6959 if (*out_size) {
6960 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
6961 return WERR_NOMEM;
6962 } else {
6963 *data = NULL;
6966 return WERR_INVALID_PARAM;
6969 if (*needed > *out_size)
6970 return WERR_MORE_DATA;
6971 else
6972 return WERR_OK;
6975 /********************************************************************
6976 * spoolss_setprinterdata
6977 ********************************************************************/
6979 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
6981 SPOOL_Q_SETPRINTERDATA q_u_local;
6982 SPOOL_R_SETPRINTERDATA r_u_local;
6983 fstring key;
6985 DEBUG(4,("_spoolss_setprinterdataex\n"));
6987 /* From MSDN documentation of SetPrinterDataEx: pass request to
6988 SetPrinterData if key is "PrinterDriverData" */
6990 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
6992 if (strcmp(key, "PrinterDriverData") == 0)
6993 return WERR_INVALID_PARAM;
6995 ZERO_STRUCT(q_u_local);
6996 ZERO_STRUCT(r_u_local);
6998 /* make a copy to call _spoolss_setprinterdata() */
7000 memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
7001 copy_unistr2(&q_u_local.value, &q_u->value);
7002 q_u_local.type = q_u->type;
7003 q_u_local.max_len = q_u->max_len;
7004 q_u_local.data = q_u->data;
7005 q_u_local.real_len = q_u->real_len;
7006 q_u_local.numeric_data = q_u->numeric_data;
7008 return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
7011 /********************************************************************
7012 * spoolss_enumprinterkey
7013 ********************************************************************/
7015 /* constants for EnumPrinterKey() */
7016 #define ENUMERATED_KEY_SIZE 19
7018 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
7020 fstring key;
7021 uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
7022 char* ptr = NULL;
7023 int i;
7024 char *PrinterKey = "PrinterDriverData";
7026 DEBUG(4,("_spoolss_enumprinterkey\n"));
7028 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7031 * we only support enumating all keys (key == "")
7032 * Of course, the only key we support is the "PrinterDriverData"
7033 * key
7035 if (strlen(key) == 0)
7037 r_u->needed = ENUMERATED_KEY_SIZE *2;
7038 if (q_u->size < r_u->needed)
7039 return WERR_MORE_DATA;
7041 ptr = PrinterKey;
7042 for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
7044 enumkeys[i] = (uint16)(*ptr);
7045 ptr++;
7048 /* tag of with 2 '\0's */
7049 enumkeys[i++] = '\0';
7050 enumkeys[i] = '\0';
7052 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
7053 return WERR_BADFILE;
7055 return WERR_OK;
7058 /* The "PrinterDriverData" key should have no subkeys */
7059 if (strcmp(key, PrinterKey) == 0)
7061 r_u-> needed = 2;
7062 if (q_u->size < r_u->needed)
7063 return WERR_MORE_DATA;
7064 enumkeys[0] = 0x0;
7065 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
7066 return WERR_BADFILE;
7068 return WERR_OK;
7072 /* The return value for an unknown key is documented in MSDN
7073 EnumPrinterKey description */
7074 return WERR_BADFILE;
7077 /********************************************************************
7078 * spoolss_enumprinterdataex
7079 ********************************************************************/
7081 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
7083 POLICY_HND *handle = &q_u->handle;
7084 uint32 in_size = q_u->size;
7085 uint32 num_entries,
7086 needed;
7087 NT_PRINTER_INFO_LEVEL *printer = NULL;
7088 PRINTER_ENUM_VALUES *enum_values = NULL;
7089 fstring key, value;
7090 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7091 int snum;
7092 uint32 param_index,
7093 data_len,
7094 type;
7095 WERROR result;
7096 uint8 *data=NULL;
7099 DEBUG(4,("_spoolss_enumprinterdataex\n"));
7101 if (!Printer) {
7102 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
7103 return WERR_BADFID;
7108 * The only key we support is "PrinterDriverData". This should return
7109 > an array of all the key/value pairs returned by EnumPrinterDataSee
7110 * _spoolss_getprinterdataex() for details --jerry
7113 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
7114 if (strcmp(key, "PrinterDriverData") != 0)
7116 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
7117 return WERR_INVALID_PARAM;
7121 if (!get_printer_snum(p,handle, &snum))
7122 return WERR_BADFID;
7124 ZERO_STRUCT(printer);
7125 result = get_a_printer(&printer, 2, lp_servicename(snum));
7126 if (!W_ERROR_IS_OK(result))
7127 return result;
7131 * loop through all params and build the array to pass
7132 * back to the client
7134 result = WERR_OK;
7135 param_index = 0;
7136 needed = 0;
7137 num_entries = 0;
7139 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
7141 PRINTER_ENUM_VALUES *ptr;
7142 uint32 add_len = 0;
7144 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
7146 if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
7148 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7149 result = WERR_NOMEM;
7150 goto done;
7152 enum_values = ptr;
7154 /* copy the data */
7155 init_unistr(&enum_values[num_entries].valuename, value);
7156 enum_values[num_entries].value_len = (strlen(value)+1) * 2;
7157 enum_values[num_entries].type = type;
7160 * NULL terminate REG_SZ
7161 * FIXME!!! We should not be correctly problems in the way
7162 * we store PrinterData here. Need to investogate
7163 * SetPrinterData[Ex] --jerry
7166 if (type == REG_SZ) {
7167 /* fix alignment if the string was stored
7168 in a bizarre fashion */
7169 if ((data_len % 2) == 0)
7170 add_len = 2;
7171 else
7172 add_len = data_len % 2;
7175 if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
7176 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7177 result = WERR_NOMEM;
7178 goto done;
7180 memcpy(enum_values[num_entries].data, data, data_len);
7181 enum_values[num_entries].data_len = data_len + add_len;
7183 /* keep track of the size of the array in bytes */
7185 needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
7187 num_entries++;
7188 param_index++;
7191 r_u->needed = needed;
7192 r_u->returned = num_entries;
7194 if (needed > in_size) {
7195 result = WERR_MORE_DATA;
7196 goto done;
7199 /* copy data into the reply */
7201 r_u->ctr.size = r_u->needed;
7202 r_u->ctr.size_of_array = r_u->returned;
7203 r_u->ctr.values = enum_values;
7207 done:
7208 free_a_printer(&printer, 2);
7210 return result;
7213 /****************************************************************************
7214 ****************************************************************************/
7216 /* Disabled because it doesn't fix the bug I am looking at but it would be
7217 a shame to throw away the code. -tpot */
7219 #if 0
7221 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
7223 init_unistr(&info->name, name);
7226 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
7227 UNISTR2 *environment,
7228 NEW_BUFFER *buffer,
7229 uint32 offered,
7230 uint32 *needed)
7232 pstring path;
7233 pstring long_archi;
7234 pstring short_archi;
7235 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
7237 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
7239 if (get_short_archi(short_archi, long_archi)==False)
7240 return WERR_INVALID_ENVIRONMENT;
7242 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
7243 return WERR_NOMEM;
7245 /* Not sure what to return here - are UNC names valid here?.
7246 Windows returns the string: C:\WINNT\System32\spool\PRTPROCS\W32X86
7247 which is pretty bogus for a RPC. */
7249 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7251 DEBUG(4,("print processor directory: [%s]\n", path));
7253 fill_printprocessordirectory_1(info, path);
7255 *needed += spoolss_size_printprocessordirectory_info_1(info);
7257 if (!alloc_buffer_size(buffer, *needed)) {
7258 safe_free(info);
7259 return WERR_INSUFFICIENT_BUFFER;
7262 smb_io_printprocessordirectory_1("", buffer, info, 0);
7264 safe_free(info);
7266 if (*needed > offered)
7267 return WERR_INSUFFICIENT_BUFFER;
7268 else
7269 return WERR_OK;
7272 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
7274 uint32 level = q_u->level;
7275 NEW_BUFFER *buffer = NULL;
7276 uint32 offered = q_u->offered;
7277 uint32 *needed = &r_u->needed;
7279 /* that's an [in out] buffer */
7280 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7281 buffer = r_u->buffer;
7283 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7285 *needed=0;
7287 switch(level) {
7288 case 1:
7289 return getprintprocessordirectory_level_1
7290 (&q_u->name, &q_u->environment, buffer, offered, needed);
7291 default:
7292 return WERR_UNKNOWN_LEVEL;
7295 return WERR_ACCESS_DENIED;
7298 #endif