Commit just a little more infrastructure for HAVE_GETDIRENTRIES
[Samba/gebeck_regimport.git] / source3 / rpc_server / srv_spoolss_nt.c
blobb44910883c6fb6bbcbb8793a2e5c9b4d940e6cd6
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2002,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
36 #endif
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
40 #define PRINTER_HANDLE_IS_PRINTER 0
41 #define PRINTER_HANDLE_IS_PRINTSERVER 1
43 /* Table to map the driver version */
44 /* to OS */
45 static const char * drv_ver_to_os[] = {
46 "WIN9X", /* driver version/cversion 0 */
47 "", /* unused ? */
48 "WINNT", /* driver version/cversion 2 */
49 "WIN2K", /* driver version/cversion 3 */
52 struct table_node {
53 const char *long_archi;
54 const char *short_archi;
55 int version;
59 /* structure to store the printer handles */
60 /* and a reference to what it's pointing to */
61 /* and the notify info asked about */
62 /* that's the central struct */
63 typedef struct _Printer{
64 struct _Printer *prev, *next;
65 BOOL document_started;
66 BOOL page_started;
67 uint32 jobid; /* jobid in printing backend */
68 BOOL printer_type;
69 union {
70 fstring handlename;
71 fstring printerservername;
72 } dev;
73 uint32 type;
74 uint32 access_granted;
75 struct {
76 uint32 flags;
77 uint32 options;
78 fstring localmachine;
79 uint32 printerlocal;
80 SPOOL_NOTIFY_OPTION *option;
81 POLICY_HND client_hnd;
82 BOOL client_connected;
83 uint32 change;
84 /* are we in a FindNextPrinterChangeNotify() call? */
85 BOOL fnpcn;
86 } notify;
87 struct {
88 fstring machine;
89 fstring user;
90 } client;
92 /* devmode sent in the OpenPrinter() call */
93 NT_DEVICEMODE *nt_devmode;
96 } Printer_entry;
98 static Printer_entry *printers_list;
100 typedef struct _counter_printer_0 {
101 ubi_dlNode Next;
102 ubi_dlNode Prev;
104 int snum;
105 uint32 counter;
106 } counter_printer_0;
108 static ubi_dlList counter_list;
110 static struct cli_state notify_cli; /* print notify back-channel */
111 static uint32 smb_connections=0;
114 /* in printing/nt_printing.c */
116 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
118 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
119 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
121 /* translate between internal status numbers and NT status numbers */
122 static int nt_printj_status(int v)
124 switch (v) {
125 case LPQ_QUEUED:
126 return 0;
127 case LPQ_PAUSED:
128 return JOB_STATUS_PAUSED;
129 case LPQ_SPOOLING:
130 return JOB_STATUS_SPOOLING;
131 case LPQ_PRINTING:
132 return JOB_STATUS_PRINTING;
133 case LPQ_ERROR:
134 return JOB_STATUS_ERROR;
135 case LPQ_DELETING:
136 return JOB_STATUS_DELETING;
137 case LPQ_OFFLINE:
138 return JOB_STATUS_OFFLINE;
139 case LPQ_PAPEROUT:
140 return JOB_STATUS_PAPEROUT;
141 case LPQ_PRINTED:
142 return JOB_STATUS_PRINTED;
143 case LPQ_DELETED:
144 return JOB_STATUS_DELETED;
145 case LPQ_BLOCKED:
146 return JOB_STATUS_BLOCKED;
147 case LPQ_USER_INTERVENTION:
148 return JOB_STATUS_USER_INTERVENTION;
150 return 0;
153 static int nt_printq_status(int v)
155 switch (v) {
156 case LPQ_PAUSED:
157 return PRINTER_STATUS_PAUSED;
158 case LPQ_QUEUED:
159 case LPQ_SPOOLING:
160 case LPQ_PRINTING:
161 return 0;
163 return 0;
166 /****************************************************************************
167 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
168 ****************************************************************************/
170 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
172 if (*pp == NULL)
173 return;
175 SAFE_FREE((*pp)->ctr.type);
176 SAFE_FREE(*pp);
179 /***************************************************************************
180 Disconnect from the client
181 ****************************************************************************/
183 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
185 WERROR result;
188 * Tell the specific printing tdb we no longer want messages for this printer
189 * by deregistering our PID.
192 if (!print_notify_deregister_pid(snum))
193 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
195 /* weird if the test succeds !!! */
196 if (smb_connections==0) {
197 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
198 return;
201 result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
203 if (!W_ERROR_IS_OK(result))
204 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
205 dos_errstr(result)));
207 /* if it's the last connection, deconnect the IPC$ share */
208 if (smb_connections==1) {
209 cli_nt_session_close(&notify_cli);
210 cli_ulogoff(&notify_cli);
211 cli_shutdown(&notify_cli);
212 message_deregister(MSG_PRINTER_NOTIFY2);
214 /* Tell the connections db we're no longer interested in
215 * printer notify messages. */
217 register_message_flags( False, FLAG_MSG_PRINTING );
220 smb_connections--;
223 /****************************************************************************
224 Functions to free a printer entry datastruct.
225 ****************************************************************************/
227 static void free_printer_entry(void *ptr)
229 Printer_entry *Printer = (Printer_entry *)ptr;
231 if (Printer->notify.client_connected==True) {
232 int snum = -1;
234 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
235 snum = -1;
236 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
237 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
238 snum = print_queue_snum(Printer->dev.handlename);
239 if (snum != -1)
240 srv_spoolss_replycloseprinter(snum,
241 &Printer->notify.client_hnd);
245 Printer->notify.flags=0;
246 Printer->notify.options=0;
247 Printer->notify.localmachine[0]='\0';
248 Printer->notify.printerlocal=0;
249 free_spool_notify_option(&Printer->notify.option);
250 Printer->notify.option=NULL;
251 Printer->notify.client_connected=False;
253 free_nt_devicemode( &Printer->nt_devmode );
255 /* Remove from the internal list. */
256 DLIST_REMOVE(printers_list, Printer);
258 SAFE_FREE(Printer);
261 /****************************************************************************
262 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
263 ****************************************************************************/
265 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
267 SPOOL_NOTIFY_OPTION *new_sp = NULL;
269 if (!sp)
270 return NULL;
272 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
273 if (!new_sp)
274 return NULL;
276 *new_sp = *sp;
278 if (sp->ctr.count) {
279 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
281 if (!new_sp->ctr.type) {
282 SAFE_FREE(new_sp);
283 return NULL;
287 return new_sp;
290 /****************************************************************************
291 find printer index by handle
292 ****************************************************************************/
294 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
296 Printer_entry *find_printer = NULL;
298 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
299 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
300 return NULL;
303 return find_printer;
306 /****************************************************************************
307 Close printer index by handle.
308 ****************************************************************************/
310 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
312 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
314 if (!Printer) {
315 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
316 return False;
319 close_policy_hnd(p, hnd);
321 return True;
324 /****************************************************************************
325 Delete a printer given a handle.
326 ****************************************************************************/
328 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
330 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
332 if (!Printer) {
333 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
334 return WERR_BADFID;
338 * It turns out that Windows allows delete printer on a handle
339 * opened by an admin user, then used on a pipe handle created
340 * by an anonymous user..... but they're working on security.... riiight !
341 * JRA.
344 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
345 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
346 return WERR_ACCESS_DENIED;
349 #if 0
350 /* Check calling user has permission to delete printer. Note that
351 since we set the snum parameter to -1 only administrators can
352 delete the printer. This stops people with the Full Control
353 permission from deleting the printer. */
355 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
356 DEBUG(3, ("printer delete denied by security descriptor\n"));
357 return WERR_ACCESS_DENIED;
359 #endif
361 if (del_a_printer(Printer->dev.handlename) != 0) {
362 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
363 return WERR_BADFID;
366 if (*lp_deleteprinter_cmd()) {
368 char *cmd = lp_deleteprinter_cmd();
369 pstring command;
370 int ret;
371 int i;
373 /* Printer->dev.handlename equals portname equals sharename */
374 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
375 Printer->dev.handlename);
377 DEBUG(10,("Running [%s]\n", command));
378 ret = smbrun(command, NULL);
379 if (ret != 0) {
380 return WERR_BADFID; /* What to return here? */
382 DEBUGADD(10,("returned [%d]\n", ret));
384 /* Send SIGHUP to process group... is there a better way? */
385 kill(0, SIGHUP);
387 /* go ahead and re-read the services immediately */
388 reload_services( False );
390 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
391 return WERR_ACCESS_DENIED;
394 return WERR_OK;
397 /****************************************************************************
398 Return the snum of a printer corresponding to an handle.
399 ****************************************************************************/
401 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
403 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
405 if (!Printer) {
406 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
407 return False;
410 switch (Printer->printer_type) {
411 case PRINTER_HANDLE_IS_PRINTER:
412 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
413 *number = print_queue_snum(Printer->dev.handlename);
414 return (*number != -1);
415 case PRINTER_HANDLE_IS_PRINTSERVER:
416 return False;
417 default:
418 return False;
422 /****************************************************************************
423 Set printer handle type.
424 Check if it's \\server or \\server\printer
425 ****************************************************************************/
427 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
429 DEBUG(3,("Setting printer type=%s\n", handlename));
431 if ( strlen(handlename) < 3 ) {
432 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
433 return False;
436 /* it's a print server */
437 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
438 DEBUGADD(4,("Printer is a print server\n"));
439 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
441 /* it's a printer */
442 else {
443 DEBUGADD(4,("Printer is a printer\n"));
444 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
447 return True;
450 /****************************************************************************
451 Set printer handle name.
452 ****************************************************************************/
454 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
456 int snum;
457 int n_services=lp_numservices();
458 char *aprinter;
459 fstring sname;
460 BOOL found=False;
462 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
464 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
465 ZERO_STRUCT(Printer->dev.printerservername);
466 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
467 return True;
470 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
471 return False;
473 if (*handlename=='\\') {
474 aprinter=strchr_m(handlename+2, '\\');
475 aprinter++;
477 else {
478 aprinter=handlename;
481 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
484 * The original code allowed smbd to store a printer name that
485 * was different from the share name. This is not possible
486 * anymore, so I've simplified this loop greatly. Here
487 * we are just verifying that the printer name is a valid
488 * printer service defined in smb.conf
489 * --jerry [Fri Feb 15 11:17:46 CST 2002]
492 for (snum=0; snum<n_services; snum++) {
494 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
495 continue;
497 fstrcpy(sname, lp_servicename(snum));
499 DEBUGADD(5,("share:%s\n",sname));
501 if (! StrCaseCmp(sname, aprinter)) {
502 found = True;
503 break;
509 if (!found) {
510 DEBUGADD(4,("Printer not found\n"));
511 return False;
514 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
516 ZERO_STRUCT(Printer->dev.handlename);
517 fstrcpy(Printer->dev.handlename, sname);
519 return True;
522 /****************************************************************************
523 Find first available printer slot. creates a printer handle for you.
524 ****************************************************************************/
526 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
528 Printer_entry *new_printer;
530 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
532 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
533 return False;
535 ZERO_STRUCTP(new_printer);
537 new_printer->notify.option=NULL;
539 /* Add to the internal list. */
540 DLIST_ADD(printers_list, new_printer);
542 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
543 SAFE_FREE(new_printer);
544 return False;
547 if (!set_printer_hnd_printertype(new_printer, name)) {
548 close_printer_handle(p, hnd);
549 return False;
552 if (!set_printer_hnd_name(new_printer, name)) {
553 close_printer_handle(p, hnd);
554 return False;
557 new_printer->access_granted = access_granted;
559 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
561 return True;
564 /****************************************************************************
565 Allocate more memory for a BUFFER.
566 ****************************************************************************/
568 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
570 prs_struct *ps;
571 uint32 extra_space;
572 uint32 old_offset;
574 ps= &buffer->prs;
576 /* damn, I'm doing the reverse operation of prs_grow() :) */
577 if (buffer_size < prs_data_size(ps))
578 extra_space=0;
579 else
580 extra_space = buffer_size - prs_data_size(ps);
583 * save the offset and move to the end of the buffer
584 * prs_grow() checks the extra_space against the offset
586 old_offset=prs_offset(ps);
587 prs_set_offset(ps, prs_data_size(ps));
589 if (!prs_grow(ps, extra_space))
590 return False;
592 prs_set_offset(ps, old_offset);
594 buffer->string_at_end=prs_data_size(ps);
596 return True;
599 /***************************************************************************
600 check to see if the client motify handle is monitoring the notification
601 given by (notify_type, notify_field).
602 **************************************************************************/
604 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
605 uint16 notify_field)
607 return True;
610 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
611 uint16 notify_field)
613 SPOOL_NOTIFY_OPTION *option = p->notify.option;
614 uint32 i, j;
617 * Flags should always be zero when the change notify
618 * is registered by the cliebnt's spooler. A user Win32 app
619 * might use the flags though instead of the NOTIFY_OPTION_INFO
620 * --jerry
623 if (p->notify.flags)
624 return is_monitoring_event_flags(
625 p->notify.flags, notify_type, notify_field);
627 for (i = 0; i < option->count; i++) {
629 /* Check match for notify_type */
631 if (option->ctr.type[i].type != notify_type)
632 continue;
634 /* Check match for field */
636 for (j = 0; j < option->ctr.type[i].count; j++) {
637 if (option->ctr.type[i].fields[j] == notify_field) {
638 return True;
643 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
644 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
645 p->dev.handlename : p->dev.printerservername,
646 notify_type, notify_field));
648 return False;
651 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
653 static void notify_one_value(struct spoolss_notify_msg *msg,
654 SPOOL_NOTIFY_INFO_DATA *data,
655 TALLOC_CTX *mem_ctx)
657 data->notify_data.value[0] = msg->notify.value[0];
658 data->notify_data.value[1] = 0;
661 static void notify_string(struct spoolss_notify_msg *msg,
662 SPOOL_NOTIFY_INFO_DATA *data,
663 TALLOC_CTX *mem_ctx)
665 UNISTR2 unistr;
667 /* The length of the message includes the trailing \0 */
669 init_unistr2(&unistr, msg->notify.data, msg->len);
671 data->notify_data.data.length = msg->len * 2;
672 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
674 if (!data->notify_data.data.string) {
675 data->notify_data.data.length = 0;
676 return;
679 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
682 static void notify_system_time(struct spoolss_notify_msg *msg,
683 SPOOL_NOTIFY_INFO_DATA *data,
684 TALLOC_CTX *mem_ctx)
686 SYSTEMTIME systime;
687 prs_struct ps;
689 if (msg->len != sizeof(time_t)) {
690 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
691 msg->len));
692 return;
695 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
696 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
697 return;
700 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
701 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
702 return;
705 if (!spoolss_io_system_time("", &ps, 0, &systime))
706 return;
708 data->notify_data.data.length = prs_offset(&ps);
709 data->notify_data.data.string =
710 talloc(mem_ctx, prs_offset(&ps));
712 memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
714 prs_mem_free(&ps);
717 struct notify2_message_table {
718 const char *name;
719 void (*fn)(struct spoolss_notify_msg *msg,
720 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
723 static struct notify2_message_table printer_notify_table[] = {
724 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
725 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
726 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
727 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
728 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
729 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
730 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
731 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
732 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
733 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
734 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
735 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
736 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
737 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
738 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
739 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
740 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
741 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
742 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
745 static struct notify2_message_table job_notify_table[] = {
746 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
747 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
748 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
749 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
750 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
751 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
752 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
753 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
754 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
755 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
756 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
757 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
758 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
759 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
760 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
761 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
762 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
763 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
764 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
765 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
766 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
767 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
768 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
769 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
773 /***********************************************************************
774 Allocate talloc context for container object
775 **********************************************************************/
777 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
779 if ( !ctr )
780 return;
782 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
784 return;
787 /***********************************************************************
788 release all allocated memory and zero out structure
789 **********************************************************************/
791 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
793 if ( !ctr )
794 return;
796 if ( ctr->ctx )
797 talloc_destroy(ctr->ctx);
799 ZERO_STRUCTP(ctr);
801 return;
804 /***********************************************************************
805 **********************************************************************/
807 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
809 if ( !ctr )
810 return NULL;
812 return ctr->ctx;
815 /***********************************************************************
816 **********************************************************************/
818 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
820 if ( !ctr || !ctr->msg_groups )
821 return NULL;
823 if ( idx >= ctr->num_groups )
824 return NULL;
826 return &ctr->msg_groups[idx];
830 /***********************************************************************
831 How many groups of change messages do we have ?
832 **********************************************************************/
834 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
836 if ( !ctr )
837 return 0;
839 return ctr->num_groups;
842 /***********************************************************************
843 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
844 **********************************************************************/
846 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
848 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
849 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
850 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
851 int i, new_slot;
853 if ( !ctr || !msg )
854 return 0;
856 /* loop over all groups looking for a matching printer name */
858 for ( i=0; i<ctr->num_groups; i++ ) {
859 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
860 break;
863 /* add a new group? */
865 if ( i == ctr->num_groups )
867 ctr->num_groups++;
869 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
870 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
871 return 0;
873 ctr->msg_groups = groups;
875 /* clear the new entry and set the printer name */
877 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
878 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
881 /* add the change messages; 'i' is the correct index now regardless */
883 msg_grp = &ctr->msg_groups[i];
885 msg_grp->num_msgs++;
887 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
888 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
889 return 0;
891 msg_grp->msgs = msg_list;
893 new_slot = msg_grp->num_msgs-1;
894 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
896 /* need to allocate own copy of data */
898 if ( msg->len != 0 )
899 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
901 return ctr->num_groups;
904 /***********************************************************************
905 Send a change notication message on all handles which have a call
906 back registered
907 **********************************************************************/
909 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
911 Printer_entry *p;
912 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
913 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
914 SPOOLSS_NOTIFY_MSG *messages;
917 if ( !msg_group ) {
918 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
919 return;
922 messages = msg_group->msgs;
924 if ( !messages ) {
925 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
926 return;
929 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
931 /* loop over all printers */
933 for (p = printers_list; p; p = p->next)
935 SPOOL_NOTIFY_INFO_DATA *data;
936 uint32 data_len = 0;
937 uint32 id;
938 int i, event_index;
940 /* Is there notification on this handle? */
942 if ( !p->notify.client_connected )
943 continue;
945 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
947 /* For this printer? Print servers always receive
948 notifications. */
950 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
951 ( !strequal(msg_group->printername, p->dev.handlename) ) )
952 continue;
954 DEBUG(10,("Our printer\n"));
956 /* allocate the max entries possible */
958 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
959 ZERO_STRUCTP(data);
961 event_index = 0;
963 /* build the array of change notifications */
965 for ( i=0; i<msg_group->num_msgs; i++ )
967 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
969 /* Are we monitoring this event? */
971 if (!is_monitoring_event(p, msg->type, msg->field))
972 continue;
975 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
976 msg->type, msg->field, p->dev.handlename));
979 * if the is a printer notification handle and not a job notification
980 * type, then set the id to 0. Other wise just use what was specified
981 * in the message.
983 * When registering change notification on a print server handle
984 * we always need to send back the id (snum) matching the printer
985 * for which the change took place. For change notify registered
986 * on a printer handle, this does not matter and the id should be 0.
988 * --jerry
991 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
992 id = 0;
993 else
994 id = msg->id;
997 /* Convert unix jobid to smb jobid */
999 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID)
1001 id = sysjob_to_jobid(msg->id);
1003 if (id == -1) {
1004 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1005 goto done;
1009 construct_info_data( &data[data_len], msg->type, msg->field, id );
1011 switch(msg->type) {
1012 case PRINTER_NOTIFY_TYPE:
1013 if ( printer_notify_table[msg->field].fn )
1014 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1015 break;
1017 case JOB_NOTIFY_TYPE:
1018 if ( job_notify_table[msg->field].fn )
1019 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1020 break;
1022 default:
1023 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1024 goto done;
1027 data_len++;
1030 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1031 data_len, data, p->notify.change, 0 );
1034 done:
1035 DEBUG(8,("send_notify2_changes: Exit...\n"));
1036 return;
1039 /***********************************************************************
1040 **********************************************************************/
1042 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
1045 int offset = 0;
1047 /* Unpack message */
1049 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1050 msg->printer);
1052 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
1053 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1055 if (msg->len == 0)
1056 tdb_unpack((char *)buf + offset, len - offset, "dd",
1057 &msg->notify.value[0], &msg->notify.value[1]);
1058 else
1059 tdb_unpack((char *)buf + offset, len - offset, "B",
1060 &msg->len, &msg->notify.data);
1062 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1063 msg->type, msg->field, msg->flags));
1065 if (msg->len == 0)
1066 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1067 msg->notify.value[1]));
1068 else
1069 dump_data(3, msg->notify.data, msg->len);
1071 return True;
1074 /********************************************************************
1075 Receive a notify2 message list
1076 ********************************************************************/
1078 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1080 size_t msg_count, i;
1081 char *buf = (char *)msg;
1082 char *msg_ptr;
1083 size_t msg_len;
1084 SPOOLSS_NOTIFY_MSG notify;
1085 SPOOLSS_NOTIFY_MSG_CTR messages;
1086 int num_groups;
1088 if (len < 4) {
1089 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1090 return;
1093 msg_count = IVAL(buf, 0);
1094 msg_ptr = buf + 4;
1096 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1098 if (msg_count == 0) {
1099 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1100 return;
1103 /* initialize the container */
1105 ZERO_STRUCT( messages );
1106 notify_msg_ctr_init( &messages );
1109 * build message groups for each printer identified
1110 * in a change_notify msg. Remember that a PCN message
1111 * includes the handle returned for the srv_spoolss_replyopenprinter()
1112 * call. Therefore messages are grouped according to printer handle.
1115 for ( i=0; i<msg_count; i++ )
1117 if (msg_ptr + 4 - buf > len) {
1118 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1119 return;
1122 msg_len = IVAL(msg_ptr,0);
1123 msg_ptr += 4;
1125 if (msg_ptr + msg_len - buf > len) {
1126 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1127 return;
1130 /* unpack messages */
1132 ZERO_STRUCT( notify );
1133 notify2_unpack_msg( &notify, msg_ptr, msg_len );
1134 msg_ptr += msg_len;
1136 /* add to correct list in container */
1138 notify_msg_ctr_addmsg( &messages, &notify );
1140 /* free memory that might have been allocated by notify2_unpack_msg() */
1142 if ( notify.len != 0 )
1143 SAFE_FREE( notify.notify.data );
1146 /* process each group of messages */
1148 num_groups = notify_msg_ctr_numgroups( &messages );
1149 for ( i=0; i<num_groups; i++ )
1150 send_notify2_changes( &messages, i );
1153 /* cleanup */
1155 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1157 notify_msg_ctr_destroy( &messages );
1159 return;
1162 /********************************************************************
1163 Send a message to ourself about new driver being installed
1164 so we can upgrade the information for each printer bound to this
1165 driver
1166 ********************************************************************/
1168 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1170 int len = strlen(drivername);
1172 if (!len)
1173 return False;
1175 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1176 drivername));
1178 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1180 return True;
1183 /**********************************************************************
1184 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1185 over all printers, upgrading ones as neessary
1186 **********************************************************************/
1188 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1190 fstring drivername;
1191 int snum;
1192 int n_services = lp_numservices();
1194 len = MIN(len,sizeof(drivername)-1);
1195 strncpy(drivername, buf, len);
1197 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1199 /* Iterate the printer list */
1201 for (snum=0; snum<n_services; snum++)
1203 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1205 WERROR result;
1206 NT_PRINTER_INFO_LEVEL *printer = NULL;
1208 result = get_a_printer(&printer, 2, lp_servicename(snum));
1209 if (!W_ERROR_IS_OK(result))
1210 continue;
1212 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1214 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1216 /* all we care about currently is the change_id */
1218 result = mod_a_printer(*printer, 2);
1219 if (!W_ERROR_IS_OK(result)) {
1220 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1221 dos_errstr(result)));
1225 free_a_printer(&printer, 2);
1229 /* all done */
1232 /********************************************************************
1233 Update the cahce for all printq's with a registered client
1234 connection
1235 ********************************************************************/
1237 void update_monitored_printq_cache( void )
1239 Printer_entry *printer = printers_list;
1240 int snum;
1242 /* loop through all printers and update the cache where
1243 client_connected == True */
1244 while ( printer )
1246 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1247 && printer->notify.client_connected )
1249 snum = print_queue_snum(printer->dev.handlename);
1250 print_queue_status( snum, NULL, NULL );
1253 printer = printer->next;
1256 return;
1258 /********************************************************************
1259 Send a message to ourself about new driver being installed
1260 so we can upgrade the information for each printer bound to this
1261 driver
1262 ********************************************************************/
1264 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1266 int len = strlen(drivername);
1268 if (!len)
1269 return False;
1271 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1272 drivername));
1274 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1276 return True;
1279 /**********************************************************************
1280 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1281 over all printers, resetting printer data as neessary
1282 **********************************************************************/
1284 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1286 fstring drivername;
1287 int snum;
1288 int n_services = lp_numservices();
1290 len = MIN( len, sizeof(drivername)-1 );
1291 strncpy( drivername, buf, len );
1293 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1295 /* Iterate the printer list */
1297 for ( snum=0; snum<n_services; snum++ )
1299 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1301 WERROR result;
1302 NT_PRINTER_INFO_LEVEL *printer = NULL;
1304 result = get_a_printer( &printer, 2, lp_servicename(snum) );
1305 if ( !W_ERROR_IS_OK(result) )
1306 continue;
1309 * if the printer is bound to the driver,
1310 * then reset to the new driver initdata
1313 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1315 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1317 if ( !set_driver_init(printer, 2) ) {
1318 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1319 printer->info_2->printername, printer->info_2->drivername));
1322 result = mod_a_printer( *printer, 2 );
1323 if ( !W_ERROR_IS_OK(result) ) {
1324 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1325 get_dos_error_msg(result)));
1329 free_a_printer( &printer, 2 );
1333 /* all done */
1335 return;
1338 /********************************************************************
1339 Copy routines used by convert_to_openprinterex()
1340 *******************************************************************/
1342 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1344 DEVICEMODE *d;
1345 int len;
1347 if (!devmode)
1348 return NULL;
1350 DEBUG (8,("dup_devmode\n"));
1352 /* bulk copy first */
1354 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1355 if (!d)
1356 return NULL;
1358 /* dup the pointer members separately */
1360 len = unistrlen(devmode->devicename.buffer);
1361 if (len != -1) {
1362 d->devicename.buffer = talloc(ctx, len*2);
1363 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1364 return NULL;
1368 len = unistrlen(devmode->formname.buffer);
1369 if (len != -1) {
1370 d->devicename.buffer = talloc(ctx, len*2);
1371 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1372 return NULL;
1375 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1377 return d;
1380 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1382 if (!new_ctr || !ctr)
1383 return;
1385 DEBUG(8,("copy_devmode_ctr\n"));
1387 new_ctr->size = ctr->size;
1388 new_ctr->devmode_ptr = ctr->devmode_ptr;
1390 if(ctr->devmode_ptr)
1391 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1394 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1396 if (!new_def || !def)
1397 return;
1399 DEBUG(8,("copy_printer_defaults\n"));
1401 new_def->datatype_ptr = def->datatype_ptr;
1403 if (def->datatype_ptr)
1404 copy_unistr2(&new_def->datatype, &def->datatype);
1406 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1408 new_def->access_required = def->access_required;
1411 /********************************************************************
1412 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1413 * SPOOL_Q_OPEN_PRINTER_EX structure
1414 ********************************************************************/
1416 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1418 if (!q_u_ex || !q_u)
1419 return;
1421 DEBUG(8,("convert_to_openprinterex\n"));
1423 q_u_ex->printername_ptr = q_u->printername_ptr;
1425 if (q_u->printername_ptr)
1426 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1428 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1431 /********************************************************************
1432 * spoolss_open_printer
1434 * called from the spoolss dispatcher
1435 ********************************************************************/
1437 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1439 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1440 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1442 if (!q_u || !r_u)
1443 return WERR_NOMEM;
1445 ZERO_STRUCT(q_u_ex);
1446 ZERO_STRUCT(r_u_ex);
1448 /* convert the OpenPrinter() call to OpenPrinterEx() */
1450 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1452 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1454 /* convert back to OpenPrinter() */
1456 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1458 return r_u->status;
1461 /********************************************************************
1462 * spoolss_open_printer
1464 * If the openprinterex rpc call contains a devmode,
1465 * it's a per-user one. This per-user devmode is derivated
1466 * from the global devmode. Openprinterex() contains a per-user
1467 * devmode for when you do EMF printing and spooling.
1468 * In the EMF case, the NT workstation is only doing half the job
1469 * of rendering the page. The other half is done by running the printer
1470 * driver on the server.
1471 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1472 * The EMF file only contains what is to be printed on the page.
1473 * So in order for the server to know how to print, the NT client sends
1474 * a devicemode attached to the openprinterex call.
1475 * But this devicemode is short lived, it's only valid for the current print job.
1477 * If Samba would have supported EMF spooling, this devicemode would
1478 * have been attached to the handle, to sent it to the driver to correctly
1479 * rasterize the EMF file.
1481 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1482 * we just act as a pass-thru between windows and the printer.
1484 * In order to know that Samba supports only RAW spooling, NT has to call
1485 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1486 * and until NT sends a RAW job, we refuse it.
1488 * But to call getprinter() or startdoc(), you first need a valid handle,
1489 * and to get an handle you have to call openprintex(). Hence why you have
1490 * a devicemode in the openprinterex() call.
1493 * Differences between NT4 and NT 2000.
1494 * NT4:
1495 * ---
1496 * On NT4, you only have a global devicemode. This global devicemode can be changed
1497 * by the administrator (or by a user with enough privs). Everytime a user
1498 * wants to print, the devicemode is resetted to the default. In Word, everytime
1499 * you print, the printer's characteristics are always reset to the global devicemode.
1501 * NT 2000:
1502 * -------
1503 * In W2K, there is the notion of per-user devicemode. The first time you use
1504 * a printer, a per-user devicemode is build from the global devicemode.
1505 * If you change your per-user devicemode, it is saved in the registry, under the
1506 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1507 * printer preferences available.
1509 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1510 * on the General Tab of the printer properties windows.
1512 * To change the global devicemode: it's the "Printing Defaults..." button
1513 * on the Advanced Tab of the printer properties window.
1515 * JFM.
1516 ********************************************************************/
1518 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1520 UNISTR2 *printername = NULL;
1521 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1522 POLICY_HND *handle = &r_u->handle;
1524 fstring name;
1525 int snum;
1526 struct current_user user;
1527 Printer_entry *Printer=NULL;
1529 if (q_u->printername_ptr != 0)
1530 printername = &q_u->printername;
1532 if (printername == NULL)
1533 return WERR_INVALID_PRINTER_NAME;
1535 /* some sanity check because you can open a printer or a print server */
1536 /* aka: \\server\printer or \\server */
1537 unistr2_to_ascii(name, printername, sizeof(name)-1);
1539 DEBUGADD(3,("checking name: %s\n",name));
1541 if (!open_printer_hnd(p, handle, name, 0))
1542 return WERR_INVALID_PRINTER_NAME;
1544 Printer=find_printer_index_by_hnd(p, handle);
1545 if (!Printer) {
1546 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1547 Can't find printer handle we created for printer %s\n", name ));
1548 close_printer_handle(p,handle);
1549 return WERR_INVALID_PRINTER_NAME;
1552 get_current_user(&user, p);
1555 * First case: the user is opening the print server:
1557 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1558 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1560 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1561 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1562 * or if the user is listed in the smb.conf printer admin parameter.
1564 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1565 * client view printer folder, but does not show the MSAPW.
1567 * Note: this test needs code to check access rights here too. Jeremy
1568 * could you look at this?
1570 * Second case: the user is opening a printer:
1571 * NT doesn't let us connect to a printer if the connecting user
1572 * doesn't have print permission.
1575 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1577 /* Printserver handles use global struct... */
1579 snum = -1;
1581 /* Map standard access rights to object specific access rights */
1583 se_map_standard(&printer_default->access_required,
1584 &printserver_std_mapping);
1586 /* Deny any object specific bits that don't apply to print
1587 servers (i.e printer and job specific bits) */
1589 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1591 if (printer_default->access_required &
1592 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1593 DEBUG(3, ("access DENIED for non-printserver bits"));
1594 close_printer_handle(p, handle);
1595 return WERR_ACCESS_DENIED;
1598 /* Allow admin access */
1600 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1602 if (!lp_ms_add_printer_wizard()) {
1603 close_printer_handle(p, handle);
1604 return WERR_ACCESS_DENIED;
1607 /* if the user is not root and not a printer admin, then fail */
1609 if ( user.uid != 0
1610 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
1612 close_printer_handle(p, handle);
1613 return WERR_ACCESS_DENIED;
1616 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1618 else
1620 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1623 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1624 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1626 /* We fall through to return WERR_OK */
1629 else
1631 /* NT doesn't let us connect to a printer if the connecting user
1632 doesn't have print permission. */
1634 if (!get_printer_snum(p, handle, &snum))
1635 return WERR_BADFID;
1637 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1639 /* map an empty access mask to the minimum access mask */
1640 if (printer_default->access_required == 0x0)
1641 printer_default->access_required = PRINTER_ACCESS_USE;
1644 * If we are not serving the printer driver for this printer,
1645 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1646 * will keep NT clients happy --jerry
1649 if (lp_use_client_driver(snum)
1650 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1652 printer_default->access_required = PRINTER_ACCESS_USE;
1655 /* check smb.conf parameters and the the sec_desc */
1657 if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
1658 DEBUG(3, ("access DENIED for printer open\n"));
1659 close_printer_handle(p, handle);
1660 return WERR_ACCESS_DENIED;
1663 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1664 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1665 close_printer_handle(p, handle);
1666 return WERR_ACCESS_DENIED;
1669 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1670 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1671 else
1672 printer_default->access_required = PRINTER_ACCESS_USE;
1674 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1675 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1679 Printer->access_granted = printer_default->access_required;
1682 * If the client sent a devmode in the OpenPrinter() call, then
1683 * save it here in case we get a job submission on this handle
1686 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1687 && q_u->printer_default.devmode_cont.devmode_ptr )
1689 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1690 &Printer->nt_devmode );
1693 return WERR_OK;
1696 /****************************************************************************
1697 ****************************************************************************/
1699 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1700 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1702 BOOL ret = True;
1704 switch (level) {
1705 case 2:
1706 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1707 break;
1708 default:
1709 break;
1712 return ret;
1715 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1716 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1718 BOOL result = True;
1720 switch (level) {
1721 case 3:
1722 printer->info_3=NULL;
1723 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1724 result = False;
1725 break;
1726 case 6:
1727 printer->info_6=NULL;
1728 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1729 result = False;
1730 break;
1731 default:
1732 break;
1735 return result;
1738 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1739 NT_DEVICEMODE **pp_nt_devmode)
1741 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1744 * Ensure nt_devmode is a valid pointer
1745 * as we will be overwriting it.
1748 if (nt_devmode == NULL) {
1749 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1750 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1751 return False;
1754 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1755 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1757 nt_devmode->specversion=devmode->specversion;
1758 nt_devmode->driverversion=devmode->driverversion;
1759 nt_devmode->size=devmode->size;
1760 nt_devmode->fields=devmode->fields;
1761 nt_devmode->orientation=devmode->orientation;
1762 nt_devmode->papersize=devmode->papersize;
1763 nt_devmode->paperlength=devmode->paperlength;
1764 nt_devmode->paperwidth=devmode->paperwidth;
1765 nt_devmode->scale=devmode->scale;
1766 nt_devmode->copies=devmode->copies;
1767 nt_devmode->defaultsource=devmode->defaultsource;
1768 nt_devmode->printquality=devmode->printquality;
1769 nt_devmode->color=devmode->color;
1770 nt_devmode->duplex=devmode->duplex;
1771 nt_devmode->yresolution=devmode->yresolution;
1772 nt_devmode->ttoption=devmode->ttoption;
1773 nt_devmode->collate=devmode->collate;
1775 nt_devmode->logpixels=devmode->logpixels;
1776 nt_devmode->bitsperpel=devmode->bitsperpel;
1777 nt_devmode->pelswidth=devmode->pelswidth;
1778 nt_devmode->pelsheight=devmode->pelsheight;
1779 nt_devmode->displayflags=devmode->displayflags;
1780 nt_devmode->displayfrequency=devmode->displayfrequency;
1781 nt_devmode->icmmethod=devmode->icmmethod;
1782 nt_devmode->icmintent=devmode->icmintent;
1783 nt_devmode->mediatype=devmode->mediatype;
1784 nt_devmode->dithertype=devmode->dithertype;
1785 nt_devmode->reserved1=devmode->reserved1;
1786 nt_devmode->reserved2=devmode->reserved2;
1787 nt_devmode->panningwidth=devmode->panningwidth;
1788 nt_devmode->panningheight=devmode->panningheight;
1791 * Only change private and driverextra if the incoming devmode
1792 * has a new one. JRA.
1795 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1796 SAFE_FREE(nt_devmode->private);
1797 nt_devmode->driverextra=devmode->driverextra;
1798 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1799 return False;
1800 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1803 *pp_nt_devmode = nt_devmode;
1805 return True;
1808 /********************************************************************
1809 * _spoolss_enddocprinter_internal.
1810 ********************************************************************/
1812 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1814 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1815 int snum;
1817 if (!Printer) {
1818 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1819 return WERR_BADFID;
1822 if (!get_printer_snum(p, handle, &snum))
1823 return WERR_BADFID;
1825 Printer->document_started=False;
1826 print_job_end(snum, Printer->jobid,True);
1827 /* error codes unhandled so far ... */
1829 return WERR_OK;
1832 /********************************************************************
1833 * api_spoolss_closeprinter
1834 ********************************************************************/
1836 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1838 POLICY_HND *handle = &q_u->handle;
1840 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1842 if (Printer && Printer->document_started)
1843 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1845 if (!close_printer_handle(p, handle))
1846 return WERR_BADFID;
1848 /* clear the returned printer handle. Observed behavior
1849 from Win2k server. Don't think this really matters.
1850 Previous code just copied the value of the closed
1851 handle. --jerry */
1853 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1855 return WERR_OK;
1858 /********************************************************************
1859 * api_spoolss_deleteprinter
1861 ********************************************************************/
1863 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1865 POLICY_HND *handle = &q_u->handle;
1866 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1867 WERROR result;
1869 if (Printer && Printer->document_started)
1870 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1872 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1874 result = delete_printer_handle(p, handle);
1876 update_c_setprinter(False);
1878 return result;
1881 /*******************************************************************
1882 * static function to lookup the version id corresponding to an
1883 * long architecture string
1884 ******************************************************************/
1886 static int get_version_id (char * arch)
1888 int i;
1889 struct table_node archi_table[]= {
1891 {"Windows 4.0", "WIN40", 0 },
1892 {"Windows NT x86", "W32X86", 2 },
1893 {"Windows NT R4000", "W32MIPS", 2 },
1894 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1895 {"Windows NT PowerPC", "W32PPC", 2 },
1896 {NULL, "", -1 }
1899 for (i=0; archi_table[i].long_archi != NULL; i++)
1901 if (strcmp(arch, archi_table[i].long_archi) == 0)
1902 return (archi_table[i].version);
1905 return -1;
1908 /********************************************************************
1909 * _spoolss_deleteprinterdriver
1910 ********************************************************************/
1912 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1914 fstring driver;
1915 fstring arch;
1916 NT_PRINTER_DRIVER_INFO_LEVEL info;
1917 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1918 int version;
1919 struct current_user user;
1920 WERROR status;
1921 WERROR status_win2k = WERR_ACCESS_DENIED;
1923 get_current_user(&user, p);
1925 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1926 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1928 /* check that we have a valid driver name first */
1930 if ((version=get_version_id(arch)) == -1)
1931 return WERR_INVALID_ENVIRONMENT;
1933 ZERO_STRUCT(info);
1934 ZERO_STRUCT(info_win2k);
1936 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1938 /* try for Win2k driver if "Windows NT x86" */
1940 if ( version == 2 ) {
1941 version = 3;
1942 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1943 status = WERR_UNKNOWN_PRINTER_DRIVER;
1944 goto done;
1947 /* otherwise it was a failure */
1948 else {
1949 status = WERR_UNKNOWN_PRINTER_DRIVER;
1950 goto done;
1955 if (printer_driver_in_use(info.info_3)) {
1956 status = WERR_PRINTER_DRIVER_IN_USE;
1957 goto done;
1960 if ( version == 2 )
1962 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1964 /* if we get to here, we now have 2 driver info structures to remove */
1965 /* remove the Win2k driver first*/
1967 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1968 free_a_printer_driver( info_win2k, 3 );
1970 /* this should not have failed---if it did, report to client */
1971 if ( !W_ERROR_IS_OK(status_win2k) )
1972 goto done;
1976 status = delete_printer_driver(info.info_3, &user, version, False);
1978 /* if at least one of the deletes succeeded return OK */
1980 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1981 status = WERR_OK;
1983 done:
1984 free_a_printer_driver( info, 3 );
1986 return status;
1989 /********************************************************************
1990 * spoolss_deleteprinterdriverex
1991 ********************************************************************/
1993 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1995 fstring driver;
1996 fstring arch;
1997 NT_PRINTER_DRIVER_INFO_LEVEL info;
1998 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1999 int version;
2000 uint32 flags = q_u->delete_flags;
2001 BOOL delete_files;
2002 struct current_user user;
2003 WERROR status;
2004 WERROR status_win2k = WERR_ACCESS_DENIED;
2006 get_current_user(&user, p);
2008 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2009 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2011 /* check that we have a valid driver name first */
2012 if ((version=get_version_id(arch)) == -1) {
2013 /* this is what NT returns */
2014 return WERR_INVALID_ENVIRONMENT;
2017 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2018 version = q_u->version;
2020 ZERO_STRUCT(info);
2021 ZERO_STRUCT(info_win2k);
2023 status = get_a_printer_driver(&info, 3, driver, arch, version);
2025 if ( !W_ERROR_IS_OK(status) )
2028 * if the client asked for a specific version,
2029 * or this is something other than Windows NT x86,
2030 * then we've failed
2033 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2034 goto done;
2036 /* try for Win2k driver if "Windows NT x86" */
2038 version = 3;
2039 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2040 status = WERR_UNKNOWN_PRINTER_DRIVER;
2041 goto done;
2045 if ( printer_driver_in_use(info.info_3) ) {
2046 status = WERR_PRINTER_DRIVER_IN_USE;
2047 goto done;
2051 * we have a couple of cases to consider.
2052 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2053 * then the delete should fail if **any** files overlap with
2054 * other drivers
2055 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2056 * non-overlapping files
2057 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2058 * is set, the do not delete any files
2059 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2062 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2064 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2066 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2067 /* no idea of the correct error here */
2068 status = WERR_ACCESS_DENIED;
2069 goto done;
2073 /* also check for W32X86/3 if necessary; maybe we already have? */
2075 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2076 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2079 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2080 /* no idea of the correct error here */
2081 free_a_printer_driver( info_win2k, 3 );
2082 status = WERR_ACCESS_DENIED;
2083 goto done;
2086 /* if we get to here, we now have 2 driver info structures to remove */
2087 /* remove the Win2k driver first*/
2089 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2090 free_a_printer_driver( info_win2k, 3 );
2092 /* this should not have failed---if it did, report to client */
2094 if ( !W_ERROR_IS_OK(status_win2k) )
2095 goto done;
2099 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2101 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2102 status = WERR_OK;
2103 done:
2104 free_a_printer_driver( info, 3 );
2106 return status;
2110 /****************************************************************************
2111 Internal routine for retreiving printerdata
2112 ***************************************************************************/
2114 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2115 const char *key, const char *value, uint32 *type, uint8 **data,
2116 uint32 *needed, uint32 in_size )
2118 REGISTRY_VALUE *val;
2119 int size, data_len;
2121 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2122 return WERR_BADFILE;
2124 *type = regval_type( val );
2126 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2128 size = regval_size( val );
2130 /* copy the min(in_size, len) */
2132 if ( in_size ) {
2133 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2135 /* special case for 0 length values */
2136 if ( data_len ) {
2137 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2138 return WERR_NOMEM;
2140 else {
2141 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2142 return WERR_NOMEM;
2145 else
2146 *data = NULL;
2148 *needed = size;
2150 DEBUG(5,("get_printer_dataex: copy done\n"));
2152 return WERR_OK;
2155 /****************************************************************************
2156 Internal routine for removing printerdata
2157 ***************************************************************************/
2159 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2161 delete_printer_data( printer->info_2, key, value );
2163 return mod_a_printer(*printer, 2);
2166 /****************************************************************************
2167 Internal routine for storing printerdata
2168 ***************************************************************************/
2170 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2171 uint32 type, uint8 *data, int real_len )
2173 delete_printer_data( printer->info_2, key, value );
2175 add_printer_data( printer->info_2, key, value, type, data, real_len );
2177 return mod_a_printer(*printer, 2);
2180 /********************************************************************
2181 GetPrinterData on a printer server Handle.
2182 ********************************************************************/
2184 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2186 int i;
2188 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2190 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2191 *type = 0x4;
2192 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2193 return WERR_NOMEM;
2194 *needed = 0x4;
2195 return WERR_OK;
2198 if (!StrCaseCmp(value, "BeepEnabled")) {
2199 *type = 0x4;
2200 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2201 return WERR_NOMEM;
2202 SIVAL(*data, 0, 0x00);
2203 *needed = 0x4;
2204 return WERR_OK;
2207 if (!StrCaseCmp(value, "EventLog")) {
2208 *type = 0x4;
2209 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2210 return WERR_NOMEM;
2211 /* formally was 0x1b */
2212 SIVAL(*data, 0, 0x0);
2213 *needed = 0x4;
2214 return WERR_OK;
2217 if (!StrCaseCmp(value, "NetPopup")) {
2218 *type = 0x4;
2219 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2220 return WERR_NOMEM;
2221 SIVAL(*data, 0, 0x00);
2222 *needed = 0x4;
2223 return WERR_OK;
2226 if (!StrCaseCmp(value, "MajorVersion")) {
2227 *type = 0x4;
2228 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2229 return WERR_NOMEM;
2230 #ifdef HAVE_ADS
2231 SIVAL(*data, 0, 3);
2232 #else
2233 SIVAL(*data, 0, 2);
2234 #endif
2235 *needed = 0x4;
2236 return WERR_OK;
2239 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2240 fstring string;
2242 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2243 *type = 0x1;
2244 *needed = 2*(strlen(string)+1);
2245 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2246 return WERR_NOMEM;
2247 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2249 /* it's done by hand ready to go on the wire */
2250 for (i=0; i<strlen(string); i++) {
2251 (*data)[2*i]=string[i];
2252 (*data)[2*i+1]='\0';
2254 return WERR_OK;
2257 if (!StrCaseCmp(value, "Architecture")) {
2258 pstring string="Windows NT x86";
2259 *type = 0x1;
2260 *needed = 2*(strlen(string)+1);
2261 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2262 return WERR_NOMEM;
2263 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2264 for (i=0; i<strlen(string); i++) {
2265 (*data)[2*i]=string[i];
2266 (*data)[2*i+1]='\0';
2268 return WERR_OK;
2271 if (!StrCaseCmp(value, "DsPresent")) {
2272 *type = 0x4;
2273 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2274 return WERR_NOMEM;
2275 SIVAL(*data, 0, 0x01);
2276 *needed = 0x4;
2277 return WERR_OK;
2280 if (!StrCaseCmp(value, "DNSMachineName")) {
2281 pstring hostname;
2283 if (!get_myfullname(hostname))
2284 return WERR_BADFILE;
2285 *type = 0x1;
2286 *needed = 2*(strlen(hostname)+1);
2287 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2288 return WERR_NOMEM;
2289 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2290 for (i=0; i<strlen(hostname); i++) {
2291 (*data)[2*i]=hostname[i];
2292 (*data)[2*i+1]='\0';
2294 return WERR_OK;
2298 return WERR_BADFILE;
2301 /********************************************************************
2302 * spoolss_getprinterdata
2303 ********************************************************************/
2305 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2307 POLICY_HND *handle = &q_u->handle;
2308 UNISTR2 *valuename = &q_u->valuename;
2309 uint32 in_size = q_u->size;
2310 uint32 *type = &r_u->type;
2311 uint32 *out_size = &r_u->size;
2312 uint8 **data = &r_u->data;
2313 uint32 *needed = &r_u->needed;
2314 WERROR status;
2315 fstring value;
2316 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2317 NT_PRINTER_INFO_LEVEL *printer = NULL;
2318 int snum = 0;
2321 * Reminder: when it's a string, the length is in BYTES
2322 * even if UNICODE is negociated.
2324 * JFM, 4/19/1999
2327 *out_size = in_size;
2329 /* in case of problem, return some default values */
2331 *needed = 0;
2332 *type = 0;
2334 DEBUG(4,("_spoolss_getprinterdata\n"));
2336 if ( !Printer ) {
2337 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2338 status = WERR_BADFID;
2339 goto done;
2342 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2344 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2345 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2346 else
2348 if ( !get_printer_snum(p,handle, &snum) ) {
2349 status = WERR_BADFID;
2350 goto done;
2353 status = get_a_printer(&printer, 2, lp_servicename(snum));
2354 if ( !W_ERROR_IS_OK(status) )
2355 goto done;
2357 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2359 if ( strequal(value, "ChangeId") ) {
2360 *type = REG_DWORD;
2361 *needed = sizeof(uint32);
2362 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2363 status = WERR_NOMEM;
2364 goto done;
2366 **data = printer->info_2->changeid;
2367 status = WERR_OK;
2369 else
2370 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2373 if (*needed > *out_size)
2374 status = WERR_MORE_DATA;
2376 done:
2377 if ( !W_ERROR_IS_OK(status) )
2379 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2381 /* reply this param doesn't exist */
2383 if ( *out_size ) {
2384 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2385 if ( printer )
2386 free_a_printer( &printer, 2 );
2387 return WERR_NOMEM;
2390 else {
2391 *data = NULL;
2395 /* cleanup & exit */
2397 if ( printer )
2398 free_a_printer( &printer, 2 );
2400 return status;
2403 /*********************************************************
2404 Connect to the client machine.
2405 **********************************************************/
2407 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, const char *remote_machine)
2409 ZERO_STRUCTP(the_cli);
2410 if(cli_initialise(the_cli) == NULL) {
2411 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2412 return False;
2415 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2416 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2417 cli_shutdown(the_cli);
2418 return False;
2421 if (ismyip(the_cli->dest_ip)) {
2422 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2423 cli_shutdown(the_cli);
2424 return False;
2427 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2428 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2429 cli_shutdown(the_cli);
2430 return False;
2433 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2434 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2435 remote_machine));
2436 cli_shutdown(the_cli);
2437 return False;
2440 the_cli->protocol = PROTOCOL_NT1;
2442 if (!cli_negprot(the_cli)) {
2443 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2444 cli_shutdown(the_cli);
2445 return False;
2448 if (the_cli->protocol != PROTOCOL_NT1) {
2449 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2450 cli_shutdown(the_cli);
2451 return False;
2455 * Do an anonymous session setup.
2458 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2459 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2460 cli_shutdown(the_cli);
2461 return False;
2464 if (!(the_cli->sec_mode & 1)) {
2465 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2466 cli_shutdown(the_cli);
2467 return False;
2470 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2471 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2472 cli_shutdown(the_cli);
2473 return False;
2477 * Ok - we have an anonymous connection to the IPC$ share.
2478 * Now start the NT Domain stuff :-).
2481 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2482 DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2483 cli_nt_session_close(the_cli);
2484 cli_ulogoff(the_cli);
2485 cli_shutdown(the_cli);
2486 return False;
2489 return True;
2492 /***************************************************************************
2493 Connect to the client.
2494 ****************************************************************************/
2496 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2498 WERROR result;
2501 * If it's the first connection, contact the client
2502 * and connect to the IPC$ share anonumously
2504 if (smb_connections==0) {
2505 fstring unix_printer;
2507 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2509 if(!spoolss_connect_to_client(&notify_cli, unix_printer))
2510 return False;
2512 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2513 /* Tell the connections db we're now interested in printer
2514 * notify messages. */
2515 register_message_flags( True, FLAG_MSG_PRINTING );
2519 * Tell the specific printing tdb we want messages for this printer
2520 * by registering our PID.
2523 if (!print_notify_register_pid(snum))
2524 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2526 smb_connections++;
2528 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2529 type, handle);
2531 if (!W_ERROR_IS_OK(result))
2532 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2533 dos_errstr(result)));
2535 return (W_ERROR_IS_OK(result));
2538 /********************************************************************
2539 * _spoolss_rffpcnex
2540 * ReplyFindFirstPrinterChangeNotifyEx
2542 * before replying OK: status=0 a rpc call is made to the workstation
2543 * asking ReplyOpenPrinter
2545 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2546 * called from api_spoolss_rffpcnex
2547 ********************************************************************/
2549 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2551 POLICY_HND *handle = &q_u->handle;
2552 uint32 flags = q_u->flags;
2553 uint32 options = q_u->options;
2554 UNISTR2 *localmachine = &q_u->localmachine;
2555 uint32 printerlocal = q_u->printerlocal;
2556 int snum = -1;
2557 SPOOL_NOTIFY_OPTION *option = q_u->option;
2559 /* store the notify value in the printer struct */
2561 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2563 if (!Printer) {
2564 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2565 return WERR_BADFID;
2568 Printer->notify.flags=flags;
2569 Printer->notify.options=options;
2570 Printer->notify.printerlocal=printerlocal;
2572 if (Printer->notify.option)
2573 free_spool_notify_option(&Printer->notify.option);
2575 Printer->notify.option=dup_spool_notify_option(option);
2577 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2578 sizeof(Printer->notify.localmachine)-1);
2580 /* Connect to the client machine and send a ReplyOpenPrinter */
2582 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2583 snum = -1;
2584 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2585 !get_printer_snum(p, handle, &snum) )
2586 return WERR_BADFID;
2588 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2589 Printer->notify.printerlocal, 1,
2590 &Printer->notify.client_hnd))
2591 return WERR_SERVER_UNAVAILABLE;
2593 Printer->notify.client_connected=True;
2595 return WERR_OK;
2598 /*******************************************************************
2599 * fill a notify_info_data with the servername
2600 ********************************************************************/
2602 void spoolss_notify_server_name(int snum,
2603 SPOOL_NOTIFY_INFO_DATA *data,
2604 print_queue_struct *queue,
2605 NT_PRINTER_INFO_LEVEL *printer,
2606 TALLOC_CTX *mem_ctx)
2608 pstring temp_name, temp;
2609 uint32 len;
2611 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2613 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2615 data->notify_data.data.length = len;
2616 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2618 if (!data->notify_data.data.string) {
2619 data->notify_data.data.length = 0;
2620 return;
2623 memcpy(data->notify_data.data.string, temp, len);
2626 /*******************************************************************
2627 * fill a notify_info_data with the printername (not including the servername).
2628 ********************************************************************/
2630 void spoolss_notify_printer_name(int snum,
2631 SPOOL_NOTIFY_INFO_DATA *data,
2632 print_queue_struct *queue,
2633 NT_PRINTER_INFO_LEVEL *printer,
2634 TALLOC_CTX *mem_ctx)
2636 pstring temp;
2637 uint32 len;
2639 /* the notify name should not contain the \\server\ part */
2640 char *p = strrchr(printer->info_2->printername, '\\');
2642 if (!p) {
2643 p = printer->info_2->printername;
2644 } else {
2645 p++;
2648 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2650 data->notify_data.data.length = len;
2651 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2653 if (!data->notify_data.data.string) {
2654 data->notify_data.data.length = 0;
2655 return;
2658 memcpy(data->notify_data.data.string, temp, len);
2661 /*******************************************************************
2662 * fill a notify_info_data with the servicename
2663 ********************************************************************/
2665 void spoolss_notify_share_name(int snum,
2666 SPOOL_NOTIFY_INFO_DATA *data,
2667 print_queue_struct *queue,
2668 NT_PRINTER_INFO_LEVEL *printer,
2669 TALLOC_CTX *mem_ctx)
2671 pstring temp;
2672 uint32 len;
2674 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2676 data->notify_data.data.length = len;
2677 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2679 if (!data->notify_data.data.string) {
2680 data->notify_data.data.length = 0;
2681 return;
2684 memcpy(data->notify_data.data.string, temp, len);
2687 /*******************************************************************
2688 * fill a notify_info_data with the port name
2689 ********************************************************************/
2691 void spoolss_notify_port_name(int snum,
2692 SPOOL_NOTIFY_INFO_DATA *data,
2693 print_queue_struct *queue,
2694 NT_PRINTER_INFO_LEVEL *printer,
2695 TALLOC_CTX *mem_ctx)
2697 pstring temp;
2698 uint32 len;
2700 /* even if it's strange, that's consistant in all the code */
2702 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2704 data->notify_data.data.length = len;
2705 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2707 if (!data->notify_data.data.string) {
2708 data->notify_data.data.length = 0;
2709 return;
2712 memcpy(data->notify_data.data.string, temp, len);
2715 /*******************************************************************
2716 * fill a notify_info_data with the printername
2717 * but it doesn't exist, have to see what to do
2718 ********************************************************************/
2720 void spoolss_notify_driver_name(int snum,
2721 SPOOL_NOTIFY_INFO_DATA *data,
2722 print_queue_struct *queue,
2723 NT_PRINTER_INFO_LEVEL *printer,
2724 TALLOC_CTX *mem_ctx)
2726 pstring temp;
2727 uint32 len;
2729 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2731 data->notify_data.data.length = len;
2732 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2734 if (!data->notify_data.data.string) {
2735 data->notify_data.data.length = 0;
2736 return;
2739 memcpy(data->notify_data.data.string, temp, len);
2742 /*******************************************************************
2743 * fill a notify_info_data with the comment
2744 ********************************************************************/
2746 void spoolss_notify_comment(int snum,
2747 SPOOL_NOTIFY_INFO_DATA *data,
2748 print_queue_struct *queue,
2749 NT_PRINTER_INFO_LEVEL *printer,
2750 TALLOC_CTX *mem_ctx)
2752 pstring temp;
2753 uint32 len;
2755 if (*printer->info_2->comment == '\0')
2756 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2757 else
2758 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2760 data->notify_data.data.length = len;
2761 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2763 if (!data->notify_data.data.string) {
2764 data->notify_data.data.length = 0;
2765 return;
2768 memcpy(data->notify_data.data.string, temp, len);
2771 /*******************************************************************
2772 * fill a notify_info_data with the comment
2773 * location = "Room 1, floor 2, building 3"
2774 ********************************************************************/
2776 void spoolss_notify_location(int snum,
2777 SPOOL_NOTIFY_INFO_DATA *data,
2778 print_queue_struct *queue,
2779 NT_PRINTER_INFO_LEVEL *printer,
2780 TALLOC_CTX *mem_ctx)
2782 pstring temp;
2783 uint32 len;
2785 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2787 data->notify_data.data.length = len;
2788 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2790 if (!data->notify_data.data.string) {
2791 data->notify_data.data.length = 0;
2792 return;
2795 memcpy(data->notify_data.data.string, temp, len);
2798 /*******************************************************************
2799 * fill a notify_info_data with the device mode
2800 * jfm:xxxx don't to it for know but that's a real problem !!!
2801 ********************************************************************/
2803 static void spoolss_notify_devmode(int snum,
2804 SPOOL_NOTIFY_INFO_DATA *data,
2805 print_queue_struct *queue,
2806 NT_PRINTER_INFO_LEVEL *printer,
2807 TALLOC_CTX *mem_ctx)
2811 /*******************************************************************
2812 * fill a notify_info_data with the separator file name
2813 ********************************************************************/
2815 void spoolss_notify_sepfile(int snum,
2816 SPOOL_NOTIFY_INFO_DATA *data,
2817 print_queue_struct *queue,
2818 NT_PRINTER_INFO_LEVEL *printer,
2819 TALLOC_CTX *mem_ctx)
2821 pstring temp;
2822 uint32 len;
2824 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2826 data->notify_data.data.length = len;
2827 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2829 if (!data->notify_data.data.string) {
2830 data->notify_data.data.length = 0;
2831 return;
2834 memcpy(data->notify_data.data.string, temp, len);
2837 /*******************************************************************
2838 * fill a notify_info_data with the print processor
2839 * jfm:xxxx return always winprint to indicate we don't do anything to it
2840 ********************************************************************/
2842 void spoolss_notify_print_processor(int snum,
2843 SPOOL_NOTIFY_INFO_DATA *data,
2844 print_queue_struct *queue,
2845 NT_PRINTER_INFO_LEVEL *printer,
2846 TALLOC_CTX *mem_ctx)
2848 pstring temp;
2849 uint32 len;
2851 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2853 data->notify_data.data.length = len;
2854 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2856 if (!data->notify_data.data.string) {
2857 data->notify_data.data.length = 0;
2858 return;
2861 memcpy(data->notify_data.data.string, temp, len);
2864 /*******************************************************************
2865 * fill a notify_info_data with the print processor options
2866 * jfm:xxxx send an empty string
2867 ********************************************************************/
2869 void spoolss_notify_parameters(int snum,
2870 SPOOL_NOTIFY_INFO_DATA *data,
2871 print_queue_struct *queue,
2872 NT_PRINTER_INFO_LEVEL *printer,
2873 TALLOC_CTX *mem_ctx)
2875 pstring temp;
2876 uint32 len;
2878 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2880 data->notify_data.data.length = len;
2881 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2883 if (!data->notify_data.data.string) {
2884 data->notify_data.data.length = 0;
2885 return;
2888 memcpy(data->notify_data.data.string, temp, len);
2891 /*******************************************************************
2892 * fill a notify_info_data with the data type
2893 * jfm:xxxx always send RAW as data type
2894 ********************************************************************/
2896 void spoolss_notify_datatype(int snum,
2897 SPOOL_NOTIFY_INFO_DATA *data,
2898 print_queue_struct *queue,
2899 NT_PRINTER_INFO_LEVEL *printer,
2900 TALLOC_CTX *mem_ctx)
2902 pstring temp;
2903 uint32 len;
2905 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2907 data->notify_data.data.length = len;
2908 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2910 if (!data->notify_data.data.string) {
2911 data->notify_data.data.length = 0;
2912 return;
2915 memcpy(data->notify_data.data.string, temp, len);
2918 /*******************************************************************
2919 * fill a notify_info_data with the security descriptor
2920 * jfm:xxxx send an null pointer to say no security desc
2921 * have to implement security before !
2922 ********************************************************************/
2924 static void spoolss_notify_security_desc(int snum,
2925 SPOOL_NOTIFY_INFO_DATA *data,
2926 print_queue_struct *queue,
2927 NT_PRINTER_INFO_LEVEL *printer,
2928 TALLOC_CTX *mem_ctx)
2930 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2931 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2934 /*******************************************************************
2935 * fill a notify_info_data with the attributes
2936 * jfm:xxxx a samba printer is always shared
2937 ********************************************************************/
2939 void spoolss_notify_attributes(int snum,
2940 SPOOL_NOTIFY_INFO_DATA *data,
2941 print_queue_struct *queue,
2942 NT_PRINTER_INFO_LEVEL *printer,
2943 TALLOC_CTX *mem_ctx)
2945 data->notify_data.value[0] = printer->info_2->attributes;
2946 data->notify_data.value[1] = 0;
2949 /*******************************************************************
2950 * fill a notify_info_data with the priority
2951 ********************************************************************/
2953 static void spoolss_notify_priority(int snum,
2954 SPOOL_NOTIFY_INFO_DATA *data,
2955 print_queue_struct *queue,
2956 NT_PRINTER_INFO_LEVEL *printer,
2957 TALLOC_CTX *mem_ctx)
2959 data->notify_data.value[0] = printer->info_2->priority;
2960 data->notify_data.value[1] = 0;
2963 /*******************************************************************
2964 * fill a notify_info_data with the default priority
2965 ********************************************************************/
2967 static void spoolss_notify_default_priority(int snum,
2968 SPOOL_NOTIFY_INFO_DATA *data,
2969 print_queue_struct *queue,
2970 NT_PRINTER_INFO_LEVEL *printer,
2971 TALLOC_CTX *mem_ctx)
2973 data->notify_data.value[0] = printer->info_2->default_priority;
2974 data->notify_data.value[1] = 0;
2977 /*******************************************************************
2978 * fill a notify_info_data with the start time
2979 ********************************************************************/
2981 static void spoolss_notify_start_time(int snum,
2982 SPOOL_NOTIFY_INFO_DATA *data,
2983 print_queue_struct *queue,
2984 NT_PRINTER_INFO_LEVEL *printer,
2985 TALLOC_CTX *mem_ctx)
2987 data->notify_data.value[0] = printer->info_2->starttime;
2988 data->notify_data.value[1] = 0;
2991 /*******************************************************************
2992 * fill a notify_info_data with the until time
2993 ********************************************************************/
2995 static void spoolss_notify_until_time(int snum,
2996 SPOOL_NOTIFY_INFO_DATA *data,
2997 print_queue_struct *queue,
2998 NT_PRINTER_INFO_LEVEL *printer,
2999 TALLOC_CTX *mem_ctx)
3001 data->notify_data.value[0] = printer->info_2->untiltime;
3002 data->notify_data.value[1] = 0;
3005 /*******************************************************************
3006 * fill a notify_info_data with the status
3007 ********************************************************************/
3009 static void spoolss_notify_status(int snum,
3010 SPOOL_NOTIFY_INFO_DATA *data,
3011 print_queue_struct *queue,
3012 NT_PRINTER_INFO_LEVEL *printer,
3013 TALLOC_CTX *mem_ctx)
3015 print_status_struct status;
3017 print_queue_length(snum, &status);
3018 data->notify_data.value[0]=(uint32) status.status;
3019 data->notify_data.value[1] = 0;
3022 /*******************************************************************
3023 * fill a notify_info_data with the number of jobs queued
3024 ********************************************************************/
3026 void spoolss_notify_cjobs(int snum,
3027 SPOOL_NOTIFY_INFO_DATA *data,
3028 print_queue_struct *queue,
3029 NT_PRINTER_INFO_LEVEL *printer,
3030 TALLOC_CTX *mem_ctx)
3032 data->notify_data.value[0] = print_queue_length(snum, NULL);
3033 data->notify_data.value[1] = 0;
3036 /*******************************************************************
3037 * fill a notify_info_data with the average ppm
3038 ********************************************************************/
3040 static void spoolss_notify_average_ppm(int snum,
3041 SPOOL_NOTIFY_INFO_DATA *data,
3042 print_queue_struct *queue,
3043 NT_PRINTER_INFO_LEVEL *printer,
3044 TALLOC_CTX *mem_ctx)
3046 /* always respond 8 pages per minutes */
3047 /* a little hard ! */
3048 data->notify_data.value[0] = printer->info_2->averageppm;
3049 data->notify_data.value[1] = 0;
3052 /*******************************************************************
3053 * fill a notify_info_data with username
3054 ********************************************************************/
3056 static void spoolss_notify_username(int snum,
3057 SPOOL_NOTIFY_INFO_DATA *data,
3058 print_queue_struct *queue,
3059 NT_PRINTER_INFO_LEVEL *printer,
3060 TALLOC_CTX *mem_ctx)
3062 pstring temp;
3063 uint32 len;
3065 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3067 data->notify_data.data.length = len;
3068 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3070 if (!data->notify_data.data.string) {
3071 data->notify_data.data.length = 0;
3072 return;
3075 memcpy(data->notify_data.data.string, temp, len);
3078 /*******************************************************************
3079 * fill a notify_info_data with job status
3080 ********************************************************************/
3082 static void spoolss_notify_job_status(int snum,
3083 SPOOL_NOTIFY_INFO_DATA *data,
3084 print_queue_struct *queue,
3085 NT_PRINTER_INFO_LEVEL *printer,
3086 TALLOC_CTX *mem_ctx)
3088 data->notify_data.value[0]=nt_printj_status(queue->status);
3089 data->notify_data.value[1] = 0;
3092 /*******************************************************************
3093 * fill a notify_info_data with job name
3094 ********************************************************************/
3096 static void spoolss_notify_job_name(int snum,
3097 SPOOL_NOTIFY_INFO_DATA *data,
3098 print_queue_struct *queue,
3099 NT_PRINTER_INFO_LEVEL *printer,
3100 TALLOC_CTX *mem_ctx)
3102 pstring temp;
3103 uint32 len;
3105 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3107 data->notify_data.data.length = len;
3108 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3110 if (!data->notify_data.data.string) {
3111 data->notify_data.data.length = 0;
3112 return;
3115 memcpy(data->notify_data.data.string, temp, len);
3118 /*******************************************************************
3119 * fill a notify_info_data with job status
3120 ********************************************************************/
3122 static void spoolss_notify_job_status_string(int snum,
3123 SPOOL_NOTIFY_INFO_DATA *data,
3124 print_queue_struct *queue,
3125 NT_PRINTER_INFO_LEVEL *printer,
3126 TALLOC_CTX *mem_ctx)
3129 * Now we're returning job status codes we just return a "" here. JRA.
3132 const char *p = "";
3133 pstring temp;
3134 uint32 len;
3136 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3137 p = "unknown";
3139 switch (queue->status) {
3140 case LPQ_QUEUED:
3141 p = "Queued";
3142 break;
3143 case LPQ_PAUSED:
3144 p = ""; /* NT provides the paused string */
3145 break;
3146 case LPQ_SPOOLING:
3147 p = "Spooling";
3148 break;
3149 case LPQ_PRINTING:
3150 p = "Printing";
3151 break;
3153 #endif /* NO LONGER NEEDED. */
3155 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3157 data->notify_data.data.length = len;
3158 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3160 if (!data->notify_data.data.string) {
3161 data->notify_data.data.length = 0;
3162 return;
3165 memcpy(data->notify_data.data.string, temp, len);
3168 /*******************************************************************
3169 * fill a notify_info_data with job time
3170 ********************************************************************/
3172 static void spoolss_notify_job_time(int snum,
3173 SPOOL_NOTIFY_INFO_DATA *data,
3174 print_queue_struct *queue,
3175 NT_PRINTER_INFO_LEVEL *printer,
3176 TALLOC_CTX *mem_ctx)
3178 data->notify_data.value[0]=0x0;
3179 data->notify_data.value[1]=0;
3182 /*******************************************************************
3183 * fill a notify_info_data with job size
3184 ********************************************************************/
3186 static void spoolss_notify_job_size(int snum,
3187 SPOOL_NOTIFY_INFO_DATA *data,
3188 print_queue_struct *queue,
3189 NT_PRINTER_INFO_LEVEL *printer,
3190 TALLOC_CTX *mem_ctx)
3192 data->notify_data.value[0]=queue->size;
3193 data->notify_data.value[1]=0;
3196 /*******************************************************************
3197 * fill a notify_info_data with page info
3198 ********************************************************************/
3199 static void spoolss_notify_total_pages(int snum,
3200 SPOOL_NOTIFY_INFO_DATA *data,
3201 print_queue_struct *queue,
3202 NT_PRINTER_INFO_LEVEL *printer,
3203 TALLOC_CTX *mem_ctx)
3205 data->notify_data.value[0]=queue->page_count;
3206 data->notify_data.value[1]=0;
3209 /*******************************************************************
3210 * fill a notify_info_data with pages printed info.
3211 ********************************************************************/
3212 static void spoolss_notify_pages_printed(int snum,
3213 SPOOL_NOTIFY_INFO_DATA *data,
3214 print_queue_struct *queue,
3215 NT_PRINTER_INFO_LEVEL *printer,
3216 TALLOC_CTX *mem_ctx)
3218 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3219 data->notify_data.value[1]=0;
3222 /*******************************************************************
3223 Fill a notify_info_data with job position.
3224 ********************************************************************/
3226 static void spoolss_notify_job_position(int snum,
3227 SPOOL_NOTIFY_INFO_DATA *data,
3228 print_queue_struct *queue,
3229 NT_PRINTER_INFO_LEVEL *printer,
3230 TALLOC_CTX *mem_ctx)
3232 data->notify_data.value[0]=queue->job;
3233 data->notify_data.value[1]=0;
3236 /*******************************************************************
3237 Fill a notify_info_data with submitted time.
3238 ********************************************************************/
3240 static void spoolss_notify_submitted_time(int snum,
3241 SPOOL_NOTIFY_INFO_DATA *data,
3242 print_queue_struct *queue,
3243 NT_PRINTER_INFO_LEVEL *printer,
3244 TALLOC_CTX *mem_ctx)
3246 struct tm *t;
3247 uint32 len;
3248 SYSTEMTIME st;
3249 char *p;
3251 t=gmtime(&queue->time);
3253 len = sizeof(SYSTEMTIME);
3255 data->notify_data.data.length = len;
3256 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3258 if (!data->notify_data.data.string) {
3259 data->notify_data.data.length = 0;
3260 return;
3263 make_systemtime(&st, t);
3266 * Systemtime must be linearized as a set of UINT16's.
3267 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3270 p = (char *)data->notify_data.data.string;
3271 SSVAL(p, 0, st.year);
3272 SSVAL(p, 2, st.month);
3273 SSVAL(p, 4, st.dayofweek);
3274 SSVAL(p, 6, st.day);
3275 SSVAL(p, 8, st.hour);
3276 SSVAL(p, 10, st.minute);
3277 SSVAL(p, 12, st.second);
3278 SSVAL(p, 14, st.milliseconds);
3281 struct s_notify_info_data_table
3283 uint16 type;
3284 uint16 field;
3285 const char *name;
3286 uint32 size;
3287 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3288 print_queue_struct *queue,
3289 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3292 /* A table describing the various print notification constants and
3293 whether the notification data is a pointer to a variable sized
3294 buffer, a one value uint32 or a two value uint32. */
3296 static const struct s_notify_info_data_table notify_info_data_table[] =
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3337 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3338 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3339 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3340 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3341 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3342 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3343 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3344 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3345 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3346 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3349 /*******************************************************************
3350 Return the size of info_data structure.
3351 ********************************************************************/
3353 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3355 int i=0;
3357 for (i = 0; i < sizeof(notify_info_data_table); i++)
3359 if ( (notify_info_data_table[i].type == type)
3360 && (notify_info_data_table[i].field == field) )
3362 switch(notify_info_data_table[i].size)
3364 case NOTIFY_ONE_VALUE:
3365 case NOTIFY_TWO_VALUE:
3366 return 1;
3367 case NOTIFY_STRING:
3368 return 2;
3370 /* The only pointer notify data I have seen on
3371 the wire is the submitted time and this has
3372 the notify size set to 4. -tpot */
3374 case NOTIFY_POINTER:
3375 return 4;
3377 case NOTIFY_SECDESC:
3378 return 5;
3383 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3385 return 0;
3388 /*******************************************************************
3389 Return the type of notify_info_data.
3390 ********************************************************************/
3392 static int type_of_notify_info_data(uint16 type, uint16 field)
3394 int i=0;
3396 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3397 if (notify_info_data_table[i].type == type &&
3398 notify_info_data_table[i].field == field)
3399 return notify_info_data_table[i].size;
3402 return False;
3405 /****************************************************************************
3406 ****************************************************************************/
3408 static int search_notify(uint16 type, uint16 field, int *value)
3410 int i;
3412 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3413 if (notify_info_data_table[i].type == type &&
3414 notify_info_data_table[i].field == field &&
3415 notify_info_data_table[i].fn != NULL) {
3416 *value = i;
3417 return True;
3421 return False;
3424 /****************************************************************************
3425 ****************************************************************************/
3427 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3429 info_data->type = type;
3430 info_data->field = field;
3431 info_data->reserved = 0;
3433 info_data->size = size_of_notify_info_data(type, field);
3434 info_data->enc_type = type_of_notify_info_data(type, field);
3436 info_data->id = id;
3441 /*******************************************************************
3443 * fill a notify_info struct with info asked
3445 ********************************************************************/
3447 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
3448 snum, SPOOL_NOTIFY_OPTION_TYPE
3449 *option_type, uint32 id,
3450 TALLOC_CTX *mem_ctx)
3452 int field_num,j;
3453 uint16 type;
3454 uint16 field;
3456 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3457 NT_PRINTER_INFO_LEVEL *printer = NULL;
3458 print_queue_struct *queue=NULL;
3460 type=option_type->type;
3462 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3463 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3464 option_type->count, lp_servicename(snum)));
3466 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3467 return False;
3469 for(field_num=0; field_num<option_type->count; field_num++)
3471 field = option_type->fields[field_num];
3473 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3475 if (!search_notify(type, field, &j) )
3476 continue;
3478 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
3480 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3481 return False;
3483 else
3484 info->data = tid;
3486 current_data = &info->data[info->count];
3488 construct_info_data(current_data, type, field, id);
3490 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3491 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3493 notify_info_data_table[j].fn(snum, current_data, queue,
3494 printer, mem_ctx);
3496 info->count++;
3499 free_a_printer(&printer, 2);
3500 return True;
3503 /*******************************************************************
3505 * fill a notify_info struct with info asked
3507 ********************************************************************/
3509 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3510 SPOOL_NOTIFY_INFO *info,
3511 NT_PRINTER_INFO_LEVEL *printer,
3512 int snum, SPOOL_NOTIFY_OPTION_TYPE
3513 *option_type, uint32 id,
3514 TALLOC_CTX *mem_ctx)
3516 int field_num,j;
3517 uint16 type;
3518 uint16 field;
3520 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3522 DEBUG(4,("construct_notify_jobs_info\n"));
3524 type = option_type->type;
3526 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3527 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3528 option_type->count));
3530 for(field_num=0; field_num<option_type->count; field_num++) {
3531 field = option_type->fields[field_num];
3533 if (!search_notify(type, field, &j) )
3534 continue;
3536 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3537 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3538 return False;
3540 else info->data = tid;
3542 current_data=&(info->data[info->count]);
3544 construct_info_data(current_data, type, field, id);
3545 notify_info_data_table[j].fn(snum, current_data, queue,
3546 printer, mem_ctx);
3547 info->count++;
3550 return True;
3554 * JFM: The enumeration is not that simple, it's even non obvious.
3556 * let's take an example: I want to monitor the PRINTER SERVER for
3557 * the printer's name and the number of jobs currently queued.
3558 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3559 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3561 * I have 3 printers on the back of my server.
3563 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3564 * structures.
3565 * Number Data Id
3566 * 1 printer 1 name 1
3567 * 2 printer 1 cjob 1
3568 * 3 printer 2 name 2
3569 * 4 printer 2 cjob 2
3570 * 5 printer 3 name 3
3571 * 6 printer 3 name 3
3573 * that's the print server case, the printer case is even worse.
3576 /*******************************************************************
3578 * enumerate all printers on the printserver
3579 * fill a notify_info struct with info asked
3581 ********************************************************************/
3583 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3584 SPOOL_NOTIFY_INFO *info,
3585 TALLOC_CTX *mem_ctx)
3587 int snum;
3588 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3589 int n_services=lp_numservices();
3590 int i;
3591 uint32 id;
3592 SPOOL_NOTIFY_OPTION *option;
3593 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3595 DEBUG(4,("printserver_notify_info\n"));
3597 if (!Printer)
3598 return WERR_BADFID;
3600 option=Printer->notify.option;
3601 id=1;
3602 info->version=2;
3603 info->data=NULL;
3604 info->count=0;
3606 for (i=0; i<option->count; i++) {
3607 option_type=&(option->ctr.type[i]);
3609 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3610 continue;
3612 for (snum=0; snum<n_services; snum++)
3614 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3615 construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
3619 #if 0
3621 * Debugging information, don't delete.
3624 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3625 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3626 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3628 for (i=0; i<info->count; i++) {
3629 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3630 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3631 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3633 #endif
3635 return WERR_OK;
3638 /*******************************************************************
3640 * fill a notify_info struct with info asked
3642 ********************************************************************/
3644 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3645 TALLOC_CTX *mem_ctx)
3647 int snum;
3648 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3649 int i;
3650 uint32 id;
3651 SPOOL_NOTIFY_OPTION *option;
3652 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3653 int count,j;
3654 print_queue_struct *queue=NULL;
3655 print_status_struct status;
3657 DEBUG(4,("printer_notify_info\n"));
3659 if (!Printer)
3660 return WERR_BADFID;
3662 option=Printer->notify.option;
3663 id = 0x0;
3664 info->version=2;
3665 info->data=NULL;
3666 info->count=0;
3668 get_printer_snum(p, hnd, &snum);
3670 for (i=0; i<option->count; i++) {
3671 option_type=&option->ctr.type[i];
3673 switch ( option_type->type ) {
3674 case PRINTER_NOTIFY_TYPE:
3675 if(construct_notify_printer_info(info, snum,
3676 option_type, id,
3677 mem_ctx))
3678 id--;
3679 break;
3681 case JOB_NOTIFY_TYPE: {
3682 NT_PRINTER_INFO_LEVEL *printer = NULL;
3684 count = print_queue_status(snum, &queue, &status);
3686 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3687 lp_servicename(snum))))
3688 goto done;
3690 for (j=0; j<count; j++) {
3691 construct_notify_jobs_info(&queue[j], info,
3692 printer, snum,
3693 option_type,
3694 queue[j].job,
3695 mem_ctx);
3698 free_a_printer(&printer, 2);
3700 done:
3701 SAFE_FREE(queue);
3702 break;
3708 * Debugging information, don't delete.
3711 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3712 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3713 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3715 for (i=0; i<info->count; i++) {
3716 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3717 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3718 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3721 return WERR_OK;
3724 /********************************************************************
3725 * spoolss_rfnpcnex
3726 ********************************************************************/
3728 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3730 POLICY_HND *handle = &q_u->handle;
3731 SPOOL_NOTIFY_INFO *info = &r_u->info;
3733 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3734 WERROR result = WERR_BADFID;
3736 /* we always have a NOTIFY_INFO struct */
3737 r_u->info_ptr=0x1;
3739 if (!Printer) {
3740 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3741 OUR_HANDLE(handle)));
3742 goto done;
3745 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3748 * We are now using the change value, and
3749 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3750 * I don't have a global notification system, I'm sending back all the
3751 * informations even when _NOTHING_ has changed.
3754 /* We need to keep track of the change value to send back in
3755 RRPCN replies otherwise our updates are ignored. */
3757 Printer->notify.fnpcn = True;
3759 if (Printer->notify.client_connected) {
3760 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3761 Printer->notify.change = q_u->change;
3764 /* just ignore the SPOOL_NOTIFY_OPTION */
3766 switch (Printer->printer_type) {
3767 case PRINTER_HANDLE_IS_PRINTSERVER:
3768 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3769 break;
3771 case PRINTER_HANDLE_IS_PRINTER:
3772 result = printer_notify_info(p, handle, info, p->mem_ctx);
3773 break;
3776 Printer->notify.fnpcn = False;
3778 done:
3779 return result;
3782 /********************************************************************
3783 * construct_printer_info_0
3784 * fill a printer_info_0 struct
3785 ********************************************************************/
3787 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3789 pstring chaine;
3790 int count;
3791 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3792 counter_printer_0 *session_counter;
3793 uint32 global_counter;
3794 struct tm *t;
3795 time_t setuptime;
3796 print_status_struct status;
3798 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3799 return False;
3801 count = print_queue_length(snum, &status);
3803 /* check if we already have a counter for this printer */
3804 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3806 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3807 if (session_counter->snum == snum)
3808 break;
3811 /* it's the first time, add it to the list */
3812 if (session_counter==NULL) {
3813 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3814 free_a_printer(&ntprinter, 2);
3815 return False;
3817 ZERO_STRUCTP(session_counter);
3818 session_counter->snum=snum;
3819 session_counter->counter=0;
3820 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3823 /* increment it */
3824 session_counter->counter++;
3826 /* JFM:
3827 * the global_counter should be stored in a TDB as it's common to all the clients
3828 * and should be zeroed on samba startup
3830 global_counter=session_counter->counter;
3832 pstrcpy(chaine,ntprinter->info_2->printername);
3834 init_unistr(&printer->printername, chaine);
3836 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3837 init_unistr(&printer->servername, chaine);
3839 printer->cjobs = count;
3840 printer->total_jobs = 0;
3841 printer->total_bytes = 0;
3843 setuptime = (time_t)ntprinter->info_2->setuptime;
3844 t=gmtime(&setuptime);
3846 printer->year = t->tm_year+1900;
3847 printer->month = t->tm_mon+1;
3848 printer->dayofweek = t->tm_wday;
3849 printer->day = t->tm_mday;
3850 printer->hour = t->tm_hour;
3851 printer->minute = t->tm_min;
3852 printer->second = t->tm_sec;
3853 printer->milliseconds = 0;
3855 printer->global_counter = global_counter;
3856 printer->total_pages = 0;
3857 #ifdef HAVE_ADS
3858 printer->major_version = 0x0005; /* NT 5 */
3859 printer->build_version = 0x0893; /* build 2195 */
3860 #else
3861 printer->major_version = 0x0004; /* NT 4 */
3862 printer->build_version = 0x0565; /* build 1381 */
3863 #endif
3864 printer->unknown7 = 0x1;
3865 printer->unknown8 = 0x0;
3866 printer->unknown9 = 0x0;
3867 printer->session_counter = session_counter->counter;
3868 printer->unknown11 = 0x0;
3869 printer->printer_errors = 0x0; /* number of print failure */
3870 printer->unknown13 = 0x0;
3871 printer->unknown14 = 0x1;
3872 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3873 printer->unknown16 = 0x0;
3874 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3875 printer->unknown18 = 0x0;
3876 printer->status = nt_printq_status(status.status);
3877 printer->unknown20 = 0x0;
3878 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3879 printer->unknown22 = 0x0;
3880 printer->unknown23 = 0x6; /* 6 ???*/
3881 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3882 printer->unknown25 = 0;
3883 printer->unknown26 = 0;
3884 printer->unknown27 = 0;
3885 printer->unknown28 = 0;
3886 printer->unknown29 = 0;
3888 free_a_printer(&ntprinter,2);
3889 return (True);
3892 /********************************************************************
3893 * construct_printer_info_1
3894 * fill a printer_info_1 struct
3895 ********************************************************************/
3896 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3898 pstring chaine;
3899 pstring chaine2;
3900 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3902 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3903 return False;
3905 printer->flags=flags;
3907 if (*ntprinter->info_2->comment == '\0') {
3908 init_unistr(&printer->comment, lp_comment(snum));
3909 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3910 ntprinter->info_2->drivername, lp_comment(snum));
3912 else {
3913 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3914 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3915 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3918 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3920 init_unistr(&printer->description, chaine);
3921 init_unistr(&printer->name, chaine2);
3923 free_a_printer(&ntprinter,2);
3925 return True;
3928 /****************************************************************************
3929 Free a DEVMODE struct.
3930 ****************************************************************************/
3932 static void free_dev_mode(DEVICEMODE *dev)
3934 if (dev == NULL)
3935 return;
3937 SAFE_FREE(dev->private);
3938 SAFE_FREE(dev);
3942 /****************************************************************************
3943 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3944 should be valid upon entry
3945 ****************************************************************************/
3947 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
3949 if ( !devmode || !ntdevmode )
3950 return False;
3952 init_unistr(&devmode->devicename, ntdevmode->devicename);
3954 init_unistr(&devmode->formname, ntdevmode->formname);
3956 devmode->specversion = ntdevmode->specversion;
3957 devmode->driverversion = ntdevmode->driverversion;
3958 devmode->size = ntdevmode->size;
3959 devmode->driverextra = ntdevmode->driverextra;
3960 devmode->fields = ntdevmode->fields;
3962 devmode->orientation = ntdevmode->orientation;
3963 devmode->papersize = ntdevmode->papersize;
3964 devmode->paperlength = ntdevmode->paperlength;
3965 devmode->paperwidth = ntdevmode->paperwidth;
3966 devmode->scale = ntdevmode->scale;
3967 devmode->copies = ntdevmode->copies;
3968 devmode->defaultsource = ntdevmode->defaultsource;
3969 devmode->printquality = ntdevmode->printquality;
3970 devmode->color = ntdevmode->color;
3971 devmode->duplex = ntdevmode->duplex;
3972 devmode->yresolution = ntdevmode->yresolution;
3973 devmode->ttoption = ntdevmode->ttoption;
3974 devmode->collate = ntdevmode->collate;
3975 devmode->icmmethod = ntdevmode->icmmethod;
3976 devmode->icmintent = ntdevmode->icmintent;
3977 devmode->mediatype = ntdevmode->mediatype;
3978 devmode->dithertype = ntdevmode->dithertype;
3980 if (ntdevmode->private != NULL) {
3981 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3982 return False;
3985 return True;
3988 /****************************************************************************
3989 Create a DEVMODE struct. Returns malloced memory.
3990 ****************************************************************************/
3992 DEVICEMODE *construct_dev_mode(int snum)
3994 NT_PRINTER_INFO_LEVEL *printer = NULL;
3995 DEVICEMODE *devmode = NULL;
3997 DEBUG(7,("construct_dev_mode\n"));
3999 DEBUGADD(8,("getting printer characteristics\n"));
4001 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4002 return NULL;
4004 if ( !printer->info_2->devmode ) {
4005 DEBUG(5, ("BONG! There was no device mode!\n"));
4006 goto done;
4009 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4010 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4011 goto done;
4014 ZERO_STRUCTP(devmode);
4016 DEBUGADD(8,("loading DEVICEMODE\n"));
4018 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4019 free_dev_mode( devmode );
4020 devmode = NULL;
4023 done:
4024 free_a_printer(&printer,2);
4026 return devmode;
4029 /********************************************************************
4030 * construct_printer_info_2
4031 * fill a printer_info_2 struct
4032 ********************************************************************/
4034 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
4036 int count;
4037 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4039 print_status_struct status;
4041 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4042 return False;
4044 count = print_queue_length(snum, &status);
4046 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4047 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4048 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4049 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4050 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4052 if (*ntprinter->info_2->comment == '\0')
4053 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4054 else
4055 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4057 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4058 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4059 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4060 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4061 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4063 printer->attributes = ntprinter->info_2->attributes;
4065 printer->priority = ntprinter->info_2->priority; /* priority */
4066 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4067 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4068 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4069 printer->status = nt_printq_status(status.status); /* status */
4070 printer->cjobs = count; /* jobs */
4071 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4073 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4074 DEBUG(8, ("Returning NULL Devicemode!\n"));
4077 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4078 /* steal the printer info sec_desc structure. [badly done]. */
4079 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4080 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4081 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4082 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4084 else {
4085 printer->secdesc = NULL;
4088 free_a_printer(&ntprinter, 2);
4089 return True;
4092 /********************************************************************
4093 * construct_printer_info_3
4094 * fill a printer_info_3 struct
4095 ********************************************************************/
4097 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
4099 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4100 PRINTER_INFO_3 *printer = NULL;
4102 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4103 return False;
4105 *pp_printer = NULL;
4106 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4107 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4108 return False;
4111 ZERO_STRUCTP(printer);
4113 printer->flags = 4; /* These are the components of the SD we are returning. */
4114 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4115 /* steal the printer info sec_desc structure. [badly done]. */
4116 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4118 #if 0
4120 * Set the flags for the components we are returning.
4123 if (printer->secdesc->owner_sid)
4124 printer->flags |= OWNER_SECURITY_INFORMATION;
4126 if (printer->secdesc->grp_sid)
4127 printer->flags |= GROUP_SECURITY_INFORMATION;
4129 if (printer->secdesc->dacl)
4130 printer->flags |= DACL_SECURITY_INFORMATION;
4132 if (printer->secdesc->sacl)
4133 printer->flags |= SACL_SECURITY_INFORMATION;
4134 #endif
4136 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4137 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4138 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4141 free_a_printer(&ntprinter, 2);
4143 *pp_printer = printer;
4144 return True;
4147 /********************************************************************
4148 * construct_printer_info_4
4149 * fill a printer_info_4 struct
4150 ********************************************************************/
4152 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
4154 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4156 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4157 return False;
4159 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4160 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4161 printer->attributes = ntprinter->info_2->attributes;
4163 free_a_printer(&ntprinter, 2);
4164 return True;
4167 /********************************************************************
4168 * construct_printer_info_5
4169 * fill a printer_info_5 struct
4170 ********************************************************************/
4172 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
4174 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4176 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4177 return False;
4179 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4180 init_unistr(&printer->portname, ntprinter->info_2->portname); /* portname */
4181 printer->attributes = ntprinter->info_2->attributes;
4182 printer->device_not_selected_timeout = 0x3a98;
4183 printer->transmission_retry_timeout = 0xafc8;
4185 free_a_printer(&ntprinter, 2);
4186 return True;
4189 /********************************************************************
4190 * construct_printer_info_7
4191 * fill a printer_info_7 struct
4192 ********************************************************************/
4194 static BOOL construct_printer_info_7(PRINTER_INFO_7 *printer, int snum)
4196 char *guid_str = NULL;
4197 GUID guid;
4199 if (is_printer_published(snum, &guid)) {
4200 asprintf(&guid_str, "{%s}", uuid_string_static(guid));
4201 strupper(guid_str);
4202 init_unistr(&printer->guid, guid_str);
4203 printer->action = SPOOL_DS_PUBLISH;
4204 } else {
4205 init_unistr(&printer->guid, "");
4206 printer->action = SPOOL_DS_UNPUBLISH;
4209 return True;
4212 /********************************************************************
4213 Spoolss_enumprinters.
4214 ********************************************************************/
4216 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4218 int snum;
4219 int i;
4220 int n_services=lp_numservices();
4221 PRINTER_INFO_1 *tp, *printers=NULL;
4222 PRINTER_INFO_1 current_prt;
4224 DEBUG(4,("enum_all_printers_info_1\n"));
4226 for (snum=0; snum<n_services; snum++) {
4227 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4228 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4230 if (construct_printer_info_1(flags, &current_prt, snum)) {
4231 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4232 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4233 SAFE_FREE(printers);
4234 *returned=0;
4235 return WERR_NOMEM;
4237 else printers = tp;
4238 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4240 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4241 (*returned)++;
4246 /* check the required size. */
4247 for (i=0; i<*returned; i++)
4248 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4250 if (!alloc_buffer_size(buffer, *needed))
4251 return WERR_INSUFFICIENT_BUFFER;
4253 /* fill the buffer with the structures */
4254 for (i=0; i<*returned; i++)
4255 smb_io_printer_info_1("", buffer, &printers[i], 0);
4257 /* clear memory */
4258 SAFE_FREE(printers);
4260 if (*needed > offered) {
4261 *returned=0;
4262 return WERR_INSUFFICIENT_BUFFER;
4264 else
4265 return WERR_OK;
4268 /********************************************************************
4269 enum_all_printers_info_1_local.
4270 *********************************************************************/
4272 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4274 DEBUG(4,("enum_all_printers_info_1_local\n"));
4276 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4279 /********************************************************************
4280 enum_all_printers_info_1_name.
4281 *********************************************************************/
4283 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4285 char *s = name;
4287 DEBUG(4,("enum_all_printers_info_1_name\n"));
4289 if ((name[0] == '\\') && (name[1] == '\\'))
4290 s = name + 2;
4292 if (is_myname_or_ipaddr(s)) {
4293 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4295 else
4296 return WERR_INVALID_NAME;
4299 /********************************************************************
4300 enum_all_printers_info_1_remote.
4301 *********************************************************************/
4303 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4305 PRINTER_INFO_1 *printer;
4306 fstring printername;
4307 fstring desc;
4308 fstring comment;
4309 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4311 /* JFM: currently it's more a place holder than anything else.
4312 * In the spooler world there is a notion of server registration.
4313 * the print servers are registring (sp ?) on the PDC (in the same domain)
4315 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4318 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4319 return WERR_NOMEM;
4321 *returned=1;
4323 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4324 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4325 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4327 init_unistr(&printer->description, desc);
4328 init_unistr(&printer->name, printername);
4329 init_unistr(&printer->comment, comment);
4330 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4332 /* check the required size. */
4333 *needed += spoolss_size_printer_info_1(printer);
4335 if (!alloc_buffer_size(buffer, *needed)) {
4336 SAFE_FREE(printer);
4337 return WERR_INSUFFICIENT_BUFFER;
4340 /* fill the buffer with the structures */
4341 smb_io_printer_info_1("", buffer, printer, 0);
4343 /* clear memory */
4344 SAFE_FREE(printer);
4346 if (*needed > offered) {
4347 *returned=0;
4348 return WERR_INSUFFICIENT_BUFFER;
4350 else
4351 return WERR_OK;
4354 /********************************************************************
4355 enum_all_printers_info_1_network.
4356 *********************************************************************/
4358 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4360 char *s = name;
4362 DEBUG(4,("enum_all_printers_info_1_network\n"));
4364 /* If we respond to a enum_printers level 1 on our name with flags
4365 set to PRINTER_ENUM_REMOTE with a list of printers then these
4366 printers incorrectly appear in the APW browse list.
4367 Specifically the printers for the server appear at the workgroup
4368 level where all the other servers in the domain are
4369 listed. Windows responds to this call with a
4370 WERR_CAN_NOT_COMPLETE so we should do the same. */
4372 if (name[0] == '\\' && name[1] == '\\')
4373 s = name + 2;
4375 if (is_myname_or_ipaddr(s))
4376 return WERR_CAN_NOT_COMPLETE;
4378 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4381 /********************************************************************
4382 * api_spoolss_enumprinters
4384 * called from api_spoolss_enumprinters (see this to understand)
4385 ********************************************************************/
4387 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4389 int snum;
4390 int i;
4391 int n_services=lp_numservices();
4392 PRINTER_INFO_2 *tp, *printers=NULL;
4393 PRINTER_INFO_2 current_prt;
4395 for (snum=0; snum<n_services; snum++) {
4396 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4397 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4399 if (construct_printer_info_2(&current_prt, snum)) {
4400 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4401 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4402 SAFE_FREE(printers);
4403 *returned = 0;
4404 return WERR_NOMEM;
4406 else printers = tp;
4407 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4408 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4409 (*returned)++;
4414 /* check the required size. */
4415 for (i=0; i<*returned; i++)
4416 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4418 if (!alloc_buffer_size(buffer, *needed)) {
4419 for (i=0; i<*returned; i++) {
4420 free_devmode(printers[i].devmode);
4422 SAFE_FREE(printers);
4423 return WERR_INSUFFICIENT_BUFFER;
4426 /* fill the buffer with the structures */
4427 for (i=0; i<*returned; i++)
4428 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4430 /* clear memory */
4431 for (i=0; i<*returned; i++) {
4432 free_devmode(printers[i].devmode);
4434 SAFE_FREE(printers);
4436 if (*needed > offered) {
4437 *returned=0;
4438 return WERR_INSUFFICIENT_BUFFER;
4440 else
4441 return WERR_OK;
4444 /********************************************************************
4445 * handle enumeration of printers at level 1
4446 ********************************************************************/
4448 static WERROR enumprinters_level1( uint32 flags, fstring name,
4449 NEW_BUFFER *buffer, uint32 offered,
4450 uint32 *needed, uint32 *returned)
4452 /* Not all the flags are equals */
4454 if (flags & PRINTER_ENUM_LOCAL)
4455 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4457 if (flags & PRINTER_ENUM_NAME)
4458 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4460 if (flags & PRINTER_ENUM_REMOTE)
4461 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4463 if (flags & PRINTER_ENUM_NETWORK)
4464 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4466 return WERR_OK; /* NT4sp5 does that */
4469 /********************************************************************
4470 * handle enumeration of printers at level 2
4471 ********************************************************************/
4473 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4474 NEW_BUFFER *buffer, uint32 offered,
4475 uint32 *needed, uint32 *returned)
4477 char *s = servername;
4479 if (flags & PRINTER_ENUM_LOCAL) {
4480 return enum_all_printers_info_2(buffer, offered, needed, returned);
4483 if (flags & PRINTER_ENUM_NAME) {
4484 if ((servername[0] == '\\') && (servername[1] == '\\'))
4485 s = servername + 2;
4486 if (is_myname_or_ipaddr(s))
4487 return enum_all_printers_info_2(buffer, offered, needed, returned);
4488 else
4489 return WERR_INVALID_NAME;
4492 if (flags & PRINTER_ENUM_REMOTE)
4493 return WERR_UNKNOWN_LEVEL;
4495 return WERR_OK;
4498 /********************************************************************
4499 * handle enumeration of printers at level 5
4500 ********************************************************************/
4502 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4503 NEW_BUFFER *buffer, uint32 offered,
4504 uint32 *needed, uint32 *returned)
4506 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4507 return WERR_OK;
4510 /********************************************************************
4511 * api_spoolss_enumprinters
4513 * called from api_spoolss_enumprinters (see this to understand)
4514 ********************************************************************/
4516 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4518 uint32 flags = q_u->flags;
4519 UNISTR2 *servername = &q_u->servername;
4520 uint32 level = q_u->level;
4521 NEW_BUFFER *buffer = NULL;
4522 uint32 offered = q_u->offered;
4523 uint32 *needed = &r_u->needed;
4524 uint32 *returned = &r_u->returned;
4526 fstring name;
4528 /* that's an [in out] buffer */
4529 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4530 buffer = r_u->buffer;
4532 DEBUG(4,("_spoolss_enumprinters\n"));
4534 *needed=0;
4535 *returned=0;
4538 * Level 1:
4539 * flags==PRINTER_ENUM_NAME
4540 * if name=="" then enumerates all printers
4541 * if name!="" then enumerate the printer
4542 * flags==PRINTER_ENUM_REMOTE
4543 * name is NULL, enumerate printers
4544 * Level 2: name!="" enumerates printers, name can't be NULL
4545 * Level 3: doesn't exist
4546 * Level 4: does a local registry lookup
4547 * Level 5: same as Level 2
4550 unistr2_to_ascii(name, servername, sizeof(name)-1);
4551 strupper(name);
4553 switch (level) {
4554 case 1:
4555 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4556 case 2:
4557 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4558 case 5:
4559 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4560 case 3:
4561 case 4:
4562 break;
4564 return WERR_UNKNOWN_LEVEL;
4567 /****************************************************************************
4568 ****************************************************************************/
4570 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4572 PRINTER_INFO_0 *printer=NULL;
4574 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4575 return WERR_NOMEM;
4577 construct_printer_info_0(printer, snum);
4579 /* check the required size. */
4580 *needed += spoolss_size_printer_info_0(printer);
4582 if (!alloc_buffer_size(buffer, *needed)) {
4583 SAFE_FREE(printer);
4584 return WERR_INSUFFICIENT_BUFFER;
4587 /* fill the buffer with the structures */
4588 smb_io_printer_info_0("", buffer, printer, 0);
4590 /* clear memory */
4591 SAFE_FREE(printer);
4593 if (*needed > offered) {
4594 return WERR_INSUFFICIENT_BUFFER;
4597 return WERR_OK;
4600 /****************************************************************************
4601 ****************************************************************************/
4603 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4605 PRINTER_INFO_1 *printer=NULL;
4607 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4608 return WERR_NOMEM;
4610 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4612 /* check the required size. */
4613 *needed += spoolss_size_printer_info_1(printer);
4615 if (!alloc_buffer_size(buffer, *needed)) {
4616 SAFE_FREE(printer);
4617 return WERR_INSUFFICIENT_BUFFER;
4620 /* fill the buffer with the structures */
4621 smb_io_printer_info_1("", buffer, printer, 0);
4623 /* clear memory */
4624 SAFE_FREE(printer);
4626 if (*needed > offered) {
4627 return WERR_INSUFFICIENT_BUFFER;
4630 return WERR_OK;
4633 /****************************************************************************
4634 ****************************************************************************/
4636 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4638 PRINTER_INFO_2 *printer=NULL;
4640 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4641 return WERR_NOMEM;
4643 construct_printer_info_2(printer, snum);
4645 /* check the required size. */
4646 *needed += spoolss_size_printer_info_2(printer);
4648 if (!alloc_buffer_size(buffer, *needed)) {
4649 free_printer_info_2(printer);
4650 return WERR_INSUFFICIENT_BUFFER;
4653 /* fill the buffer with the structures */
4654 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4655 free_printer_info_2(printer);
4656 return WERR_NOMEM;
4659 /* clear memory */
4660 free_printer_info_2(printer);
4662 if (*needed > offered) {
4663 return WERR_INSUFFICIENT_BUFFER;
4666 return WERR_OK;
4669 /****************************************************************************
4670 ****************************************************************************/
4672 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4674 PRINTER_INFO_3 *printer=NULL;
4676 if (!construct_printer_info_3(&printer, snum))
4677 return WERR_NOMEM;
4679 /* check the required size. */
4680 *needed += spoolss_size_printer_info_3(printer);
4682 if (!alloc_buffer_size(buffer, *needed)) {
4683 free_printer_info_3(printer);
4684 return WERR_INSUFFICIENT_BUFFER;
4687 /* fill the buffer with the structures */
4688 smb_io_printer_info_3("", buffer, printer, 0);
4690 /* clear memory */
4691 free_printer_info_3(printer);
4693 if (*needed > offered) {
4694 return WERR_INSUFFICIENT_BUFFER;
4697 return WERR_OK;
4700 /****************************************************************************
4701 ****************************************************************************/
4703 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4705 PRINTER_INFO_4 *printer=NULL;
4707 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4708 return WERR_NOMEM;
4710 if (!construct_printer_info_4(printer, snum))
4711 return WERR_NOMEM;
4713 /* check the required size. */
4714 *needed += spoolss_size_printer_info_4(printer);
4716 if (!alloc_buffer_size(buffer, *needed)) {
4717 free_printer_info_4(printer);
4718 return WERR_INSUFFICIENT_BUFFER;
4721 /* fill the buffer with the structures */
4722 smb_io_printer_info_4("", buffer, printer, 0);
4724 /* clear memory */
4725 free_printer_info_4(printer);
4727 if (*needed > offered) {
4728 return WERR_INSUFFICIENT_BUFFER;
4731 return WERR_OK;
4734 /****************************************************************************
4735 ****************************************************************************/
4737 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4739 PRINTER_INFO_5 *printer=NULL;
4741 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4742 return WERR_NOMEM;
4744 if (!construct_printer_info_5(printer, snum))
4745 return WERR_NOMEM;
4747 /* check the required size. */
4748 *needed += spoolss_size_printer_info_5(printer);
4750 if (!alloc_buffer_size(buffer, *needed)) {
4751 free_printer_info_5(printer);
4752 return WERR_INSUFFICIENT_BUFFER;
4755 /* fill the buffer with the structures */
4756 smb_io_printer_info_5("", buffer, printer, 0);
4758 /* clear memory */
4759 free_printer_info_5(printer);
4761 if (*needed > offered) {
4762 return WERR_INSUFFICIENT_BUFFER;
4765 return WERR_OK;
4768 static WERROR getprinter_level_7(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4770 PRINTER_INFO_7 *printer=NULL;
4772 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4773 return WERR_NOMEM;
4775 if (!construct_printer_info_7(printer, snum))
4776 return WERR_NOMEM;
4778 /* check the required size. */
4779 *needed += spoolss_size_printer_info_7(printer);
4781 if (!alloc_buffer_size(buffer, *needed)) {
4782 free_printer_info_7(printer);
4783 return WERR_INSUFFICIENT_BUFFER;
4786 /* fill the buffer with the structures */
4787 smb_io_printer_info_7("", buffer, printer, 0);
4789 /* clear memory */
4790 free_printer_info_7(printer);
4792 if (*needed > offered) {
4793 return WERR_INSUFFICIENT_BUFFER;
4796 return WERR_OK;
4799 /****************************************************************************
4800 ****************************************************************************/
4802 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4804 POLICY_HND *handle = &q_u->handle;
4805 uint32 level = q_u->level;
4806 NEW_BUFFER *buffer = NULL;
4807 uint32 offered = q_u->offered;
4808 uint32 *needed = &r_u->needed;
4810 int snum;
4812 /* that's an [in out] buffer */
4813 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4814 buffer = r_u->buffer;
4816 *needed=0;
4818 if (!get_printer_snum(p, handle, &snum))
4819 return WERR_BADFID;
4821 switch (level) {
4822 case 0:
4823 return getprinter_level_0(snum, buffer, offered, needed);
4824 case 1:
4825 return getprinter_level_1(snum, buffer, offered, needed);
4826 case 2:
4827 return getprinter_level_2(snum, buffer, offered, needed);
4828 case 3:
4829 return getprinter_level_3(snum, buffer, offered, needed);
4830 case 4:
4831 return getprinter_level_4(snum, buffer, offered, needed);
4832 case 5:
4833 return getprinter_level_5(snum, buffer, offered, needed);
4834 case 7:
4835 return getprinter_level_7(snum, buffer, offered, needed);
4837 return WERR_UNKNOWN_LEVEL;
4840 /********************************************************************
4841 * fill a DRIVER_INFO_1 struct
4842 ********************************************************************/
4844 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4846 init_unistr( &info->name, driver.info_3->name);
4849 /********************************************************************
4850 * construct_printer_driver_info_1
4851 ********************************************************************/
4853 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4855 NT_PRINTER_INFO_LEVEL *printer = NULL;
4856 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4858 ZERO_STRUCT(driver);
4860 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4861 return WERR_INVALID_PRINTER_NAME;
4863 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4864 return WERR_UNKNOWN_PRINTER_DRIVER;
4866 fill_printer_driver_info_1(info, driver, servername, architecture);
4868 free_a_printer(&printer,2);
4870 return WERR_OK;
4873 /********************************************************************
4874 * construct_printer_driver_info_2
4875 * fill a printer_info_2 struct
4876 ********************************************************************/
4878 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4880 pstring temp;
4882 info->version=driver.info_3->cversion;
4884 init_unistr( &info->name, driver.info_3->name );
4885 init_unistr( &info->architecture, driver.info_3->environment );
4888 if (strlen(driver.info_3->driverpath)) {
4889 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4890 init_unistr( &info->driverpath, temp );
4891 } else
4892 init_unistr( &info->driverpath, "" );
4894 if (strlen(driver.info_3->datafile)) {
4895 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4896 init_unistr( &info->datafile, temp );
4897 } else
4898 init_unistr( &info->datafile, "" );
4900 if (strlen(driver.info_3->configfile)) {
4901 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4902 init_unistr( &info->configfile, temp );
4903 } else
4904 init_unistr( &info->configfile, "" );
4907 /********************************************************************
4908 * construct_printer_driver_info_2
4909 * fill a printer_info_2 struct
4910 ********************************************************************/
4912 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4914 NT_PRINTER_INFO_LEVEL *printer = NULL;
4915 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4917 ZERO_STRUCT(printer);
4918 ZERO_STRUCT(driver);
4920 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4921 return WERR_INVALID_PRINTER_NAME;
4923 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4924 return WERR_UNKNOWN_PRINTER_DRIVER;
4926 fill_printer_driver_info_2(info, driver, servername);
4928 free_a_printer(&printer,2);
4930 return WERR_OK;
4933 /********************************************************************
4934 * copy a strings array and convert to UNICODE
4936 * convert an array of ascii string to a UNICODE string
4937 ********************************************************************/
4939 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
4941 int i=0;
4942 int j=0;
4943 const char *v;
4944 pstring line;
4945 uint16 *tuary;
4947 DEBUG(6,("init_unistr_array\n"));
4948 *uni_array=NULL;
4950 while (True)
4952 if ( !char_array )
4953 v = "";
4954 else
4956 v = char_array[i];
4957 if (!v)
4958 v = ""; /* hack to handle null lists */
4961 /* hack to allow this to be used in places other than when generating
4962 the list of dependent files */
4964 if ( servername )
4965 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4966 else
4967 pstrcpy( line, v );
4969 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4971 /* add one extra unit16 for the second terminating NULL */
4973 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4974 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4975 return 0;
4976 } else
4977 *uni_array = tuary;
4979 if ( !strlen(v) )
4980 break;
4982 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4983 i++;
4986 if (*uni_array) {
4987 /* special case for ""; we need to add both NULL's here */
4988 if (!j)
4989 (*uni_array)[j++]=0x0000;
4990 (*uni_array)[j]=0x0000;
4993 DEBUGADD(6,("last one:done\n"));
4995 /* return size of array in uint16's */
4997 return j+1;
5000 /********************************************************************
5001 * construct_printer_info_3
5002 * fill a printer_info_3 struct
5003 ********************************************************************/
5005 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5007 pstring temp;
5009 ZERO_STRUCTP(info);
5011 info->version=driver.info_3->cversion;
5013 init_unistr( &info->name, driver.info_3->name );
5014 init_unistr( &info->architecture, driver.info_3->environment );
5016 if (strlen(driver.info_3->driverpath)) {
5017 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5018 init_unistr( &info->driverpath, temp );
5019 } else
5020 init_unistr( &info->driverpath, "" );
5022 if (strlen(driver.info_3->datafile)) {
5023 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5024 init_unistr( &info->datafile, temp );
5025 } else
5026 init_unistr( &info->datafile, "" );
5028 if (strlen(driver.info_3->configfile)) {
5029 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5030 init_unistr( &info->configfile, temp );
5031 } else
5032 init_unistr( &info->configfile, "" );
5034 if (strlen(driver.info_3->helpfile)) {
5035 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5036 init_unistr( &info->helpfile, temp );
5037 } else
5038 init_unistr( &info->helpfile, "" );
5040 init_unistr( &info->monitorname, driver.info_3->monitorname );
5041 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5043 info->dependentfiles=NULL;
5044 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5047 /********************************************************************
5048 * construct_printer_info_3
5049 * fill a printer_info_3 struct
5050 ********************************************************************/
5052 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5054 NT_PRINTER_INFO_LEVEL *printer = NULL;
5055 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5056 WERROR status;
5057 ZERO_STRUCT(driver);
5059 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5060 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5061 if (!W_ERROR_IS_OK(status))
5062 return WERR_INVALID_PRINTER_NAME;
5064 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5065 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5067 #if 0 /* JERRY */
5070 * I put this code in during testing. Helpful when commenting out the
5071 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5072 * as win2k always queries the driver using an infor level of 6.
5073 * I've left it in (but ifdef'd out) because I'll probably
5074 * use it in experimentation again in the future. --jerry 22/01/2002
5077 if (!W_ERROR_IS_OK(status)) {
5079 * Is this a W2k client ?
5081 if (version == 3) {
5082 /* Yes - try again with a WinNT driver. */
5083 version = 2;
5084 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5085 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5087 #endif
5089 if (!W_ERROR_IS_OK(status)) {
5090 free_a_printer(&printer,2);
5091 return WERR_UNKNOWN_PRINTER_DRIVER;
5094 #if 0 /* JERRY */
5096 #endif
5099 fill_printer_driver_info_3(info, driver, servername);
5101 free_a_printer(&printer,2);
5103 return WERR_OK;
5106 /********************************************************************
5107 * construct_printer_info_6
5108 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5109 ********************************************************************/
5111 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5113 pstring temp;
5114 fstring nullstr;
5116 ZERO_STRUCTP(info);
5117 memset(&nullstr, '\0', sizeof(fstring));
5119 info->version=driver.info_3->cversion;
5121 init_unistr( &info->name, driver.info_3->name );
5122 init_unistr( &info->architecture, driver.info_3->environment );
5124 if (strlen(driver.info_3->driverpath)) {
5125 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5126 init_unistr( &info->driverpath, temp );
5127 } else
5128 init_unistr( &info->driverpath, "" );
5130 if (strlen(driver.info_3->datafile)) {
5131 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5132 init_unistr( &info->datafile, temp );
5133 } else
5134 init_unistr( &info->datafile, "" );
5136 if (strlen(driver.info_3->configfile)) {
5137 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5138 init_unistr( &info->configfile, temp );
5139 } else
5140 init_unistr( &info->configfile, "" );
5142 if (strlen(driver.info_3->helpfile)) {
5143 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5144 init_unistr( &info->helpfile, temp );
5145 } else
5146 init_unistr( &info->helpfile, "" );
5148 init_unistr( &info->monitorname, driver.info_3->monitorname );
5149 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5151 info->dependentfiles = NULL;
5152 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5154 info->previousdrivernames=NULL;
5155 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5157 info->driver_date.low=0;
5158 info->driver_date.high=0;
5160 info->padding=0;
5161 info->driver_version_low=0;
5162 info->driver_version_high=0;
5164 init_unistr( &info->mfgname, "");
5165 init_unistr( &info->oem_url, "");
5166 init_unistr( &info->hardware_id, "");
5167 init_unistr( &info->provider, "");
5170 /********************************************************************
5171 * construct_printer_info_6
5172 * fill a printer_info_6 struct
5173 ********************************************************************/
5175 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5176 fstring servername, fstring architecture, uint32 version)
5178 NT_PRINTER_INFO_LEVEL *printer = NULL;
5179 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5180 WERROR status;
5182 ZERO_STRUCT(driver);
5184 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5186 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5188 if (!W_ERROR_IS_OK(status))
5189 return WERR_INVALID_PRINTER_NAME;
5191 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5193 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5195 if (!W_ERROR_IS_OK(status))
5198 * Is this a W2k client ?
5201 if (version < 3) {
5202 free_a_printer(&printer,2);
5203 return WERR_UNKNOWN_PRINTER_DRIVER;
5206 /* Yes - try again with a WinNT driver. */
5207 version = 2;
5208 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5209 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5210 if (!W_ERROR_IS_OK(status)) {
5211 free_a_printer(&printer,2);
5212 return WERR_UNKNOWN_PRINTER_DRIVER;
5216 fill_printer_driver_info_6(info, driver, servername);
5218 free_a_printer(&printer,2);
5219 free_a_printer_driver(driver, 3);
5221 return WERR_OK;
5224 /****************************************************************************
5225 ****************************************************************************/
5227 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5229 SAFE_FREE(info->dependentfiles);
5232 /****************************************************************************
5233 ****************************************************************************/
5235 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5237 SAFE_FREE(info->dependentfiles);
5241 /****************************************************************************
5242 ****************************************************************************/
5244 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5246 DRIVER_INFO_1 *info=NULL;
5247 WERROR status;
5249 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5250 return WERR_NOMEM;
5252 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5253 if (!W_ERROR_IS_OK(status)) {
5254 SAFE_FREE(info);
5255 return status;
5258 /* check the required size. */
5259 *needed += spoolss_size_printer_driver_info_1(info);
5261 if (!alloc_buffer_size(buffer, *needed)) {
5262 SAFE_FREE(info);
5263 return WERR_INSUFFICIENT_BUFFER;
5266 /* fill the buffer with the structures */
5267 smb_io_printer_driver_info_1("", buffer, info, 0);
5269 /* clear memory */
5270 SAFE_FREE(info);
5272 if (*needed > offered)
5273 return WERR_INSUFFICIENT_BUFFER;
5275 return WERR_OK;
5278 /****************************************************************************
5279 ****************************************************************************/
5281 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5283 DRIVER_INFO_2 *info=NULL;
5284 WERROR status;
5286 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5287 return WERR_NOMEM;
5289 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5290 if (!W_ERROR_IS_OK(status)) {
5291 SAFE_FREE(info);
5292 return status;
5295 /* check the required size. */
5296 *needed += spoolss_size_printer_driver_info_2(info);
5298 if (!alloc_buffer_size(buffer, *needed)) {
5299 SAFE_FREE(info);
5300 return WERR_INSUFFICIENT_BUFFER;
5303 /* fill the buffer with the structures */
5304 smb_io_printer_driver_info_2("", buffer, info, 0);
5306 /* clear memory */
5307 SAFE_FREE(info);
5309 if (*needed > offered)
5310 return WERR_INSUFFICIENT_BUFFER;
5312 return WERR_OK;
5315 /****************************************************************************
5316 ****************************************************************************/
5318 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5320 DRIVER_INFO_3 info;
5321 WERROR status;
5323 ZERO_STRUCT(info);
5325 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5326 if (!W_ERROR_IS_OK(status)) {
5327 return status;
5330 /* check the required size. */
5331 *needed += spoolss_size_printer_driver_info_3(&info);
5333 if (!alloc_buffer_size(buffer, *needed)) {
5334 free_printer_driver_info_3(&info);
5335 return WERR_INSUFFICIENT_BUFFER;
5338 /* fill the buffer with the structures */
5339 smb_io_printer_driver_info_3("", buffer, &info, 0);
5341 free_printer_driver_info_3(&info);
5343 if (*needed > offered)
5344 return WERR_INSUFFICIENT_BUFFER;
5346 return WERR_OK;
5349 /****************************************************************************
5350 ****************************************************************************/
5352 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5354 DRIVER_INFO_6 info;
5355 WERROR status;
5357 ZERO_STRUCT(info);
5359 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5360 if (!W_ERROR_IS_OK(status)) {
5361 return status;
5364 /* check the required size. */
5365 *needed += spoolss_size_printer_driver_info_6(&info);
5367 if (!alloc_buffer_size(buffer, *needed)) {
5368 free_printer_driver_info_6(&info);
5369 return WERR_INSUFFICIENT_BUFFER;
5372 /* fill the buffer with the structures */
5373 smb_io_printer_driver_info_6("", buffer, &info, 0);
5375 free_printer_driver_info_6(&info);
5377 if (*needed > offered)
5378 return WERR_INSUFFICIENT_BUFFER;
5380 return WERR_OK;
5383 /****************************************************************************
5384 ****************************************************************************/
5386 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5388 POLICY_HND *handle = &q_u->handle;
5389 UNISTR2 *uni_arch = &q_u->architecture;
5390 uint32 level = q_u->level;
5391 uint32 clientmajorversion = q_u->clientmajorversion;
5392 NEW_BUFFER *buffer = NULL;
5393 uint32 offered = q_u->offered;
5394 uint32 *needed = &r_u->needed;
5395 uint32 *servermajorversion = &r_u->servermajorversion;
5396 uint32 *serverminorversion = &r_u->serverminorversion;
5398 fstring servername;
5399 fstring architecture;
5400 int snum;
5402 /* that's an [in out] buffer */
5403 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5404 buffer = r_u->buffer;
5406 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5408 *needed = 0;
5409 *servermajorversion = 0;
5410 *serverminorversion = 0;
5412 fstrcpy(servername, get_called_name());
5413 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5415 if (!get_printer_snum(p, handle, &snum))
5416 return WERR_BADFID;
5418 switch (level) {
5419 case 1:
5420 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5421 case 2:
5422 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5423 case 3:
5424 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5425 case 6:
5426 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5429 return WERR_UNKNOWN_LEVEL;
5432 /****************************************************************************
5433 ****************************************************************************/
5435 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5437 POLICY_HND *handle = &q_u->handle;
5439 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5441 if (!Printer) {
5442 DEBUG(3,("Error in startpageprinter printer handle\n"));
5443 return WERR_BADFID;
5446 Printer->page_started=True;
5447 return WERR_OK;
5450 /****************************************************************************
5451 ****************************************************************************/
5453 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5455 POLICY_HND *handle = &q_u->handle;
5456 int snum;
5458 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5460 if (!Printer) {
5461 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5462 return WERR_BADFID;
5465 if (!get_printer_snum(p, handle, &snum))
5466 return WERR_BADFID;
5468 Printer->page_started=False;
5469 print_job_endpage(snum, Printer->jobid);
5471 return WERR_OK;
5474 /********************************************************************
5475 * api_spoolss_getprinter
5476 * called from the spoolss dispatcher
5478 ********************************************************************/
5480 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5482 POLICY_HND *handle = &q_u->handle;
5483 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5484 uint32 *jobid = &r_u->jobid;
5486 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5487 int snum;
5488 pstring jobname;
5489 fstring datatype;
5490 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5491 struct current_user user;
5493 if (!Printer) {
5494 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5495 return WERR_BADFID;
5498 get_current_user(&user, p);
5501 * a nice thing with NT is it doesn't listen to what you tell it.
5502 * when asked to send _only_ RAW datas, it tries to send datas
5503 * in EMF format.
5505 * So I add checks like in NT Server ...
5508 if (info_1->p_datatype != 0) {
5509 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5510 if (strcmp(datatype, "RAW") != 0) {
5511 (*jobid)=0;
5512 return WERR_INVALID_DATATYPE;
5516 /* get the share number of the printer */
5517 if (!get_printer_snum(p, handle, &snum)) {
5518 return WERR_BADFID;
5521 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5523 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5525 /* An error occured in print_job_start() so return an appropriate
5526 NT error code. */
5528 if (Printer->jobid == -1) {
5529 return map_werror_from_unix(errno);
5532 Printer->document_started=True;
5533 (*jobid) = Printer->jobid;
5535 return WERR_OK;
5538 /********************************************************************
5539 * api_spoolss_getprinter
5540 * called from the spoolss dispatcher
5542 ********************************************************************/
5544 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5546 POLICY_HND *handle = &q_u->handle;
5548 return _spoolss_enddocprinter_internal(p, handle);
5551 /****************************************************************************
5552 ****************************************************************************/
5554 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5556 POLICY_HND *handle = &q_u->handle;
5557 uint32 buffer_size = q_u->buffer_size;
5558 uint8 *buffer = q_u->buffer;
5559 uint32 *buffer_written = &q_u->buffer_size2;
5560 int snum;
5561 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5563 if (!Printer) {
5564 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5565 r_u->buffer_written = q_u->buffer_size2;
5566 return WERR_BADFID;
5569 if (!get_printer_snum(p, handle, &snum))
5570 return WERR_BADFID;
5572 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5573 if (*buffer_written == -1) {
5574 r_u->buffer_written = 0;
5575 if (errno == ENOSPC)
5576 return WERR_NO_SPOOL_SPACE;
5577 else
5578 return WERR_ACCESS_DENIED;
5581 r_u->buffer_written = q_u->buffer_size2;
5583 return WERR_OK;
5586 /********************************************************************
5587 * api_spoolss_getprinter
5588 * called from the spoolss dispatcher
5590 ********************************************************************/
5592 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5593 pipes_struct *p)
5595 struct current_user user;
5596 int snum;
5597 WERROR errcode = WERR_BADFUNC;
5598 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5600 get_current_user(&user, p);
5602 if (!Printer) {
5603 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5604 return WERR_BADFID;
5607 if (!get_printer_snum(p, handle, &snum))
5608 return WERR_BADFID;
5610 switch (command) {
5611 case PRINTER_CONTROL_PAUSE:
5612 if (print_queue_pause(&user, snum, &errcode)) {
5613 errcode = WERR_OK;
5615 break;
5616 case PRINTER_CONTROL_RESUME:
5617 case PRINTER_CONTROL_UNPAUSE:
5618 if (print_queue_resume(&user, snum, &errcode)) {
5619 errcode = WERR_OK;
5621 break;
5622 case PRINTER_CONTROL_PURGE:
5623 if (print_queue_purge(&user, snum, &errcode)) {
5624 errcode = WERR_OK;
5626 break;
5627 default:
5628 return WERR_UNKNOWN_LEVEL;
5631 return errcode;
5634 /********************************************************************
5635 * api_spoolss_abortprinter
5636 * From MSDN: "Deletes printer's spool file if printer is configured
5637 * for spooling"
5638 ********************************************************************/
5640 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5642 POLICY_HND *handle = &q_u->handle;
5643 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5644 int snum;
5645 struct current_user user;
5646 WERROR errcode = WERR_OK;
5648 if (!Printer) {
5649 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5650 return WERR_BADFID;
5653 if (!get_printer_snum(p, handle, &snum))
5654 return WERR_BADFID;
5656 get_current_user( &user, p );
5658 print_job_delete( &user, snum, Printer->jobid, &errcode );
5660 return errcode;
5663 /********************************************************************
5664 * called by spoolss_api_setprinter
5665 * when updating a printer description
5666 ********************************************************************/
5668 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5669 const SPOOL_PRINTER_INFO_LEVEL *info,
5670 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5672 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5673 struct current_user user;
5674 WERROR result;
5675 int snum;
5677 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5679 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5680 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5681 OUR_HANDLE(handle)));
5683 result = WERR_BADFID;
5684 goto done;
5687 /* NT seems to like setting the security descriptor even though
5688 nothing may have actually changed. This causes annoying
5689 dialog boxes when the user doesn't have permission to change
5690 the security descriptor. */
5692 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5694 if (DEBUGLEVEL >= 10) {
5695 SEC_ACL *the_acl;
5696 int i;
5698 the_acl = old_secdesc_ctr->sec->dacl;
5699 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5700 PRINTERNAME(snum), the_acl->num_aces));
5702 for (i = 0; i < the_acl->num_aces; i++) {
5703 fstring sid_str;
5705 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5707 DEBUG(10, ("%s 0x%08x\n", sid_str,
5708 the_acl->ace[i].info.mask));
5711 the_acl = secdesc_ctr->sec->dacl;
5713 if (the_acl) {
5714 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5715 PRINTERNAME(snum), the_acl->num_aces));
5717 for (i = 0; i < the_acl->num_aces; i++) {
5718 fstring sid_str;
5720 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5722 DEBUG(10, ("%s 0x%08x\n", sid_str,
5723 the_acl->ace[i].info.mask));
5725 } else {
5726 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5730 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5732 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5733 result = WERR_OK;
5734 goto done;
5737 /* Work out which user is performing the operation */
5739 get_current_user(&user, p);
5741 /* Check the user has permissions to change the security
5742 descriptor. By experimentation with two NT machines, the user
5743 requires Full Access to the printer to change security
5744 information. */
5746 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5747 result = WERR_ACCESS_DENIED;
5748 goto done;
5751 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5753 done:
5755 return result;
5758 /********************************************************************
5759 Do Samba sanity checks on a printer info struct.
5760 this has changed purpose: it now "canonicalises" printer
5761 info from a client rather than just checking it is correct
5762 ********************************************************************/
5764 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5766 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5767 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5769 /* we force some elements to "correct" values */
5770 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5771 fstrcpy(info->sharename, lp_servicename(snum));
5772 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5773 get_called_name(), info->sharename);
5774 info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;
5776 return True;
5779 /****************************************************************************
5780 ****************************************************************************/
5782 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5784 extern userdom_struct current_user_info;
5785 char *cmd = lp_addprinter_cmd();
5786 char **qlines;
5787 pstring command;
5788 int numlines;
5789 int ret;
5790 int fd;
5791 fstring remote_machine = "%m";
5793 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5795 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5796 cmd, printer->info_2->printername, printer->info_2->sharename,
5797 printer->info_2->portname, printer->info_2->drivername,
5798 printer->info_2->location, printer->info_2->comment, remote_machine);
5800 DEBUG(10,("Running [%s]\n", command));
5801 ret = smbrun(command, &fd);
5802 DEBUGADD(10,("returned [%d]\n", ret));
5804 if ( ret != 0 ) {
5805 if (fd != -1)
5806 close(fd);
5807 return False;
5810 numlines = 0;
5811 /* Get lines and convert them back to dos-codepage */
5812 qlines = fd_lines_load(fd, &numlines);
5813 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5814 close(fd);
5816 if(numlines) {
5817 /* Set the portname to what the script says the portname should be. */
5818 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5819 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5821 /* Send SIGHUP to process group... is there a better way? */
5822 kill(0, SIGHUP);
5824 /* reload our services immediately */
5825 reload_services( False );
5828 file_lines_free(qlines);
5829 return True;
5832 /********************************************************************
5833 * Called by spoolss_api_setprinter
5834 * when updating a printer description.
5835 ********************************************************************/
5837 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5838 const SPOOL_PRINTER_INFO_LEVEL *info,
5839 DEVICEMODE *devmode)
5841 int snum;
5842 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5843 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5844 WERROR result;
5846 DEBUG(8,("update_printer\n"));
5848 result = WERR_OK;
5850 if (level!=2) {
5851 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5852 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5853 result = WERR_UNKNOWN_LEVEL;
5854 goto done;
5857 if (!Printer) {
5858 result = WERR_BADFID;
5859 goto done;
5862 if (!get_printer_snum(p, handle, &snum)) {
5863 result = WERR_BADFID;
5864 goto done;
5867 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5868 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5869 result = WERR_BADFID;
5870 goto done;
5873 DEBUGADD(8,("Converting info_2 struct\n"));
5876 * convert_printer_info converts the incoming
5877 * info from the client and overwrites the info
5878 * just read from the tdb in the pointer 'printer'.
5881 if (!convert_printer_info(info, printer, level)) {
5882 result = WERR_NOMEM;
5883 goto done;
5886 if (devmode) {
5887 /* we have a valid devmode
5888 convert it and link it*/
5890 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5891 if (!convert_devicemode(printer->info_2->printername, devmode,
5892 &printer->info_2->devmode)) {
5893 result = WERR_NOMEM;
5894 goto done;
5898 * make sure we actually reload the services after
5899 * this as smb.conf could have a new section in it
5900 * .... shouldn't .... but could
5902 reload_services(False);
5905 /* Do sanity check on the requested changes for Samba */
5907 if (!check_printer_ok(printer->info_2, snum)) {
5908 result = WERR_INVALID_PARAM;
5909 goto done;
5912 /* Check calling user has permission to update printer description */
5914 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5915 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5916 result = WERR_ACCESS_DENIED;
5917 goto done;
5920 /* Call addprinter hook */
5921 /* Check changes to see if this is really needed */
5923 if ( *lp_addprinter_cmd()
5924 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5925 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5926 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5927 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5929 if ( !add_printer_hook(printer) ) {
5930 result = WERR_ACCESS_DENIED;
5931 goto done;
5936 * When a *new* driver is bound to a printer, the drivername is used to
5937 * lookup previously saved driver initialization info, which is then
5938 * bound to the printer, simulating what happens in the Windows arch.
5940 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5942 if (!set_driver_init(printer, 2))
5944 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5945 printer->info_2->drivername));
5948 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5949 printer->info_2->drivername));
5951 notify_printer_driver(snum, printer->info_2->drivername);
5954 /* Update printer info */
5955 result = mod_a_printer(*printer, 2);
5957 /* flag which changes actually occured. This is a small subset of
5958 all the possible changes */
5960 if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
5961 notify_printer_comment(snum, printer->info_2->comment);
5963 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
5964 notify_printer_sharename(snum, printer->info_2->sharename);
5966 if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
5967 notify_printer_port(snum, printer->info_2->portname);
5969 if (!strequal(printer->info_2->location, old_printer->info_2->location))
5970 notify_printer_location(snum, printer->info_2->location);
5972 done:
5973 free_a_printer(&printer, 2);
5974 free_a_printer(&old_printer, 2);
5977 return result;
5980 /****************************************************************************
5981 ****************************************************************************/
5982 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
5983 const SPOOL_PRINTER_INFO_LEVEL *info)
5985 #ifdef HAVE_ADS
5986 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
5987 int snum;
5988 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5989 WERROR result;
5991 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5993 result = WERR_OK;
5995 if (!Printer)
5996 return WERR_BADFID;
5998 if (!get_printer_snum(p, handle, &snum))
5999 return WERR_BADFID;
6001 nt_printer_publish(snum, info7->action);
6003 return WERR_OK;
6004 #else
6005 return WERR_UNKNOWN_LEVEL;
6006 #endif
6008 /****************************************************************************
6009 ****************************************************************************/
6011 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6013 POLICY_HND *handle = &q_u->handle;
6014 uint32 level = q_u->level;
6015 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6016 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6017 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6018 uint32 command = q_u->command;
6020 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6022 if (!Printer) {
6023 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6024 return WERR_BADFID;
6027 /* check the level */
6028 switch (level) {
6029 case 0:
6030 return control_printer(handle, command, p);
6031 case 2:
6032 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6033 case 3:
6034 return update_printer_sec(handle, level, info, p,
6035 secdesc_ctr);
6036 case 7:
6037 return publish_or_unpublish_printer(p, handle, info);
6038 default:
6039 return WERR_UNKNOWN_LEVEL;
6043 /****************************************************************************
6044 ****************************************************************************/
6046 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6048 POLICY_HND *handle = &q_u->handle;
6049 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6051 if (!Printer) {
6052 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6053 return WERR_BADFID;
6056 if (Printer->notify.client_connected==True) {
6057 int snum = -1;
6059 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6060 snum = -1;
6061 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6062 !get_printer_snum(p, handle, &snum) )
6063 return WERR_BADFID;
6065 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6068 Printer->notify.flags=0;
6069 Printer->notify.options=0;
6070 Printer->notify.localmachine[0]='\0';
6071 Printer->notify.printerlocal=0;
6072 if (Printer->notify.option)
6073 free_spool_notify_option(&Printer->notify.option);
6074 Printer->notify.client_connected=False;
6076 return WERR_OK;
6079 /****************************************************************************
6080 ****************************************************************************/
6082 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6084 /* that's an [in out] buffer (despite appearences to the contrary) */
6085 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6087 r_u->needed = 0;
6088 return WERR_INVALID_PARAM; /* this is what a NT server
6089 returns for AddJob. AddJob
6090 must fail on non-local
6091 printers */
6094 /****************************************************************************
6095 ****************************************************************************/
6097 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6098 int position, int snum)
6100 pstring temp_name;
6102 struct tm *t;
6104 t=gmtime(&queue->time);
6105 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6107 job_info->jobid=queue->job;
6108 init_unistr(&job_info->printername, lp_servicename(snum));
6109 init_unistr(&job_info->machinename, temp_name);
6110 init_unistr(&job_info->username, queue->fs_user);
6111 init_unistr(&job_info->document, queue->fs_file);
6112 init_unistr(&job_info->datatype, "RAW");
6113 init_unistr(&job_info->text_status, "");
6114 job_info->status=nt_printj_status(queue->status);
6115 job_info->priority=queue->priority;
6116 job_info->position=position;
6117 job_info->totalpages=queue->page_count;
6118 job_info->pagesprinted=0;
6120 make_systemtime(&job_info->submitted, t);
6123 /****************************************************************************
6124 ****************************************************************************/
6126 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6127 int position, int snum,
6128 NT_PRINTER_INFO_LEVEL *ntprinter,
6129 DEVICEMODE *devmode)
6131 pstring temp_name;
6132 pstring chaine;
6133 struct tm *t;
6135 t=gmtime(&queue->time);
6136 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6138 job_info->jobid=queue->job;
6140 slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
6142 init_unistr(&job_info->printername, chaine);
6144 init_unistr(&job_info->machinename, temp_name);
6145 init_unistr(&job_info->username, queue->fs_user);
6146 init_unistr(&job_info->document, queue->fs_file);
6147 init_unistr(&job_info->notifyname, queue->fs_user);
6148 init_unistr(&job_info->datatype, "RAW");
6149 init_unistr(&job_info->printprocessor, "winprint");
6150 init_unistr(&job_info->parameters, "");
6151 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6152 init_unistr(&job_info->text_status, "");
6154 /* and here the security descriptor */
6156 job_info->status=nt_printj_status(queue->status);
6157 job_info->priority=queue->priority;
6158 job_info->position=position;
6159 job_info->starttime=0;
6160 job_info->untiltime=0;
6161 job_info->totalpages=queue->page_count;
6162 job_info->size=queue->size;
6163 make_systemtime(&(job_info->submitted), t);
6164 job_info->timeelapsed=0;
6165 job_info->pagesprinted=0;
6167 job_info->devmode = devmode;
6169 return (True);
6172 /****************************************************************************
6173 Enumjobs at level 1.
6174 ****************************************************************************/
6176 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6177 NEW_BUFFER *buffer, uint32 offered,
6178 uint32 *needed, uint32 *returned)
6180 JOB_INFO_1 *info;
6181 int i;
6183 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6184 if (info==NULL) {
6185 SAFE_FREE(queue);
6186 *returned=0;
6187 return WERR_NOMEM;
6190 for (i=0; i<*returned; i++)
6191 fill_job_info_1(&info[i], &queue[i], i, snum);
6193 SAFE_FREE(queue);
6195 /* check the required size. */
6196 for (i=0; i<*returned; i++)
6197 (*needed) += spoolss_size_job_info_1(&info[i]);
6199 if (!alloc_buffer_size(buffer, *needed)) {
6200 SAFE_FREE(info);
6201 return WERR_INSUFFICIENT_BUFFER;
6204 /* fill the buffer with the structures */
6205 for (i=0; i<*returned; i++)
6206 smb_io_job_info_1("", buffer, &info[i], 0);
6208 /* clear memory */
6209 SAFE_FREE(info);
6211 if (*needed > offered) {
6212 *returned=0;
6213 return WERR_INSUFFICIENT_BUFFER;
6216 return WERR_OK;
6219 /****************************************************************************
6220 Enumjobs at level 2.
6221 ****************************************************************************/
6223 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6224 NEW_BUFFER *buffer, uint32 offered,
6225 uint32 *needed, uint32 *returned)
6227 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6228 JOB_INFO_2 *info = NULL;
6229 int i;
6230 WERROR result;
6231 DEVICEMODE *devmode = NULL;
6233 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6234 if (info==NULL) {
6235 *returned=0;
6236 result = WERR_NOMEM;
6237 goto done;
6240 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6241 if (!W_ERROR_IS_OK(result)) {
6242 *returned = 0;
6243 goto done;
6246 /* this should not be a failure condition if the devmode is NULL */
6248 devmode = construct_dev_mode(snum);
6250 for (i=0; i<*returned; i++)
6251 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6252 devmode);
6254 free_a_printer(&ntprinter, 2);
6255 SAFE_FREE(queue);
6257 /* check the required size. */
6258 for (i=0; i<*returned; i++)
6259 (*needed) += spoolss_size_job_info_2(&info[i]);
6261 if (*needed > offered) {
6262 *returned=0;
6263 result = WERR_INSUFFICIENT_BUFFER;
6264 goto done;
6267 if (!alloc_buffer_size(buffer, *needed)) {
6268 SAFE_FREE(info);
6269 result = WERR_INSUFFICIENT_BUFFER;
6270 goto done;
6273 /* fill the buffer with the structures */
6274 for (i=0; i<*returned; i++)
6275 smb_io_job_info_2("", buffer, &info[i], 0);
6277 result = WERR_OK;
6279 done:
6280 free_a_printer(&ntprinter, 2);
6281 free_devmode(devmode);
6282 SAFE_FREE(queue);
6283 SAFE_FREE(info);
6285 return result;
6289 /****************************************************************************
6290 Enumjobs.
6291 ****************************************************************************/
6293 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6295 POLICY_HND *handle = &q_u->handle;
6296 uint32 level = q_u->level;
6297 NEW_BUFFER *buffer = NULL;
6298 uint32 offered = q_u->offered;
6299 uint32 *needed = &r_u->needed;
6300 uint32 *returned = &r_u->returned;
6302 int snum;
6303 print_status_struct prt_status;
6304 print_queue_struct *queue=NULL;
6306 /* that's an [in out] buffer */
6307 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6308 buffer = r_u->buffer;
6310 DEBUG(4,("_spoolss_enumjobs\n"));
6312 *needed=0;
6313 *returned=0;
6315 if (!get_printer_snum(p, handle, &snum))
6316 return WERR_BADFID;
6318 *returned = print_queue_status(snum, &queue, &prt_status);
6319 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6321 if (*returned == 0) {
6322 SAFE_FREE(queue);
6323 return WERR_OK;
6326 switch (level) {
6327 case 1:
6328 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6329 case 2:
6330 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6331 default:
6332 SAFE_FREE(queue);
6333 *returned=0;
6334 return WERR_UNKNOWN_LEVEL;
6338 /****************************************************************************
6339 ****************************************************************************/
6341 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6343 return WERR_OK;
6346 /****************************************************************************
6347 ****************************************************************************/
6349 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6351 POLICY_HND *handle = &q_u->handle;
6352 uint32 jobid = q_u->jobid;
6353 uint32 command = q_u->command;
6355 struct current_user user;
6356 int snum;
6357 WERROR errcode = WERR_BADFUNC;
6359 if (!get_printer_snum(p, handle, &snum)) {
6360 return WERR_BADFID;
6363 if (!print_job_exists(snum, jobid)) {
6364 return WERR_INVALID_PRINTER_NAME;
6367 get_current_user(&user, p);
6369 switch (command) {
6370 case JOB_CONTROL_CANCEL:
6371 case JOB_CONTROL_DELETE:
6372 if (print_job_delete(&user, snum, jobid, &errcode)) {
6373 errcode = WERR_OK;
6375 break;
6376 case JOB_CONTROL_PAUSE:
6377 if (print_job_pause(&user, snum, jobid, &errcode)) {
6378 errcode = WERR_OK;
6380 break;
6381 case JOB_CONTROL_RESTART:
6382 case JOB_CONTROL_RESUME:
6383 if (print_job_resume(&user, snum, jobid, &errcode)) {
6384 errcode = WERR_OK;
6386 break;
6387 default:
6388 return WERR_UNKNOWN_LEVEL;
6391 return errcode;
6394 /****************************************************************************
6395 Enumerates all printer drivers at level 1.
6396 ****************************************************************************/
6398 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6400 int i;
6401 int ndrivers;
6402 uint32 version;
6403 fstring *list = NULL;
6405 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6406 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6408 *returned=0;
6410 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6411 list=NULL;
6412 ndrivers=get_ntdrivers(&list, architecture, version);
6413 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6415 if(ndrivers == -1)
6416 return WERR_NOMEM;
6418 if(ndrivers != 0) {
6419 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6420 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6421 SAFE_FREE(driver_info_1);
6422 SAFE_FREE(list);
6423 return WERR_NOMEM;
6425 else driver_info_1 = tdi1;
6428 for (i=0; i<ndrivers; i++) {
6429 WERROR status;
6430 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6431 ZERO_STRUCT(driver);
6432 status = get_a_printer_driver(&driver, 3, list[i],
6433 architecture, version);
6434 if (!W_ERROR_IS_OK(status)) {
6435 SAFE_FREE(list);
6436 return status;
6438 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6439 free_a_printer_driver(driver, 3);
6442 *returned+=ndrivers;
6443 SAFE_FREE(list);
6446 /* check the required size. */
6447 for (i=0; i<*returned; i++) {
6448 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6449 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6452 if (!alloc_buffer_size(buffer, *needed)) {
6453 SAFE_FREE(driver_info_1);
6454 return WERR_INSUFFICIENT_BUFFER;
6457 /* fill the buffer with the driver structures */
6458 for (i=0; i<*returned; i++) {
6459 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6460 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6463 SAFE_FREE(driver_info_1);
6465 if (*needed > offered) {
6466 *returned=0;
6467 return WERR_INSUFFICIENT_BUFFER;
6470 return WERR_OK;
6473 /****************************************************************************
6474 Enumerates all printer drivers at level 2.
6475 ****************************************************************************/
6477 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6479 int i;
6480 int ndrivers;
6481 uint32 version;
6482 fstring *list = NULL;
6484 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6485 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6487 *returned=0;
6489 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6490 list=NULL;
6491 ndrivers=get_ntdrivers(&list, architecture, version);
6492 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6494 if(ndrivers == -1)
6495 return WERR_NOMEM;
6497 if(ndrivers != 0) {
6498 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6499 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6500 SAFE_FREE(driver_info_2);
6501 SAFE_FREE(list);
6502 return WERR_NOMEM;
6504 else driver_info_2 = tdi2;
6507 for (i=0; i<ndrivers; i++) {
6508 WERROR status;
6510 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6511 ZERO_STRUCT(driver);
6512 status = get_a_printer_driver(&driver, 3, list[i],
6513 architecture, version);
6514 if (!W_ERROR_IS_OK(status)) {
6515 SAFE_FREE(list);
6516 return status;
6518 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6519 free_a_printer_driver(driver, 3);
6522 *returned+=ndrivers;
6523 SAFE_FREE(list);
6526 /* check the required size. */
6527 for (i=0; i<*returned; i++) {
6528 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6529 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6532 if (!alloc_buffer_size(buffer, *needed)) {
6533 SAFE_FREE(driver_info_2);
6534 return WERR_INSUFFICIENT_BUFFER;
6537 /* fill the buffer with the form structures */
6538 for (i=0; i<*returned; i++) {
6539 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6540 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6543 SAFE_FREE(driver_info_2);
6545 if (*needed > offered) {
6546 *returned=0;
6547 return WERR_INSUFFICIENT_BUFFER;
6550 return WERR_OK;
6553 /****************************************************************************
6554 Enumerates all printer drivers at level 3.
6555 ****************************************************************************/
6557 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6559 int i;
6560 int ndrivers;
6561 uint32 version;
6562 fstring *list = NULL;
6564 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6565 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6567 *returned=0;
6569 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6570 list=NULL;
6571 ndrivers=get_ntdrivers(&list, architecture, version);
6572 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6574 if(ndrivers == -1)
6575 return WERR_NOMEM;
6577 if(ndrivers != 0) {
6578 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6579 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6580 SAFE_FREE(driver_info_3);
6581 SAFE_FREE(list);
6582 return WERR_NOMEM;
6584 else driver_info_3 = tdi3;
6587 for (i=0; i<ndrivers; i++) {
6588 WERROR status;
6590 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6591 ZERO_STRUCT(driver);
6592 status = get_a_printer_driver(&driver, 3, list[i],
6593 architecture, version);
6594 if (!W_ERROR_IS_OK(status)) {
6595 SAFE_FREE(list);
6596 return status;
6598 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6599 free_a_printer_driver(driver, 3);
6602 *returned+=ndrivers;
6603 SAFE_FREE(list);
6606 /* check the required size. */
6607 for (i=0; i<*returned; i++) {
6608 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6609 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6612 if (!alloc_buffer_size(buffer, *needed)) {
6613 SAFE_FREE(driver_info_3);
6614 return WERR_INSUFFICIENT_BUFFER;
6617 /* fill the buffer with the driver structures */
6618 for (i=0; i<*returned; i++) {
6619 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6620 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6623 for (i=0; i<*returned; i++)
6624 SAFE_FREE(driver_info_3[i].dependentfiles);
6626 SAFE_FREE(driver_info_3);
6628 if (*needed > offered) {
6629 *returned=0;
6630 return WERR_INSUFFICIENT_BUFFER;
6633 return WERR_OK;
6636 /****************************************************************************
6637 Enumerates all printer drivers.
6638 ****************************************************************************/
6640 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6642 UNISTR2 *environment = &q_u->environment;
6643 uint32 level = q_u->level;
6644 NEW_BUFFER *buffer = NULL;
6645 uint32 offered = q_u->offered;
6646 uint32 *needed = &r_u->needed;
6647 uint32 *returned = &r_u->returned;
6649 fstring *list = NULL;
6650 fstring servername;
6651 fstring architecture;
6653 /* that's an [in out] buffer */
6654 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6655 buffer = r_u->buffer;
6657 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6658 fstrcpy(servername, get_called_name());
6659 *needed=0;
6660 *returned=0;
6662 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6664 switch (level) {
6665 case 1:
6666 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6667 case 2:
6668 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6669 case 3:
6670 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6671 default:
6672 *returned=0;
6673 SAFE_FREE(list);
6674 return WERR_UNKNOWN_LEVEL;
6678 /****************************************************************************
6679 ****************************************************************************/
6681 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6683 form->flag=list->flag;
6684 init_unistr(&form->name, list->name);
6685 form->width=list->width;
6686 form->length=list->length;
6687 form->left=list->left;
6688 form->top=list->top;
6689 form->right=list->right;
6690 form->bottom=list->bottom;
6693 /****************************************************************************
6694 ****************************************************************************/
6696 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6698 uint32 level = q_u->level;
6699 NEW_BUFFER *buffer = NULL;
6700 uint32 offered = q_u->offered;
6701 uint32 *needed = &r_u->needed;
6702 uint32 *numofforms = &r_u->numofforms;
6703 uint32 numbuiltinforms;
6705 nt_forms_struct *list=NULL;
6706 nt_forms_struct *builtinlist=NULL;
6707 FORM_1 *forms_1;
6708 int buffer_size=0;
6709 int i;
6711 /* that's an [in out] buffer */
6712 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6713 buffer = r_u->buffer;
6715 DEBUG(4,("_spoolss_enumforms\n"));
6716 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6717 DEBUGADD(5,("Info level [%d]\n", level));
6719 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6720 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6721 *numofforms = get_ntforms(&list);
6722 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6723 *numofforms += numbuiltinforms;
6725 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6727 switch (level) {
6728 case 1:
6729 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6730 *numofforms=0;
6731 return WERR_NOMEM;
6734 /* construct the list of form structures */
6735 for (i=0; i<numbuiltinforms; i++) {
6736 DEBUGADD(6,("Filling form number [%d]\n",i));
6737 fill_form_1(&forms_1[i], &builtinlist[i]);
6740 SAFE_FREE(builtinlist);
6742 for (; i<*numofforms; i++) {
6743 DEBUGADD(6,("Filling form number [%d]\n",i));
6744 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6747 SAFE_FREE(list);
6749 /* check the required size. */
6750 for (i=0; i<numbuiltinforms; i++) {
6751 DEBUGADD(6,("adding form [%d]'s size\n",i));
6752 buffer_size += spoolss_size_form_1(&forms_1[i]);
6754 for (; i<*numofforms; i++) {
6755 DEBUGADD(6,("adding form [%d]'s size\n",i));
6756 buffer_size += spoolss_size_form_1(&forms_1[i]);
6759 *needed=buffer_size;
6761 if (!alloc_buffer_size(buffer, buffer_size)){
6762 SAFE_FREE(forms_1);
6763 return WERR_INSUFFICIENT_BUFFER;
6766 /* fill the buffer with the form structures */
6767 for (i=0; i<numbuiltinforms; i++) {
6768 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6769 smb_io_form_1("", buffer, &forms_1[i], 0);
6771 for (; i<*numofforms; i++) {
6772 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6773 smb_io_form_1("", buffer, &forms_1[i], 0);
6776 SAFE_FREE(forms_1);
6778 if (*needed > offered) {
6779 *numofforms=0;
6780 return WERR_INSUFFICIENT_BUFFER;
6782 else
6783 return WERR_OK;
6785 default:
6786 SAFE_FREE(list);
6787 SAFE_FREE(builtinlist);
6788 return WERR_UNKNOWN_LEVEL;
6793 /****************************************************************************
6794 ****************************************************************************/
6796 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6798 uint32 level = q_u->level;
6799 UNISTR2 *uni_formname = &q_u->formname;
6800 NEW_BUFFER *buffer = NULL;
6801 uint32 offered = q_u->offered;
6802 uint32 *needed = &r_u->needed;
6804 nt_forms_struct *list=NULL;
6805 nt_forms_struct builtin_form;
6806 BOOL foundBuiltin;
6807 FORM_1 form_1;
6808 fstring form_name;
6809 int buffer_size=0;
6810 int numofforms=0, i=0;
6812 /* that's an [in out] buffer */
6813 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6814 buffer = r_u->buffer;
6816 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6818 DEBUG(4,("_spoolss_getform\n"));
6819 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6820 DEBUGADD(5,("Info level [%d]\n", level));
6822 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6823 if (!foundBuiltin) {
6824 numofforms = get_ntforms(&list);
6825 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6827 if (numofforms == 0)
6828 return WERR_BADFID;
6831 switch (level) {
6832 case 1:
6833 if (foundBuiltin) {
6834 fill_form_1(&form_1, &builtin_form);
6835 } else {
6837 /* Check if the requested name is in the list of form structures */
6838 for (i=0; i<numofforms; i++) {
6840 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6842 if (strequal(form_name, list[i].name)) {
6843 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6844 fill_form_1(&form_1, &list[i]);
6845 break;
6849 SAFE_FREE(list);
6850 if (i == numofforms) {
6851 return WERR_BADFID;
6854 /* check the required size. */
6856 *needed=spoolss_size_form_1(&form_1);
6858 if (!alloc_buffer_size(buffer, buffer_size)){
6859 return WERR_INSUFFICIENT_BUFFER;
6862 if (*needed > offered) {
6863 return WERR_INSUFFICIENT_BUFFER;
6866 /* fill the buffer with the form structures */
6867 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6868 smb_io_form_1("", buffer, &form_1, 0);
6870 return WERR_OK;
6872 default:
6873 SAFE_FREE(list);
6874 return WERR_UNKNOWN_LEVEL;
6878 /****************************************************************************
6879 ****************************************************************************/
6881 static void fill_port_1(PORT_INFO_1 *port, const char *name)
6883 init_unistr(&port->port_name, name);
6886 /****************************************************************************
6887 ****************************************************************************/
6889 static void fill_port_2(PORT_INFO_2 *port, const char *name)
6891 init_unistr(&port->port_name, name);
6892 init_unistr(&port->monitor_name, "Local Monitor");
6893 init_unistr(&port->description, "Local Port");
6894 #define PORT_TYPE_WRITE 1
6895 port->port_type=PORT_TYPE_WRITE;
6896 port->reserved=0x0;
6899 /****************************************************************************
6900 enumports level 1.
6901 ****************************************************************************/
6903 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6905 PORT_INFO_1 *ports=NULL;
6906 int i=0;
6908 if (*lp_enumports_cmd()) {
6909 char *cmd = lp_enumports_cmd();
6910 char **qlines;
6911 pstring command;
6912 int numlines;
6913 int ret;
6914 int fd;
6916 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6918 DEBUG(10,("Running [%s]\n", command));
6919 ret = smbrun(command, &fd);
6920 DEBUG(10,("Returned [%d]\n", ret));
6921 if (ret != 0) {
6922 if (fd != -1)
6923 close(fd);
6924 /* Is this the best error to return here? */
6925 return WERR_ACCESS_DENIED;
6928 numlines = 0;
6929 qlines = fd_lines_load(fd, &numlines);
6930 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6931 close(fd);
6933 if(numlines) {
6934 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6935 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6936 dos_errstr(WERR_NOMEM)));
6937 file_lines_free(qlines);
6938 return WERR_NOMEM;
6941 for (i=0; i<numlines; i++) {
6942 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6943 fill_port_1(&ports[i], qlines[i]);
6946 file_lines_free(qlines);
6949 *returned = numlines;
6951 } else {
6952 *returned = 1; /* Sole Samba port returned. */
6954 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
6955 return WERR_NOMEM;
6957 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
6959 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
6962 /* check the required size. */
6963 for (i=0; i<*returned; i++) {
6964 DEBUGADD(6,("adding port [%d]'s size\n", i));
6965 *needed += spoolss_size_port_info_1(&ports[i]);
6968 if (!alloc_buffer_size(buffer, *needed)) {
6969 SAFE_FREE(ports);
6970 return WERR_INSUFFICIENT_BUFFER;
6973 /* fill the buffer with the ports structures */
6974 for (i=0; i<*returned; i++) {
6975 DEBUGADD(6,("adding port [%d] to buffer\n", i));
6976 smb_io_port_1("", buffer, &ports[i], 0);
6979 SAFE_FREE(ports);
6981 if (*needed > offered) {
6982 *returned=0;
6983 return WERR_INSUFFICIENT_BUFFER;
6986 return WERR_OK;
6989 /****************************************************************************
6990 enumports level 2.
6991 ****************************************************************************/
6993 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6995 PORT_INFO_2 *ports=NULL;
6996 int i=0;
6998 if (*lp_enumports_cmd()) {
6999 char *cmd = lp_enumports_cmd();
7000 char *path;
7001 char **qlines;
7002 pstring tmp_file;
7003 pstring command;
7004 int numlines;
7005 int ret;
7006 int fd;
7008 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7009 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7010 else
7011 path = lp_lockdir();
7013 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7014 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7016 unlink(tmp_file);
7017 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7018 ret = smbrun(command, &fd);
7019 DEBUGADD(10,("returned [%d]\n", ret));
7020 if (ret != 0) {
7021 if (fd != -1)
7022 close(fd);
7023 /* Is this the best error to return here? */
7024 return WERR_ACCESS_DENIED;
7027 numlines = 0;
7028 qlines = fd_lines_load(fd, &numlines);
7029 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7030 close(fd);
7032 if(numlines) {
7033 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7034 file_lines_free(qlines);
7035 return WERR_NOMEM;
7038 for (i=0; i<numlines; i++) {
7039 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7040 fill_port_2(&(ports[i]), qlines[i]);
7043 file_lines_free(qlines);
7046 *returned = numlines;
7048 } else {
7050 *returned = 1;
7052 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7053 return WERR_NOMEM;
7055 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7057 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7060 /* check the required size. */
7061 for (i=0; i<*returned; i++) {
7062 DEBUGADD(6,("adding port [%d]'s size\n", i));
7063 *needed += spoolss_size_port_info_2(&ports[i]);
7066 if (!alloc_buffer_size(buffer, *needed)) {
7067 SAFE_FREE(ports);
7068 return WERR_INSUFFICIENT_BUFFER;
7071 /* fill the buffer with the ports structures */
7072 for (i=0; i<*returned; i++) {
7073 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7074 smb_io_port_2("", buffer, &ports[i], 0);
7077 SAFE_FREE(ports);
7079 if (*needed > offered) {
7080 *returned=0;
7081 return WERR_INSUFFICIENT_BUFFER;
7084 return WERR_OK;
7087 /****************************************************************************
7088 enumports.
7089 ****************************************************************************/
7091 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7093 uint32 level = q_u->level;
7094 NEW_BUFFER *buffer = NULL;
7095 uint32 offered = q_u->offered;
7096 uint32 *needed = &r_u->needed;
7097 uint32 *returned = &r_u->returned;
7099 /* that's an [in out] buffer */
7100 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7101 buffer = r_u->buffer;
7103 DEBUG(4,("_spoolss_enumports\n"));
7105 *returned=0;
7106 *needed=0;
7108 switch (level) {
7109 case 1:
7110 return enumports_level_1(buffer, offered, needed, returned);
7111 case 2:
7112 return enumports_level_2(buffer, offered, needed, returned);
7113 default:
7114 return WERR_UNKNOWN_LEVEL;
7118 /****************************************************************************
7119 ****************************************************************************/
7121 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7122 const SPOOL_PRINTER_INFO_LEVEL *info,
7123 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7124 uint32 user_switch, const SPOOL_USER_CTR *user,
7125 POLICY_HND *handle)
7127 NT_PRINTER_INFO_LEVEL *printer = NULL;
7128 fstring name;
7129 int snum;
7130 WERROR err = WERR_OK;
7132 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7133 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7134 return WERR_NOMEM;
7137 ZERO_STRUCTP(printer);
7139 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7140 if (!convert_printer_info(info, printer, 2)) {
7141 free_a_printer(&printer, 2);
7142 return WERR_NOMEM;
7145 /* check to see if the printer already exists */
7147 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7148 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7149 printer->info_2->sharename));
7150 free_a_printer(&printer, 2);
7151 return WERR_PRINTER_ALREADY_EXISTS;
7154 if (*lp_addprinter_cmd() ) {
7155 if ( !add_printer_hook(printer) ) {
7156 free_a_printer(&printer,2);
7157 return WERR_ACCESS_DENIED;
7161 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7162 printer->info_2->sharename);
7165 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7166 free_a_printer(&printer,2);
7167 return WERR_ACCESS_DENIED;
7170 /* you must be a printer admin to add a new printer */
7171 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7172 free_a_printer(&printer,2);
7173 return WERR_ACCESS_DENIED;
7177 * Do sanity check on the requested changes for Samba.
7180 if (!check_printer_ok(printer->info_2, snum)) {
7181 free_a_printer(&printer,2);
7182 return WERR_INVALID_PARAM;
7186 * When a printer is created, the drivername bound to the printer is used
7187 * to lookup previously saved driver initialization info, which is then
7188 * bound to the new printer, simulating what happens in the Windows arch.
7191 if (!devmode)
7193 set_driver_init(printer, 2);
7195 else
7197 /* A valid devmode was included, convert and link it
7199 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7201 if (!convert_devicemode(printer->info_2->printername, devmode,
7202 &printer->info_2->devmode))
7203 return WERR_NOMEM;
7206 /* write the ASCII on disk */
7207 err = mod_a_printer(*printer, 2);
7208 if (!W_ERROR_IS_OK(err)) {
7209 free_a_printer(&printer,2);
7210 return err;
7213 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7214 /* Handle open failed - remove addition. */
7215 del_a_printer(printer->info_2->sharename);
7216 free_a_printer(&printer,2);
7217 return WERR_ACCESS_DENIED;
7220 update_c_setprinter(False);
7221 free_a_printer(&printer,2);
7223 return WERR_OK;
7226 /****************************************************************************
7227 ****************************************************************************/
7229 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7231 UNISTR2 *uni_srv_name = &q_u->server_name;
7232 uint32 level = q_u->level;
7233 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7234 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7235 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7236 uint32 user_switch = q_u->user_switch;
7237 SPOOL_USER_CTR *user = &q_u->user_ctr;
7238 POLICY_HND *handle = &r_u->handle;
7240 switch (level) {
7241 case 1:
7242 /* we don't handle yet */
7243 /* but I know what to do ... */
7244 return WERR_UNKNOWN_LEVEL;
7245 case 2:
7246 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7247 devmode, sdb,
7248 user_switch, user, handle);
7249 default:
7250 return WERR_UNKNOWN_LEVEL;
7254 /****************************************************************************
7255 ****************************************************************************/
7257 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7259 uint32 level = q_u->level;
7260 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7261 WERROR err = WERR_OK;
7262 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7263 struct current_user user;
7264 fstring driver_name;
7265 uint32 version;
7267 ZERO_STRUCT(driver);
7269 get_current_user(&user, p);
7271 if (!convert_printer_driver_info(info, &driver, level)) {
7272 err = WERR_NOMEM;
7273 goto done;
7276 DEBUG(5,("Cleaning driver's information\n"));
7277 err = clean_up_driver_struct(driver, level, &user);
7278 if (!W_ERROR_IS_OK(err))
7279 goto done;
7281 DEBUG(5,("Moving driver to final destination\n"));
7282 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7283 if (W_ERROR_IS_OK(err))
7284 err = WERR_ACCESS_DENIED;
7285 goto done;
7288 if (add_a_printer_driver(driver, level)!=0) {
7289 err = WERR_ACCESS_DENIED;
7290 goto done;
7293 /* BEGIN_ADMIN_LOG */
7294 switch(level) {
7295 case 3:
7296 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7297 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7298 fstrcpy(driver_name, driver.info_3->name);
7299 break;
7300 case 6:
7301 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7302 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7303 fstrcpy(driver_name, driver.info_6->name);
7304 break;
7306 /* END_ADMIN_LOG */
7309 * I think this is where he DrvUpgradePrinter() hook would be
7310 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7311 * server. Right now, we just need to send ourselves a message
7312 * to update each printer bound to this driver. --jerry
7315 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7316 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7317 driver_name));
7321 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7322 * decide if the driver init data should be deleted. The rules are:
7323 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7324 * 2) delete init data only if there is no 2k/Xp driver
7325 * 3) always delete init data
7326 * The generalized rule is always use init data from the highest order driver.
7327 * It is necessary to follow the driver install by an initialization step to
7328 * finish off this process.
7330 if (level == 3)
7331 version = driver.info_3->cversion;
7332 else if (level == 6)
7333 version = driver.info_6->version;
7334 else
7335 version = -1;
7336 switch (version) {
7338 * 9x printer driver - never delete init data
7340 case 0:
7341 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7342 driver_name));
7343 break;
7346 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7347 * there is no 2k/Xp driver init data for this driver name.
7349 case 2:
7351 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7353 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7355 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7357 if (!del_driver_init(driver_name))
7358 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7359 } else {
7361 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7363 free_a_printer_driver(driver1,3);
7364 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7365 driver_name));
7368 break;
7371 * 2k or Xp printer driver - always delete init data
7373 case 3:
7374 if (!del_driver_init(driver_name))
7375 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7376 break;
7378 default:
7379 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7380 break;
7384 done:
7385 free_a_printer_driver(driver, level);
7386 return err;
7389 /********************************************************************
7390 * spoolss_addprinterdriverex
7391 ********************************************************************/
7393 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7395 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7396 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7399 * we only support the semantics of AddPrinterDriver()
7400 * i.e. only copy files that are newer than existing ones
7403 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7404 return WERR_ACCESS_DENIED;
7406 ZERO_STRUCT(q_u_local);
7407 ZERO_STRUCT(r_u_local);
7409 /* just pass the information off to _spoolss_addprinterdriver() */
7410 q_u_local.server_name_ptr = q_u->server_name_ptr;
7411 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7412 q_u_local.level = q_u->level;
7413 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7415 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7418 /****************************************************************************
7419 ****************************************************************************/
7421 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7423 init_unistr(&info->name, name);
7426 /****************************************************************************
7427 ****************************************************************************/
7429 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7431 pstring path;
7432 pstring long_archi;
7433 pstring short_archi;
7434 DRIVER_DIRECTORY_1 *info=NULL;
7436 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7438 if (get_short_archi(short_archi, long_archi)==False)
7439 return WERR_INVALID_ENVIRONMENT;
7441 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7442 return WERR_NOMEM;
7444 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7446 DEBUG(4,("printer driver directory: [%s]\n", path));
7448 fill_driverdir_1(info, path);
7450 *needed += spoolss_size_driverdir_info_1(info);
7452 if (!alloc_buffer_size(buffer, *needed)) {
7453 SAFE_FREE(info);
7454 return WERR_INSUFFICIENT_BUFFER;
7457 smb_io_driverdir_1("", buffer, info, 0);
7459 SAFE_FREE(info);
7461 if (*needed > offered)
7462 return WERR_INSUFFICIENT_BUFFER;
7464 return WERR_OK;
7467 /****************************************************************************
7468 ****************************************************************************/
7470 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7472 UNISTR2 *name = &q_u->name;
7473 UNISTR2 *uni_environment = &q_u->environment;
7474 uint32 level = q_u->level;
7475 NEW_BUFFER *buffer = NULL;
7476 uint32 offered = q_u->offered;
7477 uint32 *needed = &r_u->needed;
7479 /* that's an [in out] buffer */
7480 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7481 buffer = r_u->buffer;
7483 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7485 *needed=0;
7487 switch(level) {
7488 case 1:
7489 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7490 default:
7491 return WERR_UNKNOWN_LEVEL;
7495 /****************************************************************************
7496 ****************************************************************************/
7498 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7500 POLICY_HND *handle = &q_u->handle;
7501 uint32 idx = q_u->index;
7502 uint32 in_value_len = q_u->valuesize;
7503 uint32 in_data_len = q_u->datasize;
7504 uint32 *out_max_value_len = &r_u->valuesize;
7505 uint16 **out_value = &r_u->value;
7506 uint32 *out_value_len = &r_u->realvaluesize;
7507 uint32 *out_type = &r_u->type;
7508 uint32 *out_max_data_len = &r_u->datasize;
7509 uint8 **data_out = &r_u->data;
7510 uint32 *out_data_len = &r_u->realdatasize;
7512 NT_PRINTER_INFO_LEVEL *printer = NULL;
7514 uint32 param_index;
7515 uint32 biggest_valuesize;
7516 uint32 biggest_datasize;
7517 uint32 data_len;
7518 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7519 int snum;
7520 WERROR result;
7521 REGISTRY_VALUE *val;
7522 NT_PRINTER_DATA *p_data;
7523 int i, key_index, num_values;
7524 int name_length;
7526 ZERO_STRUCT( printer );
7528 *out_type = 0;
7530 *out_max_data_len = 0;
7531 *data_out = NULL;
7532 *out_data_len = 0;
7534 DEBUG(5,("spoolss_enumprinterdata\n"));
7536 if (!Printer) {
7537 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7538 return WERR_BADFID;
7541 if (!get_printer_snum(p,handle, &snum))
7542 return WERR_BADFID;
7544 result = get_a_printer(&printer, 2, lp_servicename(snum));
7545 if (!W_ERROR_IS_OK(result))
7546 return result;
7548 p_data = &printer->info_2->data;
7549 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7551 result = WERR_OK;
7554 * The NT machine wants to know the biggest size of value and data
7556 * cf: MSDN EnumPrinterData remark section
7559 if ( !in_value_len && !in_data_len )
7561 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7563 param_index = 0;
7564 biggest_valuesize = 0;
7565 biggest_datasize = 0;
7567 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7569 for ( i=0; i<num_values; i++ )
7571 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7573 name_length = strlen(val->valuename);
7574 if ( strlen(val->valuename) > biggest_valuesize )
7575 biggest_valuesize = name_length;
7577 if ( val->size > biggest_datasize )
7578 biggest_datasize = val->size;
7580 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7581 biggest_datasize));
7584 /* the value is an UNICODE string but real_value_size is the length
7585 in bytes including the trailing 0 */
7587 *out_value_len = 2 * (1+biggest_valuesize);
7588 *out_data_len = biggest_datasize;
7590 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7592 goto done;
7596 * the value len is wrong in NT sp3
7597 * that's the number of bytes not the number of unicode chars
7600 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7602 if ( !val )
7605 /* out_value should default to "" or else NT4 has
7606 problems unmarshalling the response */
7608 *out_max_value_len = (in_value_len/sizeof(uint16));
7610 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7612 result = WERR_NOMEM;
7613 goto done;
7616 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7618 /* the data is counted in bytes */
7620 *out_max_data_len = in_data_len;
7621 *out_data_len = in_data_len;
7623 /* only allocate when given a non-zero data_len */
7625 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7627 result = WERR_NOMEM;
7628 goto done;
7631 result = WERR_NO_MORE_ITEMS;
7633 else
7636 * the value is:
7637 * - counted in bytes in the request
7638 * - counted in UNICODE chars in the max reply
7639 * - counted in bytes in the real size
7641 * take a pause *before* coding not *during* coding
7644 /* name */
7645 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7646 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7648 result = WERR_NOMEM;
7649 goto done;
7652 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7654 /* type */
7656 *out_type = regval_type( val );
7658 /* data - counted in bytes */
7660 *out_max_data_len = in_data_len;
7661 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7663 result = WERR_NOMEM;
7664 goto done;
7666 data_len = (size_t)regval_size(val);
7667 memcpy( *data_out, regval_data_p(val), data_len );
7668 *out_data_len = data_len;
7671 done:
7672 free_a_printer(&printer, 2);
7673 return result;
7676 /****************************************************************************
7677 ****************************************************************************/
7679 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7681 POLICY_HND *handle = &q_u->handle;
7682 UNISTR2 *value = &q_u->value;
7683 uint32 type = q_u->type;
7684 uint8 *data = q_u->data;
7685 uint32 real_len = q_u->real_len;
7687 NT_PRINTER_INFO_LEVEL *printer = NULL;
7688 int snum=0;
7689 WERROR status = WERR_OK;
7690 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7691 fstring valuename;
7693 DEBUG(5,("spoolss_setprinterdata\n"));
7695 if (!Printer) {
7696 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7697 return WERR_BADFID;
7700 if (!get_printer_snum(p,handle, &snum))
7701 return WERR_BADFID;
7704 * Access check : NT returns "access denied" if you make a
7705 * SetPrinterData call without the necessary privildge.
7706 * we were originally returning OK if nothing changed
7707 * which made Win2k issue **a lot** of SetPrinterData
7708 * when connecting to a printer --jerry
7711 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7713 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7714 status = WERR_ACCESS_DENIED;
7715 goto done;
7718 status = get_a_printer(&printer, 2, lp_servicename(snum));
7719 if (!W_ERROR_IS_OK(status))
7720 return status;
7722 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7725 * When client side code sets a magic printer data key, detect it and save
7726 * the current printer data and the magic key's data (its the DEVMODE) for
7727 * future printer/driver initializations.
7729 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7731 /* Set devmode and printer initialization info */
7732 status = save_driver_init( printer, 2, data, real_len );
7734 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7736 else
7738 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7739 type, data, real_len );
7740 if ( W_ERROR_IS_OK(status) )
7741 status = mod_a_printer(*printer, 2);
7744 done:
7745 free_a_printer(&printer, 2);
7747 return status;
7750 /****************************************************************************
7751 ****************************************************************************/
7753 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7755 POLICY_HND *handle = &q_u->handle;
7756 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7757 int snum;
7759 DEBUG(5,("_spoolss_resetprinter\n"));
7762 * All we do is to check to see if the handle and queue is valid.
7763 * This call really doesn't mean anything to us because we only
7764 * support RAW printing. --jerry
7767 if (!Printer) {
7768 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7769 return WERR_BADFID;
7772 if (!get_printer_snum(p,handle, &snum))
7773 return WERR_BADFID;
7776 /* blindly return success */
7777 return WERR_OK;
7781 /****************************************************************************
7782 ****************************************************************************/
7784 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7786 POLICY_HND *handle = &q_u->handle;
7787 UNISTR2 *value = &q_u->valuename;
7789 NT_PRINTER_INFO_LEVEL *printer = NULL;
7790 int snum=0;
7791 WERROR status = WERR_OK;
7792 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7793 pstring valuename;
7795 DEBUG(5,("spoolss_deleteprinterdata\n"));
7797 if (!Printer) {
7798 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7799 return WERR_BADFID;
7802 if (!get_printer_snum(p, handle, &snum))
7803 return WERR_BADFID;
7805 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7806 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7807 return WERR_ACCESS_DENIED;
7810 status = get_a_printer(&printer, 2, lp_servicename(snum));
7811 if (!W_ERROR_IS_OK(status))
7812 return status;
7814 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7816 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7818 free_a_printer(&printer, 2);
7820 return status;
7823 /****************************************************************************
7824 ****************************************************************************/
7826 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7828 POLICY_HND *handle = &q_u->handle;
7829 FORM *form = &q_u->form;
7830 nt_forms_struct tmpForm;
7831 int snum;
7832 WERROR status = WERR_OK;
7833 NT_PRINTER_INFO_LEVEL *printer = NULL;
7835 int count=0;
7836 nt_forms_struct *list=NULL;
7837 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7839 DEBUG(5,("spoolss_addform\n"));
7841 if (!Printer) {
7842 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7843 return WERR_BADFID;
7847 /* forms can be added on printer of on the print server handle */
7849 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7851 if (!get_printer_snum(p,handle, &snum))
7852 return WERR_BADFID;
7854 status = get_a_printer(&printer, 2, lp_servicename(snum));
7855 if (!W_ERROR_IS_OK(status))
7856 goto done;
7859 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7860 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7861 status = WERR_ACCESS_DENIED;
7862 goto done;
7865 /* can't add if builtin */
7867 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7868 status = WERR_ALREADY_EXISTS;
7869 goto done;
7872 count = get_ntforms(&list);
7874 if(!add_a_form(&list, form, &count)) {
7875 status = WERR_NOMEM;
7876 goto done;
7879 write_ntforms(&list, count);
7882 * ChangeID must always be set if this is a printer
7885 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7886 status = mod_a_printer(*printer, 2);
7888 done:
7889 if ( printer )
7890 free_a_printer(&printer, 2);
7891 SAFE_FREE(list);
7893 return status;
7896 /****************************************************************************
7897 ****************************************************************************/
7899 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7901 POLICY_HND *handle = &q_u->handle;
7902 UNISTR2 *form_name = &q_u->name;
7903 nt_forms_struct tmpForm;
7904 int count=0;
7905 nt_forms_struct *list=NULL;
7906 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7907 int snum;
7908 WERROR status = WERR_OK;
7909 NT_PRINTER_INFO_LEVEL *printer = NULL;
7911 DEBUG(5,("spoolss_deleteform\n"));
7913 if (!Printer) {
7914 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7915 return WERR_BADFID;
7918 /* forms can be deleted on printer of on the print server handle */
7920 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7922 if (!get_printer_snum(p,handle, &snum))
7923 return WERR_BADFID;
7925 status = get_a_printer(&printer, 2, lp_servicename(snum));
7926 if (!W_ERROR_IS_OK(status))
7927 goto done;
7930 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7931 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7932 status = WERR_ACCESS_DENIED;
7933 goto done;
7936 /* can't delete if builtin */
7938 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7939 status = WERR_INVALID_PARAM;
7940 goto done;
7943 count = get_ntforms(&list);
7945 if ( !delete_a_form(&list, form_name, &count, &status ))
7946 goto done;
7949 * ChangeID must always be set if this is a printer
7952 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7953 status = mod_a_printer(*printer, 2);
7955 done:
7956 if ( printer )
7957 free_a_printer(&printer, 2);
7958 SAFE_FREE(list);
7960 return status;
7963 /****************************************************************************
7964 ****************************************************************************/
7966 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
7968 POLICY_HND *handle = &q_u->handle;
7969 FORM *form = &q_u->form;
7970 nt_forms_struct tmpForm;
7971 int snum;
7972 WERROR status = WERR_OK;
7973 NT_PRINTER_INFO_LEVEL *printer = NULL;
7975 int count=0;
7976 nt_forms_struct *list=NULL;
7977 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7979 DEBUG(5,("spoolss_setform\n"));
7981 if (!Printer) {
7982 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7983 return WERR_BADFID;
7986 /* forms can be modified on printer of on the print server handle */
7988 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7990 if (!get_printer_snum(p,handle, &snum))
7991 return WERR_BADFID;
7993 status = get_a_printer(&printer, 2, lp_servicename(snum));
7994 if (!W_ERROR_IS_OK(status))
7995 goto done;
7998 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7999 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8000 status = WERR_ACCESS_DENIED;
8001 goto done;
8004 /* can't set if builtin */
8005 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8006 status = WERR_INVALID_PARAM;
8007 goto done;
8010 count = get_ntforms(&list);
8011 update_a_form(&list, form, count);
8012 write_ntforms(&list, count);
8015 * ChangeID must always be set if this is a printer
8018 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8019 status = mod_a_printer(*printer, 2);
8022 done:
8023 if ( printer )
8024 free_a_printer(&printer, 2);
8025 SAFE_FREE(list);
8027 return status;
8030 /****************************************************************************
8031 enumprintprocessors level 1.
8032 ****************************************************************************/
8034 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8036 PRINTPROCESSOR_1 *info_1=NULL;
8038 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8039 return WERR_NOMEM;
8041 (*returned) = 0x1;
8043 init_unistr(&info_1->name, "winprint");
8045 *needed += spoolss_size_printprocessor_info_1(info_1);
8047 if (!alloc_buffer_size(buffer, *needed))
8048 return WERR_INSUFFICIENT_BUFFER;
8050 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8052 SAFE_FREE(info_1);
8054 if (*needed > offered) {
8055 *returned=0;
8056 return WERR_INSUFFICIENT_BUFFER;
8059 return WERR_OK;
8062 /****************************************************************************
8063 ****************************************************************************/
8065 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8067 uint32 level = q_u->level;
8068 NEW_BUFFER *buffer = NULL;
8069 uint32 offered = q_u->offered;
8070 uint32 *needed = &r_u->needed;
8071 uint32 *returned = &r_u->returned;
8073 /* that's an [in out] buffer */
8074 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8075 buffer = r_u->buffer;
8077 DEBUG(5,("spoolss_enumprintprocessors\n"));
8080 * Enumerate the print processors ...
8082 * Just reply with "winprint", to keep NT happy
8083 * and I can use my nice printer checker.
8086 *returned=0;
8087 *needed=0;
8089 switch (level) {
8090 case 1:
8091 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8092 default:
8093 return WERR_UNKNOWN_LEVEL;
8097 /****************************************************************************
8098 enumprintprocdatatypes level 1.
8099 ****************************************************************************/
8101 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8103 PRINTPROCDATATYPE_1 *info_1=NULL;
8105 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8106 return WERR_NOMEM;
8108 (*returned) = 0x1;
8110 init_unistr(&info_1->name, "RAW");
8112 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8114 if (!alloc_buffer_size(buffer, *needed))
8115 return WERR_INSUFFICIENT_BUFFER;
8117 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8119 SAFE_FREE(info_1);
8121 if (*needed > offered) {
8122 *returned=0;
8123 return WERR_INSUFFICIENT_BUFFER;
8126 return WERR_OK;
8129 /****************************************************************************
8130 ****************************************************************************/
8132 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8134 uint32 level = q_u->level;
8135 NEW_BUFFER *buffer = NULL;
8136 uint32 offered = q_u->offered;
8137 uint32 *needed = &r_u->needed;
8138 uint32 *returned = &r_u->returned;
8140 /* that's an [in out] buffer */
8141 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8142 buffer = r_u->buffer;
8144 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8146 *returned=0;
8147 *needed=0;
8149 switch (level) {
8150 case 1:
8151 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8152 default:
8153 return WERR_UNKNOWN_LEVEL;
8157 /****************************************************************************
8158 enumprintmonitors level 1.
8159 ****************************************************************************/
8161 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8163 PRINTMONITOR_1 *info_1=NULL;
8165 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8166 return WERR_NOMEM;
8168 (*returned) = 0x1;
8170 init_unistr(&info_1->name, "Local Port");
8172 *needed += spoolss_size_printmonitor_info_1(info_1);
8174 if (!alloc_buffer_size(buffer, *needed))
8175 return WERR_INSUFFICIENT_BUFFER;
8177 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8179 SAFE_FREE(info_1);
8181 if (*needed > offered) {
8182 *returned=0;
8183 return WERR_INSUFFICIENT_BUFFER;
8186 return WERR_OK;
8189 /****************************************************************************
8190 enumprintmonitors level 2.
8191 ****************************************************************************/
8193 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8195 PRINTMONITOR_2 *info_2=NULL;
8197 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8198 return WERR_NOMEM;
8200 (*returned) = 0x1;
8202 init_unistr(&info_2->name, "Local Port");
8203 init_unistr(&info_2->environment, "Windows NT X86");
8204 init_unistr(&info_2->dll_name, "localmon.dll");
8206 *needed += spoolss_size_printmonitor_info_2(info_2);
8208 if (!alloc_buffer_size(buffer, *needed))
8209 return WERR_INSUFFICIENT_BUFFER;
8211 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8213 SAFE_FREE(info_2);
8215 if (*needed > offered) {
8216 *returned=0;
8217 return WERR_INSUFFICIENT_BUFFER;
8220 return WERR_OK;
8223 /****************************************************************************
8224 ****************************************************************************/
8226 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8228 uint32 level = q_u->level;
8229 NEW_BUFFER *buffer = NULL;
8230 uint32 offered = q_u->offered;
8231 uint32 *needed = &r_u->needed;
8232 uint32 *returned = &r_u->returned;
8234 /* that's an [in out] buffer */
8235 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8236 buffer = r_u->buffer;
8238 DEBUG(5,("spoolss_enumprintmonitors\n"));
8241 * Enumerate the print monitors ...
8243 * Just reply with "Local Port", to keep NT happy
8244 * and I can use my nice printer checker.
8247 *returned=0;
8248 *needed=0;
8250 switch (level) {
8251 case 1:
8252 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8253 case 2:
8254 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8255 default:
8256 return WERR_UNKNOWN_LEVEL;
8260 /****************************************************************************
8261 ****************************************************************************/
8263 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8265 int i=0;
8266 BOOL found=False;
8267 JOB_INFO_1 *info_1=NULL;
8269 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8271 if (info_1 == NULL) {
8272 SAFE_FREE(queue);
8273 return WERR_NOMEM;
8276 for (i=0; i<count && found==False; i++) {
8277 if (queue[i].job==(int)jobid)
8278 found=True;
8281 if (found==False) {
8282 SAFE_FREE(queue);
8283 SAFE_FREE(info_1);
8284 /* NT treats not found as bad param... yet another bad choice */
8285 return WERR_INVALID_PARAM;
8288 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8290 *needed += spoolss_size_job_info_1(info_1);
8292 if (!alloc_buffer_size(buffer, *needed)) {
8293 SAFE_FREE(info_1);
8294 return WERR_INSUFFICIENT_BUFFER;
8297 smb_io_job_info_1("", buffer, info_1, 0);
8299 SAFE_FREE(info_1);
8301 if (*needed > offered)
8302 return WERR_INSUFFICIENT_BUFFER;
8304 return WERR_OK;
8307 /****************************************************************************
8308 ****************************************************************************/
8310 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8312 int i = 0;
8313 BOOL found = False;
8314 JOB_INFO_2 *info_2;
8315 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8316 WERROR ret;
8317 DEVICEMODE *devmode = NULL;
8318 NT_DEVICEMODE *nt_devmode = NULL;
8320 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8322 ZERO_STRUCTP(info_2);
8324 if (info_2 == NULL) {
8325 ret = WERR_NOMEM;
8326 goto done;
8329 for ( i=0; i<count && found==False; i++ )
8331 if (queue[i].job == (int)jobid)
8332 found = True;
8335 if ( !found )
8337 /* NT treats not found as bad param... yet another bad
8338 choice */
8339 ret = WERR_INVALID_PARAM;
8340 goto done;
8343 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
8344 if (!W_ERROR_IS_OK(ret))
8345 goto done;
8348 * if the print job does not have a DEVMODE associated with it,
8349 * just use the one for the printer. A NULL devicemode is not
8350 * a failure condition
8353 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8354 devmode = construct_dev_mode(snum);
8355 else {
8356 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8357 ZERO_STRUCTP( devmode );
8358 convert_nt_devicemode( devmode, nt_devmode );
8362 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8364 *needed += spoolss_size_job_info_2(info_2);
8366 if (!alloc_buffer_size(buffer, *needed)) {
8367 ret = WERR_INSUFFICIENT_BUFFER;
8368 goto done;
8371 smb_io_job_info_2("", buffer, info_2, 0);
8373 if (*needed > offered) {
8374 ret = WERR_INSUFFICIENT_BUFFER;
8375 goto done;
8378 ret = WERR_OK;
8380 done:
8381 /* Cleanup allocated memory */
8383 free_job_info_2(info_2); /* Also frees devmode */
8384 SAFE_FREE(info_2);
8385 free_a_printer(&ntprinter, 2);
8387 return ret;
8390 /****************************************************************************
8391 ****************************************************************************/
8393 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8395 POLICY_HND *handle = &q_u->handle;
8396 uint32 jobid = q_u->jobid;
8397 uint32 level = q_u->level;
8398 NEW_BUFFER *buffer = NULL;
8399 uint32 offered = q_u->offered;
8400 uint32 *needed = &r_u->needed;
8401 WERROR wstatus = WERR_OK;
8403 int snum;
8404 int count;
8405 print_queue_struct *queue = NULL;
8406 print_status_struct prt_status;
8408 /* that's an [in out] buffer */
8409 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8410 buffer = r_u->buffer;
8412 DEBUG(5,("spoolss_getjob\n"));
8414 *needed = 0;
8416 if (!get_printer_snum(p, handle, &snum))
8417 return WERR_BADFID;
8419 count = print_queue_status(snum, &queue, &prt_status);
8421 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8422 count, prt_status.status, prt_status.message));
8424 switch ( level ) {
8425 case 1:
8426 wstatus = getjob_level_1(queue, count, snum, jobid,
8427 buffer, offered, needed);
8428 break;
8429 case 2:
8430 wstatus = getjob_level_2(queue, count, snum, jobid,
8431 buffer, offered, needed);
8432 break;
8433 default:
8434 wstatus = WERR_UNKNOWN_LEVEL;
8435 break;
8438 SAFE_FREE(queue);
8439 return wstatus;
8442 /********************************************************************
8443 spoolss_getprinterdataex
8445 From MSDN documentation of GetPrinterDataEx: pass request
8446 to GetPrinterData if key is "PrinterDriverData".
8447 ********************************************************************/
8449 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8451 POLICY_HND *handle = &q_u->handle;
8452 uint32 in_size = q_u->size;
8453 uint32 *type = &r_u->type;
8454 uint32 *out_size = &r_u->size;
8455 uint8 **data = &r_u->data;
8456 uint32 *needed = &r_u->needed;
8457 fstring keyname, valuename;
8459 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8461 NT_PRINTER_INFO_LEVEL *printer = NULL;
8462 int snum = 0;
8463 WERROR status = WERR_OK;
8465 DEBUG(4,("_spoolss_getprinterdataex\n"));
8467 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8468 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8470 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8471 keyname, valuename));
8473 /* in case of problem, return some default values */
8475 *needed = 0;
8476 *type = 0;
8477 *out_size = in_size;
8479 if (!Printer) {
8480 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8481 status = WERR_BADFID;
8482 goto done;
8485 /* Is the handle to a printer or to the server? */
8487 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8488 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8489 status = WERR_INVALID_PARAM;
8490 goto done;
8493 if ( !get_printer_snum(p,handle, &snum) )
8494 return WERR_BADFID;
8496 status = get_a_printer(&printer, 2, lp_servicename(snum));
8497 if ( !W_ERROR_IS_OK(status) )
8498 goto done;
8500 /* check to see if the keyname is valid */
8501 if ( !strlen(keyname) ) {
8502 status = WERR_INVALID_PARAM;
8503 goto done;
8506 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8507 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8508 free_a_printer( &printer, 2 );
8509 status = WERR_BADFILE;
8510 goto done;
8513 /* When given a new keyname, we should just create it */
8515 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8517 if (*needed > *out_size)
8518 status = WERR_MORE_DATA;
8520 done:
8521 if ( !W_ERROR_IS_OK(status) )
8523 DEBUG(5, ("error: allocating %d\n", *out_size));
8525 /* reply this param doesn't exist */
8527 if ( *out_size )
8529 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8530 status = WERR_NOMEM;
8531 goto done;
8534 else {
8535 *data = NULL;
8539 if ( printer )
8540 free_a_printer( &printer, 2 );
8542 return status;
8545 /********************************************************************
8546 * spoolss_setprinterdataex
8547 ********************************************************************/
8549 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8551 POLICY_HND *handle = &q_u->handle;
8552 uint32 type = q_u->type;
8553 uint8 *data = q_u->data;
8554 uint32 real_len = q_u->real_len;
8556 NT_PRINTER_INFO_LEVEL *printer = NULL;
8557 int snum = 0;
8558 WERROR status = WERR_OK;
8559 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8560 fstring valuename;
8561 fstring keyname;
8562 char *oid_string;
8564 DEBUG(4,("_spoolss_setprinterdataex\n"));
8566 /* From MSDN documentation of SetPrinterDataEx: pass request to
8567 SetPrinterData if key is "PrinterDriverData" */
8569 if (!Printer) {
8570 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8571 return WERR_BADFID;
8574 if ( !get_printer_snum(p,handle, &snum) )
8575 return WERR_BADFID;
8578 * Access check : NT returns "access denied" if you make a
8579 * SetPrinterData call without the necessary privildge.
8580 * we were originally returning OK if nothing changed
8581 * which made Win2k issue **a lot** of SetPrinterData
8582 * when connecting to a printer --jerry
8585 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8587 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8588 return WERR_ACCESS_DENIED;
8591 status = get_a_printer(&printer, 2, lp_servicename(snum));
8592 if (!W_ERROR_IS_OK(status))
8593 return status;
8595 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8596 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8598 /* check for OID in valuename */
8600 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8602 *oid_string = '\0';
8603 oid_string++;
8606 /* save the registry data */
8608 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8610 /* save the OID if one was specified and the previous set call succeeded */
8612 if ( W_ERROR_IS_OK(status) && oid_string )
8615 fstrcat( keyname, "\\" );
8616 fstrcat( keyname, SPOOL_OID_KEY );
8619 * I'm not checking the status here on purpose. Don't know
8620 * if this is right, but I'm returning the status from the
8621 * previous set_printer_dataex() call. I have no idea if
8622 * this is right. --jerry
8625 set_printer_dataex( printer, keyname, valuename,
8626 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8629 free_a_printer(&printer, 2);
8631 return status;
8635 /********************************************************************
8636 * spoolss_deleteprinterdataex
8637 ********************************************************************/
8639 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8641 POLICY_HND *handle = &q_u->handle;
8642 UNISTR2 *value = &q_u->valuename;
8643 UNISTR2 *key = &q_u->keyname;
8645 NT_PRINTER_INFO_LEVEL *printer = NULL;
8646 int snum=0;
8647 WERROR status = WERR_OK;
8648 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8649 pstring valuename, keyname;
8651 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8653 if (!Printer) {
8654 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8655 return WERR_BADFID;
8658 if (!get_printer_snum(p, handle, &snum))
8659 return WERR_BADFID;
8661 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8662 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8663 return WERR_ACCESS_DENIED;
8666 status = get_a_printer(&printer, 2, lp_servicename(snum));
8667 if (!W_ERROR_IS_OK(status))
8668 return status;
8670 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8671 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8673 status = delete_printer_dataex( printer, keyname, valuename );
8675 free_a_printer(&printer, 2);
8677 return status;
8680 /********************************************************************
8681 * spoolss_enumprinterkey
8682 ********************************************************************/
8685 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8687 fstring key;
8688 fstring *keynames = NULL;
8689 uint16 *enumkeys = NULL;
8690 int num_keys;
8691 int printerkey_len;
8692 POLICY_HND *handle = &q_u->handle;
8693 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8694 NT_PRINTER_DATA *data;
8695 NT_PRINTER_INFO_LEVEL *printer = NULL;
8696 int snum = 0;
8697 WERROR status = WERR_BADFILE;
8700 DEBUG(4,("_spoolss_enumprinterkey\n"));
8702 if (!Printer) {
8703 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8704 return WERR_BADFID;
8707 if ( !get_printer_snum(p,handle, &snum) )
8708 return WERR_BADFID;
8710 status = get_a_printer(&printer, 2, lp_servicename(snum));
8711 if (!W_ERROR_IS_OK(status))
8712 return status;
8714 /* get the list of subkey names */
8716 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8717 data = &printer->info_2->data;
8719 num_keys = get_printer_subkeys( data, key, &keynames );
8721 if ( num_keys == -1 ) {
8722 status = WERR_BADFILE;
8723 goto done;
8726 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8728 r_u->needed = printerkey_len*2;
8730 if ( q_u->size < r_u->needed ) {
8731 status = WERR_MORE_DATA;
8732 goto done;
8735 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8736 status = WERR_NOMEM;
8737 goto done;
8740 status = WERR_OK;
8742 if ( q_u->size < r_u->needed )
8743 status = WERR_MORE_DATA;
8745 done:
8746 free_a_printer( &printer, 2 );
8747 SAFE_FREE( keynames );
8749 return status;
8752 /********************************************************************
8753 * spoolss_deleteprinterkey
8754 ********************************************************************/
8756 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8758 POLICY_HND *handle = &q_u->handle;
8759 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8760 fstring key;
8761 NT_PRINTER_INFO_LEVEL *printer = NULL;
8762 int snum=0;
8763 WERROR status;
8765 DEBUG(5,("spoolss_deleteprinterkey\n"));
8767 if (!Printer) {
8768 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8769 return WERR_BADFID;
8772 /* if keyname == NULL, return error */
8774 if ( !q_u->keyname.buffer )
8775 return WERR_INVALID_PARAM;
8777 if (!get_printer_snum(p, handle, &snum))
8778 return WERR_BADFID;
8780 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8781 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8782 return WERR_ACCESS_DENIED;
8785 status = get_a_printer(&printer, 2, lp_servicename(snum));
8786 if (!W_ERROR_IS_OK(status))
8787 return status;
8789 /* delete the key and all subneys */
8791 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8793 status = delete_all_printer_data( printer->info_2, key );
8795 if ( W_ERROR_IS_OK(status) )
8796 status = mod_a_printer(*printer, 2);
8798 free_a_printer( &printer, 2 );
8800 return status;
8804 /********************************************************************
8805 * spoolss_enumprinterdataex
8806 ********************************************************************/
8808 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8810 POLICY_HND *handle = &q_u->handle;
8811 uint32 in_size = q_u->size;
8812 uint32 num_entries,
8813 needed;
8814 NT_PRINTER_INFO_LEVEL *printer = NULL;
8815 PRINTER_ENUM_VALUES *enum_values = NULL;
8816 NT_PRINTER_DATA *p_data;
8817 fstring key;
8818 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8819 int snum;
8820 WERROR result;
8821 int key_index;
8822 int i;
8823 REGISTRY_VALUE *val;
8824 char *value_name;
8825 int data_len;
8828 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8830 if (!Printer) {
8831 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8832 return WERR_BADFID;
8835 /* first get the printer off of disk */
8837 if (!get_printer_snum(p,handle, &snum))
8838 return WERR_BADFID;
8840 ZERO_STRUCT(printer);
8841 result = get_a_printer(&printer, 2, lp_servicename(snum));
8842 if (!W_ERROR_IS_OK(result))
8843 return result;
8845 /* now look for a match on the key name */
8847 p_data = &printer->info_2->data;
8849 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8850 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8852 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8853 result = WERR_INVALID_PARAM;
8854 goto done;
8857 result = WERR_OK;
8858 needed = 0;
8860 /* allocate the memory for the array of pointers -- if necessary */
8862 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8863 if ( num_entries )
8865 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8867 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8868 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8869 result = WERR_NOMEM;
8870 goto done;
8873 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8877 * loop through all params and build the array to pass
8878 * back to the client
8881 for ( i=0; i<num_entries; i++ )
8883 /* lookup the registry value */
8885 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8886 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8888 /* copy the data */
8890 value_name = regval_name( val );
8891 init_unistr( &enum_values[i].valuename, value_name );
8892 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8893 enum_values[i].type = regval_type( val );
8895 data_len = regval_size( val );
8896 if ( data_len ) {
8897 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8899 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8900 data_len ));
8901 result = WERR_NOMEM;
8902 goto done;
8905 enum_values[i].data_len = data_len;
8907 /* keep track of the size of the array in bytes */
8909 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8912 /* housekeeping information in the reply */
8914 r_u->needed = needed;
8915 r_u->returned = num_entries;
8917 if (needed > in_size) {
8918 result = WERR_MORE_DATA;
8919 goto done;
8922 /* copy data into the reply */
8924 r_u->ctr.size = r_u->needed;
8925 r_u->ctr.size_of_array = r_u->returned;
8926 r_u->ctr.values = enum_values;
8930 done:
8931 free_a_printer(&printer, 2);
8933 return result;
8936 /****************************************************************************
8937 ****************************************************************************/
8939 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
8941 init_unistr(&info->name, name);
8944 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
8945 UNISTR2 *environment,
8946 NEW_BUFFER *buffer,
8947 uint32 offered,
8948 uint32 *needed)
8950 pstring path;
8951 pstring long_archi;
8952 pstring short_archi;
8953 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
8955 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
8957 if (get_short_archi(short_archi, long_archi)==False)
8958 return WERR_INVALID_ENVIRONMENT;
8960 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
8961 return WERR_NOMEM;
8963 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8965 fill_printprocessordirectory_1(info, path);
8967 *needed += spoolss_size_printprocessordirectory_info_1(info);
8969 if (!alloc_buffer_size(buffer, *needed)) {
8970 safe_free(info);
8971 return WERR_INSUFFICIENT_BUFFER;
8974 smb_io_printprocessordirectory_1("", buffer, info, 0);
8976 safe_free(info);
8978 if (*needed > offered)
8979 return WERR_INSUFFICIENT_BUFFER;
8980 else
8981 return WERR_OK;
8984 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
8986 uint32 level = q_u->level;
8987 NEW_BUFFER *buffer = NULL;
8988 uint32 offered = q_u->offered;
8989 uint32 *needed = &r_u->needed;
8990 WERROR result;
8992 /* that's an [in out] buffer */
8993 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8994 buffer = r_u->buffer;
8996 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8998 *needed=0;
9000 switch(level) {
9001 case 1:
9002 result = getprintprocessordirectory_level_1
9003 (&q_u->name, &q_u->environment, buffer, offered, needed);
9004 break;
9005 default:
9006 result = WERR_UNKNOWN_LEVEL;
9009 return result;
9012 #if 0
9014 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9015 SPOOL_R_REPLYOPENPRINTER *r_u)
9017 DEBUG(5,("_spoolss_replyopenprinter\n"));
9019 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9021 return WERR_OK;
9024 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9025 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9027 DEBUG(5,("_spoolss_replycloseprinter\n"));
9028 return WERR_OK;
9031 #endif