couple of merges from APP_HEAD
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob4c87d0f73d7f89933958ad9f23eb3cb79d8c0134
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 client'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 = talloc(mem_ctx, prs_offset(&ps));
711 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
713 prs_mem_free(&ps);
716 struct notify2_message_table {
717 const char *name;
718 void (*fn)(struct spoolss_notify_msg *msg,
719 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
722 static struct notify2_message_table printer_notify_table[] = {
723 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
724 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
725 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
726 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
727 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
728 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
729 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
730 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
731 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
732 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
733 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
734 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
735 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
736 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
737 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
738 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
739 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
740 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
741 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
744 static struct notify2_message_table job_notify_table[] = {
745 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
746 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
747 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
748 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
749 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
750 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
751 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
752 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
753 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
754 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
755 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
756 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
757 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
758 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
759 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
760 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
761 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
762 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
763 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
764 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
765 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
766 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
767 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
768 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
772 /***********************************************************************
773 Allocate talloc context for container object
774 **********************************************************************/
776 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
778 if ( !ctr )
779 return;
781 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
783 return;
786 /***********************************************************************
787 release all allocated memory and zero out structure
788 **********************************************************************/
790 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
792 if ( !ctr )
793 return;
795 if ( ctr->ctx )
796 talloc_destroy(ctr->ctx);
798 ZERO_STRUCTP(ctr);
800 return;
803 /***********************************************************************
804 **********************************************************************/
806 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
808 if ( !ctr )
809 return NULL;
811 return ctr->ctx;
814 /***********************************************************************
815 **********************************************************************/
817 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
819 if ( !ctr || !ctr->msg_groups )
820 return NULL;
822 if ( idx >= ctr->num_groups )
823 return NULL;
825 return &ctr->msg_groups[idx];
829 /***********************************************************************
830 How many groups of change messages do we have ?
831 **********************************************************************/
833 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
835 if ( !ctr )
836 return 0;
838 return ctr->num_groups;
841 /***********************************************************************
842 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
843 **********************************************************************/
845 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
847 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
848 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
849 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
850 int i, new_slot;
852 if ( !ctr || !msg )
853 return 0;
855 /* loop over all groups looking for a matching printer name */
857 for ( i=0; i<ctr->num_groups; i++ ) {
858 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
859 break;
862 /* add a new group? */
864 if ( i == ctr->num_groups )
866 ctr->num_groups++;
868 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
869 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
870 return 0;
872 ctr->msg_groups = groups;
874 /* clear the new entry and set the printer name */
876 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
877 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
880 /* add the change messages; 'i' is the correct index now regardless */
882 msg_grp = &ctr->msg_groups[i];
884 msg_grp->num_msgs++;
886 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
887 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
888 return 0;
890 msg_grp->msgs = msg_list;
892 new_slot = msg_grp->num_msgs-1;
893 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
895 /* need to allocate own copy of data */
897 if ( msg->len != 0 )
898 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
900 return ctr->num_groups;
903 /***********************************************************************
904 Send a change notication message on all handles which have a call
905 back registered
906 **********************************************************************/
908 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
910 Printer_entry *p;
911 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
912 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
913 SPOOLSS_NOTIFY_MSG *messages;
916 if ( !msg_group ) {
917 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
918 return;
921 messages = msg_group->msgs;
923 if ( !messages ) {
924 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
925 return;
928 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
930 /* loop over all printers */
932 for (p = printers_list; p; p = p->next)
934 SPOOL_NOTIFY_INFO_DATA *data;
935 uint32 data_len = 0;
936 uint32 id;
937 int i, event_index;
939 /* Is there notification on this handle? */
941 if ( !p->notify.client_connected )
942 continue;
944 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
946 /* For this printer? Print servers always receive
947 notifications. */
949 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
950 ( !strequal(msg_group->printername, p->dev.handlename) ) )
951 continue;
953 DEBUG(10,("Our printer\n"));
955 /* allocate the max entries possible */
957 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
958 ZERO_STRUCTP(data);
960 event_index = 0;
962 /* build the array of change notifications */
964 for ( i=0; i<msg_group->num_msgs; i++ )
966 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
968 /* Are we monitoring this event? */
970 if (!is_monitoring_event(p, msg->type, msg->field))
971 continue;
974 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
975 msg->type, msg->field, p->dev.handlename));
978 * if the is a printer notification handle and not a job notification
979 * type, then set the id to 0. Other wise just use what was specified
980 * in the message.
982 * When registering change notification on a print server handle
983 * we always need to send back the id (snum) matching the printer
984 * for which the change took place. For change notify registered
985 * on a printer handle, this does not matter and the id should be 0.
987 * --jerry
990 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
991 id = 0;
992 else
993 id = msg->id;
996 /* Convert unix jobid to smb jobid */
998 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID)
1000 id = sysjob_to_jobid(msg->id);
1002 if (id == -1) {
1003 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1004 goto done;
1008 construct_info_data( &data[data_len], msg->type, msg->field, id );
1010 switch(msg->type) {
1011 case PRINTER_NOTIFY_TYPE:
1012 if ( printer_notify_table[msg->field].fn )
1013 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1014 break;
1016 case JOB_NOTIFY_TYPE:
1017 if ( job_notify_table[msg->field].fn )
1018 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1019 break;
1021 default:
1022 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1023 goto done;
1026 data_len++;
1029 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1030 data_len, data, p->notify.change, 0 );
1033 done:
1034 DEBUG(8,("send_notify2_changes: Exit...\n"));
1035 return;
1038 /***********************************************************************
1039 **********************************************************************/
1041 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
1044 size_t offset = 0;
1046 /* Unpack message */
1048 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1049 msg->printer);
1051 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
1052 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1054 if (msg->len == 0)
1055 tdb_unpack((char *)buf + offset, len - offset, "dd",
1056 &msg->notify.value[0], &msg->notify.value[1]);
1057 else
1058 tdb_unpack((char *)buf + offset, len - offset, "B",
1059 &msg->len, &msg->notify.data);
1061 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
1062 msg->type, msg->field, msg->flags));
1064 if (msg->len == 0)
1065 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1066 msg->notify.value[1]));
1067 else
1068 dump_data(3, msg->notify.data, msg->len);
1070 return True;
1073 /********************************************************************
1074 Receive a notify2 message list
1075 ********************************************************************/
1077 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1079 size_t msg_count, i;
1080 char *buf = (char *)msg;
1081 char *msg_ptr;
1082 size_t msg_len;
1083 SPOOLSS_NOTIFY_MSG notify;
1084 SPOOLSS_NOTIFY_MSG_CTR messages;
1085 int num_groups;
1087 if (len < 4) {
1088 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1089 return;
1092 msg_count = IVAL(buf, 0);
1093 msg_ptr = buf + 4;
1095 DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
1097 if (msg_count == 0) {
1098 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1099 return;
1102 /* initialize the container */
1104 ZERO_STRUCT( messages );
1105 notify_msg_ctr_init( &messages );
1108 * build message groups for each printer identified
1109 * in a change_notify msg. Remember that a PCN message
1110 * includes the handle returned for the srv_spoolss_replyopenprinter()
1111 * call. Therefore messages are grouped according to printer handle.
1114 for ( i=0; i<msg_count; i++ )
1116 if (msg_ptr + 4 - buf > len) {
1117 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1118 return;
1121 msg_len = IVAL(msg_ptr,0);
1122 msg_ptr += 4;
1124 if (msg_ptr + msg_len - buf > len) {
1125 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1126 return;
1129 /* unpack messages */
1131 ZERO_STRUCT( notify );
1132 notify2_unpack_msg( &notify, msg_ptr, msg_len );
1133 msg_ptr += msg_len;
1135 /* add to correct list in container */
1137 notify_msg_ctr_addmsg( &messages, &notify );
1139 /* free memory that might have been allocated by notify2_unpack_msg() */
1141 if ( notify.len != 0 )
1142 SAFE_FREE( notify.notify.data );
1145 /* process each group of messages */
1147 num_groups = notify_msg_ctr_numgroups( &messages );
1148 for ( i=0; i<num_groups; i++ )
1149 send_notify2_changes( &messages, i );
1152 /* cleanup */
1154 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1156 notify_msg_ctr_destroy( &messages );
1158 return;
1161 /********************************************************************
1162 Send a message to ourself about new driver being installed
1163 so we can upgrade the information for each printer bound to this
1164 driver
1165 ********************************************************************/
1167 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1169 int len = strlen(drivername);
1171 if (!len)
1172 return False;
1174 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1175 drivername));
1177 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1179 return True;
1182 /**********************************************************************
1183 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1184 over all printers, upgrading ones as neessary
1185 **********************************************************************/
1187 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1189 fstring drivername;
1190 int snum;
1191 int n_services = lp_numservices();
1193 len = MIN(len,sizeof(drivername)-1);
1194 strncpy(drivername, buf, len);
1196 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1198 /* Iterate the printer list */
1200 for (snum=0; snum<n_services; snum++)
1202 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1204 WERROR result;
1205 NT_PRINTER_INFO_LEVEL *printer = NULL;
1207 result = get_a_printer(&printer, 2, lp_servicename(snum));
1208 if (!W_ERROR_IS_OK(result))
1209 continue;
1211 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1213 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1215 /* all we care about currently is the change_id */
1217 result = mod_a_printer(*printer, 2);
1218 if (!W_ERROR_IS_OK(result)) {
1219 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1220 dos_errstr(result)));
1224 free_a_printer(&printer, 2);
1228 /* all done */
1231 /********************************************************************
1232 Update the cahce for all printq's with a registered client
1233 connection
1234 ********************************************************************/
1236 void update_monitored_printq_cache( void )
1238 Printer_entry *printer = printers_list;
1239 int snum;
1241 /* loop through all printers and update the cache where
1242 client_connected == True */
1243 while ( printer )
1245 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1246 && printer->notify.client_connected )
1248 snum = print_queue_snum(printer->dev.handlename);
1249 print_queue_status( snum, NULL, NULL );
1252 printer = printer->next;
1255 return;
1257 /********************************************************************
1258 Send a message to ourself about new driver being installed
1259 so we can upgrade the information for each printer bound to this
1260 driver
1261 ********************************************************************/
1263 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1265 int len = strlen(drivername);
1267 if (!len)
1268 return False;
1270 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1271 drivername));
1273 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1275 return True;
1278 /**********************************************************************
1279 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1280 over all printers, resetting printer data as neessary
1281 **********************************************************************/
1283 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1285 fstring drivername;
1286 int snum;
1287 int n_services = lp_numservices();
1289 len = MIN( len, sizeof(drivername)-1 );
1290 strncpy( drivername, buf, len );
1292 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1294 /* Iterate the printer list */
1296 for ( snum=0; snum<n_services; snum++ )
1298 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1300 WERROR result;
1301 NT_PRINTER_INFO_LEVEL *printer = NULL;
1303 result = get_a_printer( &printer, 2, lp_servicename(snum) );
1304 if ( !W_ERROR_IS_OK(result) )
1305 continue;
1308 * if the printer is bound to the driver,
1309 * then reset to the new driver initdata
1312 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1314 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1316 if ( !set_driver_init(printer, 2) ) {
1317 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1318 printer->info_2->printername, printer->info_2->drivername));
1321 result = mod_a_printer( *printer, 2 );
1322 if ( !W_ERROR_IS_OK(result) ) {
1323 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1324 get_dos_error_msg(result)));
1328 free_a_printer( &printer, 2 );
1332 /* all done */
1334 return;
1337 /********************************************************************
1338 Copy routines used by convert_to_openprinterex()
1339 *******************************************************************/
1341 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1343 DEVICEMODE *d;
1344 int len;
1346 if (!devmode)
1347 return NULL;
1349 DEBUG (8,("dup_devmode\n"));
1351 /* bulk copy first */
1353 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1354 if (!d)
1355 return NULL;
1357 /* dup the pointer members separately */
1359 len = unistrlen(devmode->devicename.buffer);
1360 if (len != -1) {
1361 d->devicename.buffer = talloc(ctx, len*2);
1362 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1363 return NULL;
1367 len = unistrlen(devmode->formname.buffer);
1368 if (len != -1) {
1369 d->devicename.buffer = talloc(ctx, len*2);
1370 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1371 return NULL;
1374 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1376 return d;
1379 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1381 if (!new_ctr || !ctr)
1382 return;
1384 DEBUG(8,("copy_devmode_ctr\n"));
1386 new_ctr->size = ctr->size;
1387 new_ctr->devmode_ptr = ctr->devmode_ptr;
1389 if(ctr->devmode_ptr)
1390 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1393 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1395 if (!new_def || !def)
1396 return;
1398 DEBUG(8,("copy_printer_defaults\n"));
1400 new_def->datatype_ptr = def->datatype_ptr;
1402 if (def->datatype_ptr)
1403 copy_unistr2(&new_def->datatype, &def->datatype);
1405 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1407 new_def->access_required = def->access_required;
1410 /********************************************************************
1411 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1412 * SPOOL_Q_OPEN_PRINTER_EX structure
1413 ********************************************************************/
1415 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1417 if (!q_u_ex || !q_u)
1418 return;
1420 DEBUG(8,("convert_to_openprinterex\n"));
1422 q_u_ex->printername_ptr = q_u->printername_ptr;
1424 if (q_u->printername_ptr)
1425 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1427 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1430 /********************************************************************
1431 * spoolss_open_printer
1433 * called from the spoolss dispatcher
1434 ********************************************************************/
1436 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1438 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1439 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1441 if (!q_u || !r_u)
1442 return WERR_NOMEM;
1444 ZERO_STRUCT(q_u_ex);
1445 ZERO_STRUCT(r_u_ex);
1447 /* convert the OpenPrinter() call to OpenPrinterEx() */
1449 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1451 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1453 /* convert back to OpenPrinter() */
1455 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1457 return r_u->status;
1460 /********************************************************************
1461 * spoolss_open_printer
1463 * If the openprinterex rpc call contains a devmode,
1464 * it's a per-user one. This per-user devmode is derivated
1465 * from the global devmode. Openprinterex() contains a per-user
1466 * devmode for when you do EMF printing and spooling.
1467 * In the EMF case, the NT workstation is only doing half the job
1468 * of rendering the page. The other half is done by running the printer
1469 * driver on the server.
1470 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1471 * The EMF file only contains what is to be printed on the page.
1472 * So in order for the server to know how to print, the NT client sends
1473 * a devicemode attached to the openprinterex call.
1474 * But this devicemode is short lived, it's only valid for the current print job.
1476 * If Samba would have supported EMF spooling, this devicemode would
1477 * have been attached to the handle, to sent it to the driver to correctly
1478 * rasterize the EMF file.
1480 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1481 * we just act as a pass-thru between windows and the printer.
1483 * In order to know that Samba supports only RAW spooling, NT has to call
1484 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1485 * and until NT sends a RAW job, we refuse it.
1487 * But to call getprinter() or startdoc(), you first need a valid handle,
1488 * and to get an handle you have to call openprintex(). Hence why you have
1489 * a devicemode in the openprinterex() call.
1492 * Differences between NT4 and NT 2000.
1493 * NT4:
1494 * ---
1495 * On NT4, you only have a global devicemode. This global devicemode can be changed
1496 * by the administrator (or by a user with enough privs). Everytime a user
1497 * wants to print, the devicemode is resetted to the default. In Word, everytime
1498 * you print, the printer's characteristics are always reset to the global devicemode.
1500 * NT 2000:
1501 * -------
1502 * In W2K, there is the notion of per-user devicemode. The first time you use
1503 * a printer, a per-user devicemode is build from the global devicemode.
1504 * If you change your per-user devicemode, it is saved in the registry, under the
1505 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1506 * printer preferences available.
1508 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1509 * on the General Tab of the printer properties windows.
1511 * To change the global devicemode: it's the "Printing Defaults..." button
1512 * on the Advanced Tab of the printer properties window.
1514 * JFM.
1515 ********************************************************************/
1517 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1519 UNISTR2 *printername = NULL;
1520 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1521 POLICY_HND *handle = &r_u->handle;
1523 fstring name;
1524 int snum;
1525 struct current_user user;
1526 Printer_entry *Printer=NULL;
1528 if (q_u->printername_ptr != 0)
1529 printername = &q_u->printername;
1531 if (printername == NULL)
1532 return WERR_INVALID_PRINTER_NAME;
1534 /* some sanity check because you can open a printer or a print server */
1535 /* aka: \\server\printer or \\server */
1536 unistr2_to_ascii(name, printername, sizeof(name)-1);
1538 DEBUGADD(3,("checking name: %s\n",name));
1540 if (!open_printer_hnd(p, handle, name, 0))
1541 return WERR_INVALID_PRINTER_NAME;
1543 Printer=find_printer_index_by_hnd(p, handle);
1544 if (!Printer) {
1545 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1546 Can't find printer handle we created for printer %s\n", name ));
1547 close_printer_handle(p,handle);
1548 return WERR_INVALID_PRINTER_NAME;
1551 get_current_user(&user, p);
1554 * First case: the user is opening the print server:
1556 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1557 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1559 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1560 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1561 * or if the user is listed in the smb.conf printer admin parameter.
1563 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1564 * client view printer folder, but does not show the MSAPW.
1566 * Note: this test needs code to check access rights here too. Jeremy
1567 * could you look at this?
1569 * Second case: the user is opening a printer:
1570 * NT doesn't let us connect to a printer if the connecting user
1571 * doesn't have print permission.
1574 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1576 /* Printserver handles use global struct... */
1578 snum = -1;
1580 /* Map standard access rights to object specific access rights */
1582 se_map_standard(&printer_default->access_required,
1583 &printserver_std_mapping);
1585 /* Deny any object specific bits that don't apply to print
1586 servers (i.e printer and job specific bits) */
1588 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1590 if (printer_default->access_required &
1591 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1592 DEBUG(3, ("access DENIED for non-printserver bits"));
1593 close_printer_handle(p, handle);
1594 return WERR_ACCESS_DENIED;
1597 /* Allow admin access */
1599 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1601 if (!lp_ms_add_printer_wizard()) {
1602 close_printer_handle(p, handle);
1603 return WERR_ACCESS_DENIED;
1606 /* if the user is not root and not a printer admin, then fail */
1608 if ( user.uid != 0
1609 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1611 close_printer_handle(p, handle);
1612 return WERR_ACCESS_DENIED;
1615 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1617 else
1619 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1622 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1623 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1625 /* We fall through to return WERR_OK */
1628 else
1630 /* NT doesn't let us connect to a printer if the connecting user
1631 doesn't have print permission. */
1633 if (!get_printer_snum(p, handle, &snum))
1634 return WERR_BADFID;
1636 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1638 /* map an empty access mask to the minimum access mask */
1639 if (printer_default->access_required == 0x0)
1640 printer_default->access_required = PRINTER_ACCESS_USE;
1643 * If we are not serving the printer driver for this printer,
1644 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1645 * will keep NT clients happy --jerry
1648 if (lp_use_client_driver(snum)
1649 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1651 printer_default->access_required = PRINTER_ACCESS_USE;
1654 /* check smb.conf parameters and the the sec_desc */
1656 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1657 DEBUG(3, ("access DENIED for printer open\n"));
1658 close_printer_handle(p, handle);
1659 return WERR_ACCESS_DENIED;
1662 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1663 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1664 close_printer_handle(p, handle);
1665 return WERR_ACCESS_DENIED;
1668 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1669 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1670 else
1671 printer_default->access_required = PRINTER_ACCESS_USE;
1673 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1674 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1678 Printer->access_granted = printer_default->access_required;
1681 * If the client sent a devmode in the OpenPrinter() call, then
1682 * save it here in case we get a job submission on this handle
1685 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1686 && q_u->printer_default.devmode_cont.devmode_ptr )
1688 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1689 &Printer->nt_devmode );
1692 return WERR_OK;
1695 /****************************************************************************
1696 ****************************************************************************/
1698 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1699 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1701 BOOL ret = True;
1703 switch (level) {
1704 case 2:
1705 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1706 break;
1707 default:
1708 break;
1711 return ret;
1714 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1715 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1717 BOOL result = True;
1719 switch (level) {
1720 case 3:
1721 printer->info_3=NULL;
1722 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1723 result = False;
1724 break;
1725 case 6:
1726 printer->info_6=NULL;
1727 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1728 result = False;
1729 break;
1730 default:
1731 break;
1734 return result;
1737 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1738 NT_DEVICEMODE **pp_nt_devmode)
1740 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1743 * Ensure nt_devmode is a valid pointer
1744 * as we will be overwriting it.
1747 if (nt_devmode == NULL) {
1748 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1749 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1750 return False;
1753 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1754 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1756 nt_devmode->specversion=devmode->specversion;
1757 nt_devmode->driverversion=devmode->driverversion;
1758 nt_devmode->size=devmode->size;
1759 nt_devmode->fields=devmode->fields;
1760 nt_devmode->orientation=devmode->orientation;
1761 nt_devmode->papersize=devmode->papersize;
1762 nt_devmode->paperlength=devmode->paperlength;
1763 nt_devmode->paperwidth=devmode->paperwidth;
1764 nt_devmode->scale=devmode->scale;
1765 nt_devmode->copies=devmode->copies;
1766 nt_devmode->defaultsource=devmode->defaultsource;
1767 nt_devmode->printquality=devmode->printquality;
1768 nt_devmode->color=devmode->color;
1769 nt_devmode->duplex=devmode->duplex;
1770 nt_devmode->yresolution=devmode->yresolution;
1771 nt_devmode->ttoption=devmode->ttoption;
1772 nt_devmode->collate=devmode->collate;
1774 nt_devmode->logpixels=devmode->logpixels;
1775 nt_devmode->bitsperpel=devmode->bitsperpel;
1776 nt_devmode->pelswidth=devmode->pelswidth;
1777 nt_devmode->pelsheight=devmode->pelsheight;
1778 nt_devmode->displayflags=devmode->displayflags;
1779 nt_devmode->displayfrequency=devmode->displayfrequency;
1780 nt_devmode->icmmethod=devmode->icmmethod;
1781 nt_devmode->icmintent=devmode->icmintent;
1782 nt_devmode->mediatype=devmode->mediatype;
1783 nt_devmode->dithertype=devmode->dithertype;
1784 nt_devmode->reserved1=devmode->reserved1;
1785 nt_devmode->reserved2=devmode->reserved2;
1786 nt_devmode->panningwidth=devmode->panningwidth;
1787 nt_devmode->panningheight=devmode->panningheight;
1790 * Only change private and driverextra if the incoming devmode
1791 * has a new one. JRA.
1794 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1795 SAFE_FREE(nt_devmode->private);
1796 nt_devmode->driverextra=devmode->driverextra;
1797 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1798 return False;
1799 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1802 *pp_nt_devmode = nt_devmode;
1804 return True;
1807 /********************************************************************
1808 * _spoolss_enddocprinter_internal.
1809 ********************************************************************/
1811 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1813 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1814 int snum;
1816 if (!Printer) {
1817 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1818 return WERR_BADFID;
1821 if (!get_printer_snum(p, handle, &snum))
1822 return WERR_BADFID;
1824 Printer->document_started=False;
1825 print_job_end(snum, Printer->jobid,True);
1826 /* error codes unhandled so far ... */
1828 return WERR_OK;
1831 /********************************************************************
1832 * api_spoolss_closeprinter
1833 ********************************************************************/
1835 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1837 POLICY_HND *handle = &q_u->handle;
1839 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1841 if (Printer && Printer->document_started)
1842 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1844 if (!close_printer_handle(p, handle))
1845 return WERR_BADFID;
1847 /* clear the returned printer handle. Observed behavior
1848 from Win2k server. Don't think this really matters.
1849 Previous code just copied the value of the closed
1850 handle. --jerry */
1852 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1854 return WERR_OK;
1857 /********************************************************************
1858 * api_spoolss_deleteprinter
1860 ********************************************************************/
1862 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1864 POLICY_HND *handle = &q_u->handle;
1865 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1866 WERROR result;
1868 if (Printer && Printer->document_started)
1869 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1871 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1873 result = delete_printer_handle(p, handle);
1875 update_c_setprinter(False);
1877 return result;
1880 /*******************************************************************
1881 * static function to lookup the version id corresponding to an
1882 * long architecture string
1883 ******************************************************************/
1885 static int get_version_id (char * arch)
1887 int i;
1888 struct table_node archi_table[]= {
1890 {"Windows 4.0", "WIN40", 0 },
1891 {"Windows NT x86", "W32X86", 2 },
1892 {"Windows NT R4000", "W32MIPS", 2 },
1893 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1894 {"Windows NT PowerPC", "W32PPC", 2 },
1895 {NULL, "", -1 }
1898 for (i=0; archi_table[i].long_archi != NULL; i++)
1900 if (strcmp(arch, archi_table[i].long_archi) == 0)
1901 return (archi_table[i].version);
1904 return -1;
1907 /********************************************************************
1908 * _spoolss_deleteprinterdriver
1909 ********************************************************************/
1911 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1913 fstring driver;
1914 fstring arch;
1915 NT_PRINTER_DRIVER_INFO_LEVEL info;
1916 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1917 int version;
1918 struct current_user user;
1919 WERROR status;
1920 WERROR status_win2k = WERR_ACCESS_DENIED;
1922 get_current_user(&user, p);
1924 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1925 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1927 /* check that we have a valid driver name first */
1929 if ((version=get_version_id(arch)) == -1)
1930 return WERR_INVALID_ENVIRONMENT;
1932 ZERO_STRUCT(info);
1933 ZERO_STRUCT(info_win2k);
1935 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1937 /* try for Win2k driver if "Windows NT x86" */
1939 if ( version == 2 ) {
1940 version = 3;
1941 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1942 status = WERR_UNKNOWN_PRINTER_DRIVER;
1943 goto done;
1946 /* otherwise it was a failure */
1947 else {
1948 status = WERR_UNKNOWN_PRINTER_DRIVER;
1949 goto done;
1954 if (printer_driver_in_use(info.info_3)) {
1955 status = WERR_PRINTER_DRIVER_IN_USE;
1956 goto done;
1959 if ( version == 2 )
1961 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1963 /* if we get to here, we now have 2 driver info structures to remove */
1964 /* remove the Win2k driver first*/
1966 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
1967 free_a_printer_driver( info_win2k, 3 );
1969 /* this should not have failed---if it did, report to client */
1970 if ( !W_ERROR_IS_OK(status_win2k) )
1971 goto done;
1975 status = delete_printer_driver(info.info_3, &user, version, False);
1977 /* if at least one of the deletes succeeded return OK */
1979 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1980 status = WERR_OK;
1982 done:
1983 free_a_printer_driver( info, 3 );
1985 return status;
1988 /********************************************************************
1989 * spoolss_deleteprinterdriverex
1990 ********************************************************************/
1992 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
1994 fstring driver;
1995 fstring arch;
1996 NT_PRINTER_DRIVER_INFO_LEVEL info;
1997 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1998 int version;
1999 uint32 flags = q_u->delete_flags;
2000 BOOL delete_files;
2001 struct current_user user;
2002 WERROR status;
2003 WERROR status_win2k = WERR_ACCESS_DENIED;
2005 get_current_user(&user, p);
2007 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2008 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2010 /* check that we have a valid driver name first */
2011 if ((version=get_version_id(arch)) == -1) {
2012 /* this is what NT returns */
2013 return WERR_INVALID_ENVIRONMENT;
2016 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2017 version = q_u->version;
2019 ZERO_STRUCT(info);
2020 ZERO_STRUCT(info_win2k);
2022 status = get_a_printer_driver(&info, 3, driver, arch, version);
2024 if ( !W_ERROR_IS_OK(status) )
2027 * if the client asked for a specific version,
2028 * or this is something other than Windows NT x86,
2029 * then we've failed
2032 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2033 goto done;
2035 /* try for Win2k driver if "Windows NT x86" */
2037 version = 3;
2038 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2039 status = WERR_UNKNOWN_PRINTER_DRIVER;
2040 goto done;
2044 if ( printer_driver_in_use(info.info_3) ) {
2045 status = WERR_PRINTER_DRIVER_IN_USE;
2046 goto done;
2050 * we have a couple of cases to consider.
2051 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2052 * then the delete should fail if **any** files overlap with
2053 * other drivers
2054 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2055 * non-overlapping files
2056 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2057 * is set, the do not delete any files
2058 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2061 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2063 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2065 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2066 /* no idea of the correct error here */
2067 status = WERR_ACCESS_DENIED;
2068 goto done;
2072 /* also check for W32X86/3 if necessary; maybe we already have? */
2074 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2075 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2078 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2079 /* no idea of the correct error here */
2080 free_a_printer_driver( info_win2k, 3 );
2081 status = WERR_ACCESS_DENIED;
2082 goto done;
2085 /* if we get to here, we now have 2 driver info structures to remove */
2086 /* remove the Win2k driver first*/
2088 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2089 free_a_printer_driver( info_win2k, 3 );
2091 /* this should not have failed---if it did, report to client */
2093 if ( !W_ERROR_IS_OK(status_win2k) )
2094 goto done;
2098 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2100 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2101 status = WERR_OK;
2102 done:
2103 free_a_printer_driver( info, 3 );
2105 return status;
2109 /****************************************************************************
2110 Internal routine for retreiving printerdata
2111 ***************************************************************************/
2113 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2114 const char *key, const char *value, uint32 *type, uint8 **data,
2115 uint32 *needed, uint32 in_size )
2117 REGISTRY_VALUE *val;
2118 int size, data_len;
2120 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2121 return WERR_BADFILE;
2123 *type = regval_type( val );
2125 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2127 size = regval_size( val );
2129 /* copy the min(in_size, len) */
2131 if ( in_size ) {
2132 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2134 /* special case for 0 length values */
2135 if ( data_len ) {
2136 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2137 return WERR_NOMEM;
2139 else {
2140 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2141 return WERR_NOMEM;
2144 else
2145 *data = NULL;
2147 *needed = size;
2149 DEBUG(5,("get_printer_dataex: copy done\n"));
2151 return WERR_OK;
2154 /****************************************************************************
2155 Internal routine for removing printerdata
2156 ***************************************************************************/
2158 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2160 delete_printer_data( printer->info_2, key, value );
2162 return mod_a_printer(*printer, 2);
2165 /****************************************************************************
2166 Internal routine for storing printerdata
2167 ***************************************************************************/
2169 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2170 uint32 type, uint8 *data, int real_len )
2172 delete_printer_data( printer->info_2, key, value );
2174 add_printer_data( printer->info_2, key, value, type, data, real_len );
2176 return mod_a_printer(*printer, 2);
2179 /********************************************************************
2180 GetPrinterData on a printer server Handle.
2181 ********************************************************************/
2183 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2185 int i;
2187 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2189 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2190 *type = 0x4;
2191 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2192 return WERR_NOMEM;
2193 *needed = 0x4;
2194 return WERR_OK;
2197 if (!StrCaseCmp(value, "BeepEnabled")) {
2198 *type = 0x4;
2199 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2200 return WERR_NOMEM;
2201 SIVAL(*data, 0, 0x00);
2202 *needed = 0x4;
2203 return WERR_OK;
2206 if (!StrCaseCmp(value, "EventLog")) {
2207 *type = 0x4;
2208 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2209 return WERR_NOMEM;
2210 /* formally was 0x1b */
2211 SIVAL(*data, 0, 0x0);
2212 *needed = 0x4;
2213 return WERR_OK;
2216 if (!StrCaseCmp(value, "NetPopup")) {
2217 *type = 0x4;
2218 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2219 return WERR_NOMEM;
2220 SIVAL(*data, 0, 0x00);
2221 *needed = 0x4;
2222 return WERR_OK;
2225 if (!StrCaseCmp(value, "MajorVersion")) {
2226 *type = 0x4;
2227 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2228 return WERR_NOMEM;
2229 #ifdef HAVE_ADS
2230 SIVAL(*data, 0, 3);
2231 #else
2232 SIVAL(*data, 0, 2);
2233 #endif
2234 *needed = 0x4;
2235 return WERR_OK;
2238 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2239 fstring string;
2241 fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2242 *type = 0x1;
2243 *needed = 2*(strlen(string)+1);
2244 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2245 return WERR_NOMEM;
2246 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2248 /* it's done by hand ready to go on the wire */
2249 for (i=0; i<strlen(string); i++) {
2250 (*data)[2*i]=string[i];
2251 (*data)[2*i+1]='\0';
2253 return WERR_OK;
2256 if (!StrCaseCmp(value, "Architecture")) {
2257 pstring string="Windows NT x86";
2258 *type = 0x1;
2259 *needed = 2*(strlen(string)+1);
2260 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2261 return WERR_NOMEM;
2262 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2263 for (i=0; i<strlen(string); i++) {
2264 (*data)[2*i]=string[i];
2265 (*data)[2*i+1]='\0';
2267 return WERR_OK;
2270 if (!StrCaseCmp(value, "DsPresent")) {
2271 *type = 0x4;
2272 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2273 return WERR_NOMEM;
2274 SIVAL(*data, 0, 0x01);
2275 *needed = 0x4;
2276 return WERR_OK;
2279 if (!StrCaseCmp(value, "DNSMachineName")) {
2280 pstring hostname;
2282 if (!get_myfullname(hostname))
2283 return WERR_BADFILE;
2284 *type = 0x1;
2285 *needed = 2*(strlen(hostname)+1);
2286 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2287 return WERR_NOMEM;
2288 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2289 for (i=0; i<strlen(hostname); i++) {
2290 (*data)[2*i]=hostname[i];
2291 (*data)[2*i+1]='\0';
2293 return WERR_OK;
2297 return WERR_BADFILE;
2300 /********************************************************************
2301 * spoolss_getprinterdata
2302 ********************************************************************/
2304 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2306 POLICY_HND *handle = &q_u->handle;
2307 UNISTR2 *valuename = &q_u->valuename;
2308 uint32 in_size = q_u->size;
2309 uint32 *type = &r_u->type;
2310 uint32 *out_size = &r_u->size;
2311 uint8 **data = &r_u->data;
2312 uint32 *needed = &r_u->needed;
2313 WERROR status;
2314 fstring value;
2315 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2316 NT_PRINTER_INFO_LEVEL *printer = NULL;
2317 int snum = 0;
2320 * Reminder: when it's a string, the length is in BYTES
2321 * even if UNICODE is negociated.
2323 * JFM, 4/19/1999
2326 *out_size = in_size;
2328 /* in case of problem, return some default values */
2330 *needed = 0;
2331 *type = 0;
2333 DEBUG(4,("_spoolss_getprinterdata\n"));
2335 if ( !Printer ) {
2336 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2337 status = WERR_BADFID;
2338 goto done;
2341 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2343 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2344 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2345 else
2347 if ( !get_printer_snum(p,handle, &snum) ) {
2348 status = WERR_BADFID;
2349 goto done;
2352 status = get_a_printer(&printer, 2, lp_servicename(snum));
2353 if ( !W_ERROR_IS_OK(status) )
2354 goto done;
2356 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2358 if ( strequal(value, "ChangeId") ) {
2359 *type = REG_DWORD;
2360 *needed = sizeof(uint32);
2361 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2362 status = WERR_NOMEM;
2363 goto done;
2365 **data = printer->info_2->changeid;
2366 status = WERR_OK;
2368 else
2369 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2372 if (*needed > *out_size)
2373 status = WERR_MORE_DATA;
2375 done:
2376 if ( !W_ERROR_IS_OK(status) )
2378 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2380 /* reply this param doesn't exist */
2382 if ( *out_size ) {
2383 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2384 if ( printer )
2385 free_a_printer( &printer, 2 );
2386 return WERR_NOMEM;
2389 else {
2390 *data = NULL;
2394 /* cleanup & exit */
2396 if ( printer )
2397 free_a_printer( &printer, 2 );
2399 return status;
2402 /*********************************************************
2403 Connect to the client machine.
2404 **********************************************************/
2406 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, const char *remote_machine)
2408 ZERO_STRUCTP(the_cli);
2409 if(cli_initialise(the_cli) == NULL) {
2410 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
2411 return False;
2414 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2415 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
2416 cli_shutdown(the_cli);
2417 return False;
2420 if (ismyip(the_cli->dest_ip)) {
2421 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2422 cli_shutdown(the_cli);
2423 return False;
2426 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2427 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2428 cli_shutdown(the_cli);
2429 return False;
2432 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2433 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
2434 remote_machine));
2435 cli_shutdown(the_cli);
2436 return False;
2439 the_cli->protocol = PROTOCOL_NT1;
2441 if (!cli_negprot(the_cli)) {
2442 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2443 cli_shutdown(the_cli);
2444 return False;
2447 if (the_cli->protocol != PROTOCOL_NT1) {
2448 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2449 cli_shutdown(the_cli);
2450 return False;
2454 * Do an anonymous session setup.
2457 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2458 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2459 cli_shutdown(the_cli);
2460 return False;
2463 if (!(the_cli->sec_mode & 1)) {
2464 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2465 cli_shutdown(the_cli);
2466 return False;
2469 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2470 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2471 cli_shutdown(the_cli);
2472 return False;
2476 * Ok - we have an anonymous connection to the IPC$ share.
2477 * Now start the NT Domain stuff :-).
2480 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2481 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)));
2482 cli_nt_session_close(the_cli);
2483 cli_ulogoff(the_cli);
2484 cli_shutdown(the_cli);
2485 return False;
2488 return True;
2491 /***************************************************************************
2492 Connect to the client.
2493 ****************************************************************************/
2495 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
2497 WERROR result;
2500 * If it's the first connection, contact the client
2501 * and connect to the IPC$ share anonumously
2503 if (smb_connections==0) {
2504 fstring unix_printer;
2506 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2508 if(!spoolss_connect_to_client(&notify_cli, unix_printer))
2509 return False;
2511 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2512 /* Tell the connections db we're now interested in printer
2513 * notify messages. */
2514 register_message_flags( True, FLAG_MSG_PRINTING );
2518 * Tell the specific printing tdb we want messages for this printer
2519 * by registering our PID.
2522 if (!print_notify_register_pid(snum))
2523 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2525 smb_connections++;
2527 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2528 type, handle);
2530 if (!W_ERROR_IS_OK(result))
2531 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2532 dos_errstr(result)));
2534 return (W_ERROR_IS_OK(result));
2537 /********************************************************************
2538 * _spoolss_rffpcnex
2539 * ReplyFindFirstPrinterChangeNotifyEx
2541 * before replying OK: status=0 a rpc call is made to the workstation
2542 * asking ReplyOpenPrinter
2544 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2545 * called from api_spoolss_rffpcnex
2546 ********************************************************************/
2548 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2550 POLICY_HND *handle = &q_u->handle;
2551 uint32 flags = q_u->flags;
2552 uint32 options = q_u->options;
2553 UNISTR2 *localmachine = &q_u->localmachine;
2554 uint32 printerlocal = q_u->printerlocal;
2555 int snum = -1;
2556 SPOOL_NOTIFY_OPTION *option = q_u->option;
2558 /* store the notify value in the printer struct */
2560 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2562 if (!Printer) {
2563 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2564 return WERR_BADFID;
2567 Printer->notify.flags=flags;
2568 Printer->notify.options=options;
2569 Printer->notify.printerlocal=printerlocal;
2571 if (Printer->notify.option)
2572 free_spool_notify_option(&Printer->notify.option);
2574 Printer->notify.option=dup_spool_notify_option(option);
2576 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2577 sizeof(Printer->notify.localmachine)-1);
2579 /* Connect to the client machine and send a ReplyOpenPrinter */
2581 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2582 snum = -1;
2583 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2584 !get_printer_snum(p, handle, &snum) )
2585 return WERR_BADFID;
2587 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2588 Printer->notify.printerlocal, 1,
2589 &Printer->notify.client_hnd))
2590 return WERR_SERVER_UNAVAILABLE;
2592 Printer->notify.client_connected=True;
2594 return WERR_OK;
2597 /*******************************************************************
2598 * fill a notify_info_data with the servername
2599 ********************************************************************/
2601 void spoolss_notify_server_name(int snum,
2602 SPOOL_NOTIFY_INFO_DATA *data,
2603 print_queue_struct *queue,
2604 NT_PRINTER_INFO_LEVEL *printer,
2605 TALLOC_CTX *mem_ctx)
2607 pstring temp_name, temp;
2608 uint32 len;
2610 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2612 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2614 data->notify_data.data.length = len;
2615 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2617 if (!data->notify_data.data.string) {
2618 data->notify_data.data.length = 0;
2619 return;
2622 memcpy(data->notify_data.data.string, temp, len);
2625 /*******************************************************************
2626 * fill a notify_info_data with the printername (not including the servername).
2627 ********************************************************************/
2629 void spoolss_notify_printer_name(int snum,
2630 SPOOL_NOTIFY_INFO_DATA *data,
2631 print_queue_struct *queue,
2632 NT_PRINTER_INFO_LEVEL *printer,
2633 TALLOC_CTX *mem_ctx)
2635 pstring temp;
2636 uint32 len;
2638 /* the notify name should not contain the \\server\ part */
2639 char *p = strrchr(printer->info_2->printername, '\\');
2641 if (!p) {
2642 p = printer->info_2->printername;
2643 } else {
2644 p++;
2647 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2649 data->notify_data.data.length = len;
2650 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2652 if (!data->notify_data.data.string) {
2653 data->notify_data.data.length = 0;
2654 return;
2657 memcpy(data->notify_data.data.string, temp, len);
2660 /*******************************************************************
2661 * fill a notify_info_data with the servicename
2662 ********************************************************************/
2664 void spoolss_notify_share_name(int snum,
2665 SPOOL_NOTIFY_INFO_DATA *data,
2666 print_queue_struct *queue,
2667 NT_PRINTER_INFO_LEVEL *printer,
2668 TALLOC_CTX *mem_ctx)
2670 pstring temp;
2671 uint32 len;
2673 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2675 data->notify_data.data.length = len;
2676 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2678 if (!data->notify_data.data.string) {
2679 data->notify_data.data.length = 0;
2680 return;
2683 memcpy(data->notify_data.data.string, temp, len);
2686 /*******************************************************************
2687 * fill a notify_info_data with the port name
2688 ********************************************************************/
2690 void spoolss_notify_port_name(int snum,
2691 SPOOL_NOTIFY_INFO_DATA *data,
2692 print_queue_struct *queue,
2693 NT_PRINTER_INFO_LEVEL *printer,
2694 TALLOC_CTX *mem_ctx)
2696 pstring temp;
2697 uint32 len;
2699 /* even if it's strange, that's consistant in all the code */
2701 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2703 data->notify_data.data.length = len;
2704 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2706 if (!data->notify_data.data.string) {
2707 data->notify_data.data.length = 0;
2708 return;
2711 memcpy(data->notify_data.data.string, temp, len);
2714 /*******************************************************************
2715 * fill a notify_info_data with the printername
2716 * but it doesn't exist, have to see what to do
2717 ********************************************************************/
2719 void spoolss_notify_driver_name(int snum,
2720 SPOOL_NOTIFY_INFO_DATA *data,
2721 print_queue_struct *queue,
2722 NT_PRINTER_INFO_LEVEL *printer,
2723 TALLOC_CTX *mem_ctx)
2725 pstring temp;
2726 uint32 len;
2728 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2730 data->notify_data.data.length = len;
2731 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2733 if (!data->notify_data.data.string) {
2734 data->notify_data.data.length = 0;
2735 return;
2738 memcpy(data->notify_data.data.string, temp, len);
2741 /*******************************************************************
2742 * fill a notify_info_data with the comment
2743 ********************************************************************/
2745 void spoolss_notify_comment(int snum,
2746 SPOOL_NOTIFY_INFO_DATA *data,
2747 print_queue_struct *queue,
2748 NT_PRINTER_INFO_LEVEL *printer,
2749 TALLOC_CTX *mem_ctx)
2751 pstring temp;
2752 uint32 len;
2754 if (*printer->info_2->comment == '\0')
2755 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2756 else
2757 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2759 data->notify_data.data.length = len;
2760 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2762 if (!data->notify_data.data.string) {
2763 data->notify_data.data.length = 0;
2764 return;
2767 memcpy(data->notify_data.data.string, temp, len);
2770 /*******************************************************************
2771 * fill a notify_info_data with the comment
2772 * location = "Room 1, floor 2, building 3"
2773 ********************************************************************/
2775 void spoolss_notify_location(int snum,
2776 SPOOL_NOTIFY_INFO_DATA *data,
2777 print_queue_struct *queue,
2778 NT_PRINTER_INFO_LEVEL *printer,
2779 TALLOC_CTX *mem_ctx)
2781 pstring temp;
2782 uint32 len;
2784 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2786 data->notify_data.data.length = len;
2787 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2789 if (!data->notify_data.data.string) {
2790 data->notify_data.data.length = 0;
2791 return;
2794 memcpy(data->notify_data.data.string, temp, len);
2797 /*******************************************************************
2798 * fill a notify_info_data with the device mode
2799 * jfm:xxxx don't to it for know but that's a real problem !!!
2800 ********************************************************************/
2802 static void spoolss_notify_devmode(int snum,
2803 SPOOL_NOTIFY_INFO_DATA *data,
2804 print_queue_struct *queue,
2805 NT_PRINTER_INFO_LEVEL *printer,
2806 TALLOC_CTX *mem_ctx)
2810 /*******************************************************************
2811 * fill a notify_info_data with the separator file name
2812 ********************************************************************/
2814 void spoolss_notify_sepfile(int snum,
2815 SPOOL_NOTIFY_INFO_DATA *data,
2816 print_queue_struct *queue,
2817 NT_PRINTER_INFO_LEVEL *printer,
2818 TALLOC_CTX *mem_ctx)
2820 pstring temp;
2821 uint32 len;
2823 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2825 data->notify_data.data.length = len;
2826 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2828 if (!data->notify_data.data.string) {
2829 data->notify_data.data.length = 0;
2830 return;
2833 memcpy(data->notify_data.data.string, temp, len);
2836 /*******************************************************************
2837 * fill a notify_info_data with the print processor
2838 * jfm:xxxx return always winprint to indicate we don't do anything to it
2839 ********************************************************************/
2841 void spoolss_notify_print_processor(int snum,
2842 SPOOL_NOTIFY_INFO_DATA *data,
2843 print_queue_struct *queue,
2844 NT_PRINTER_INFO_LEVEL *printer,
2845 TALLOC_CTX *mem_ctx)
2847 pstring temp;
2848 uint32 len;
2850 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2852 data->notify_data.data.length = len;
2853 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2855 if (!data->notify_data.data.string) {
2856 data->notify_data.data.length = 0;
2857 return;
2860 memcpy(data->notify_data.data.string, temp, len);
2863 /*******************************************************************
2864 * fill a notify_info_data with the print processor options
2865 * jfm:xxxx send an empty string
2866 ********************************************************************/
2868 void spoolss_notify_parameters(int snum,
2869 SPOOL_NOTIFY_INFO_DATA *data,
2870 print_queue_struct *queue,
2871 NT_PRINTER_INFO_LEVEL *printer,
2872 TALLOC_CTX *mem_ctx)
2874 pstring temp;
2875 uint32 len;
2877 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2879 data->notify_data.data.length = len;
2880 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2882 if (!data->notify_data.data.string) {
2883 data->notify_data.data.length = 0;
2884 return;
2887 memcpy(data->notify_data.data.string, temp, len);
2890 /*******************************************************************
2891 * fill a notify_info_data with the data type
2892 * jfm:xxxx always send RAW as data type
2893 ********************************************************************/
2895 void spoolss_notify_datatype(int snum,
2896 SPOOL_NOTIFY_INFO_DATA *data,
2897 print_queue_struct *queue,
2898 NT_PRINTER_INFO_LEVEL *printer,
2899 TALLOC_CTX *mem_ctx)
2901 pstring temp;
2902 uint32 len;
2904 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2906 data->notify_data.data.length = len;
2907 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2909 if (!data->notify_data.data.string) {
2910 data->notify_data.data.length = 0;
2911 return;
2914 memcpy(data->notify_data.data.string, temp, len);
2917 /*******************************************************************
2918 * fill a notify_info_data with the security descriptor
2919 * jfm:xxxx send an null pointer to say no security desc
2920 * have to implement security before !
2921 ********************************************************************/
2923 static void spoolss_notify_security_desc(int snum,
2924 SPOOL_NOTIFY_INFO_DATA *data,
2925 print_queue_struct *queue,
2926 NT_PRINTER_INFO_LEVEL *printer,
2927 TALLOC_CTX *mem_ctx)
2929 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
2930 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
2933 /*******************************************************************
2934 * fill a notify_info_data with the attributes
2935 * jfm:xxxx a samba printer is always shared
2936 ********************************************************************/
2938 void spoolss_notify_attributes(int snum,
2939 SPOOL_NOTIFY_INFO_DATA *data,
2940 print_queue_struct *queue,
2941 NT_PRINTER_INFO_LEVEL *printer,
2942 TALLOC_CTX *mem_ctx)
2944 data->notify_data.value[0] = printer->info_2->attributes;
2945 data->notify_data.value[1] = 0;
2948 /*******************************************************************
2949 * fill a notify_info_data with the priority
2950 ********************************************************************/
2952 static void spoolss_notify_priority(int snum,
2953 SPOOL_NOTIFY_INFO_DATA *data,
2954 print_queue_struct *queue,
2955 NT_PRINTER_INFO_LEVEL *printer,
2956 TALLOC_CTX *mem_ctx)
2958 data->notify_data.value[0] = printer->info_2->priority;
2959 data->notify_data.value[1] = 0;
2962 /*******************************************************************
2963 * fill a notify_info_data with the default priority
2964 ********************************************************************/
2966 static void spoolss_notify_default_priority(int snum,
2967 SPOOL_NOTIFY_INFO_DATA *data,
2968 print_queue_struct *queue,
2969 NT_PRINTER_INFO_LEVEL *printer,
2970 TALLOC_CTX *mem_ctx)
2972 data->notify_data.value[0] = printer->info_2->default_priority;
2973 data->notify_data.value[1] = 0;
2976 /*******************************************************************
2977 * fill a notify_info_data with the start time
2978 ********************************************************************/
2980 static void spoolss_notify_start_time(int snum,
2981 SPOOL_NOTIFY_INFO_DATA *data,
2982 print_queue_struct *queue,
2983 NT_PRINTER_INFO_LEVEL *printer,
2984 TALLOC_CTX *mem_ctx)
2986 data->notify_data.value[0] = printer->info_2->starttime;
2987 data->notify_data.value[1] = 0;
2990 /*******************************************************************
2991 * fill a notify_info_data with the until time
2992 ********************************************************************/
2994 static void spoolss_notify_until_time(int snum,
2995 SPOOL_NOTIFY_INFO_DATA *data,
2996 print_queue_struct *queue,
2997 NT_PRINTER_INFO_LEVEL *printer,
2998 TALLOC_CTX *mem_ctx)
3000 data->notify_data.value[0] = printer->info_2->untiltime;
3001 data->notify_data.value[1] = 0;
3004 /*******************************************************************
3005 * fill a notify_info_data with the status
3006 ********************************************************************/
3008 static void spoolss_notify_status(int snum,
3009 SPOOL_NOTIFY_INFO_DATA *data,
3010 print_queue_struct *queue,
3011 NT_PRINTER_INFO_LEVEL *printer,
3012 TALLOC_CTX *mem_ctx)
3014 print_status_struct status;
3016 print_queue_length(snum, &status);
3017 data->notify_data.value[0]=(uint32) status.status;
3018 data->notify_data.value[1] = 0;
3021 /*******************************************************************
3022 * fill a notify_info_data with the number of jobs queued
3023 ********************************************************************/
3025 void spoolss_notify_cjobs(int snum,
3026 SPOOL_NOTIFY_INFO_DATA *data,
3027 print_queue_struct *queue,
3028 NT_PRINTER_INFO_LEVEL *printer,
3029 TALLOC_CTX *mem_ctx)
3031 data->notify_data.value[0] = print_queue_length(snum, NULL);
3032 data->notify_data.value[1] = 0;
3035 /*******************************************************************
3036 * fill a notify_info_data with the average ppm
3037 ********************************************************************/
3039 static void spoolss_notify_average_ppm(int snum,
3040 SPOOL_NOTIFY_INFO_DATA *data,
3041 print_queue_struct *queue,
3042 NT_PRINTER_INFO_LEVEL *printer,
3043 TALLOC_CTX *mem_ctx)
3045 /* always respond 8 pages per minutes */
3046 /* a little hard ! */
3047 data->notify_data.value[0] = printer->info_2->averageppm;
3048 data->notify_data.value[1] = 0;
3051 /*******************************************************************
3052 * fill a notify_info_data with username
3053 ********************************************************************/
3055 static void spoolss_notify_username(int snum,
3056 SPOOL_NOTIFY_INFO_DATA *data,
3057 print_queue_struct *queue,
3058 NT_PRINTER_INFO_LEVEL *printer,
3059 TALLOC_CTX *mem_ctx)
3061 pstring temp;
3062 uint32 len;
3064 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3066 data->notify_data.data.length = len;
3067 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3069 if (!data->notify_data.data.string) {
3070 data->notify_data.data.length = 0;
3071 return;
3074 memcpy(data->notify_data.data.string, temp, len);
3077 /*******************************************************************
3078 * fill a notify_info_data with job status
3079 ********************************************************************/
3081 static void spoolss_notify_job_status(int snum,
3082 SPOOL_NOTIFY_INFO_DATA *data,
3083 print_queue_struct *queue,
3084 NT_PRINTER_INFO_LEVEL *printer,
3085 TALLOC_CTX *mem_ctx)
3087 data->notify_data.value[0]=nt_printj_status(queue->status);
3088 data->notify_data.value[1] = 0;
3091 /*******************************************************************
3092 * fill a notify_info_data with job name
3093 ********************************************************************/
3095 static void spoolss_notify_job_name(int snum,
3096 SPOOL_NOTIFY_INFO_DATA *data,
3097 print_queue_struct *queue,
3098 NT_PRINTER_INFO_LEVEL *printer,
3099 TALLOC_CTX *mem_ctx)
3101 pstring temp;
3102 uint32 len;
3104 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3106 data->notify_data.data.length = len;
3107 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3109 if (!data->notify_data.data.string) {
3110 data->notify_data.data.length = 0;
3111 return;
3114 memcpy(data->notify_data.data.string, temp, len);
3117 /*******************************************************************
3118 * fill a notify_info_data with job status
3119 ********************************************************************/
3121 static void spoolss_notify_job_status_string(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3128 * Now we're returning job status codes we just return a "" here. JRA.
3131 const char *p = "";
3132 pstring temp;
3133 uint32 len;
3135 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3136 p = "unknown";
3138 switch (queue->status) {
3139 case LPQ_QUEUED:
3140 p = "Queued";
3141 break;
3142 case LPQ_PAUSED:
3143 p = ""; /* NT provides the paused string */
3144 break;
3145 case LPQ_SPOOLING:
3146 p = "Spooling";
3147 break;
3148 case LPQ_PRINTING:
3149 p = "Printing";
3150 break;
3152 #endif /* NO LONGER NEEDED. */
3154 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3156 data->notify_data.data.length = len;
3157 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3159 if (!data->notify_data.data.string) {
3160 data->notify_data.data.length = 0;
3161 return;
3164 memcpy(data->notify_data.data.string, temp, len);
3167 /*******************************************************************
3168 * fill a notify_info_data with job time
3169 ********************************************************************/
3171 static void spoolss_notify_job_time(int snum,
3172 SPOOL_NOTIFY_INFO_DATA *data,
3173 print_queue_struct *queue,
3174 NT_PRINTER_INFO_LEVEL *printer,
3175 TALLOC_CTX *mem_ctx)
3177 data->notify_data.value[0]=0x0;
3178 data->notify_data.value[1]=0;
3181 /*******************************************************************
3182 * fill a notify_info_data with job size
3183 ********************************************************************/
3185 static void spoolss_notify_job_size(int snum,
3186 SPOOL_NOTIFY_INFO_DATA *data,
3187 print_queue_struct *queue,
3188 NT_PRINTER_INFO_LEVEL *printer,
3189 TALLOC_CTX *mem_ctx)
3191 data->notify_data.value[0]=queue->size;
3192 data->notify_data.value[1]=0;
3195 /*******************************************************************
3196 * fill a notify_info_data with page info
3197 ********************************************************************/
3198 static void spoolss_notify_total_pages(int snum,
3199 SPOOL_NOTIFY_INFO_DATA *data,
3200 print_queue_struct *queue,
3201 NT_PRINTER_INFO_LEVEL *printer,
3202 TALLOC_CTX *mem_ctx)
3204 data->notify_data.value[0]=queue->page_count;
3205 data->notify_data.value[1]=0;
3208 /*******************************************************************
3209 * fill a notify_info_data with pages printed info.
3210 ********************************************************************/
3211 static void spoolss_notify_pages_printed(int snum,
3212 SPOOL_NOTIFY_INFO_DATA *data,
3213 print_queue_struct *queue,
3214 NT_PRINTER_INFO_LEVEL *printer,
3215 TALLOC_CTX *mem_ctx)
3217 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3218 data->notify_data.value[1]=0;
3221 /*******************************************************************
3222 Fill a notify_info_data with job position.
3223 ********************************************************************/
3225 static void spoolss_notify_job_position(int snum,
3226 SPOOL_NOTIFY_INFO_DATA *data,
3227 print_queue_struct *queue,
3228 NT_PRINTER_INFO_LEVEL *printer,
3229 TALLOC_CTX *mem_ctx)
3231 data->notify_data.value[0]=queue->job;
3232 data->notify_data.value[1]=0;
3235 /*******************************************************************
3236 Fill a notify_info_data with submitted time.
3237 ********************************************************************/
3239 static void spoolss_notify_submitted_time(int snum,
3240 SPOOL_NOTIFY_INFO_DATA *data,
3241 print_queue_struct *queue,
3242 NT_PRINTER_INFO_LEVEL *printer,
3243 TALLOC_CTX *mem_ctx)
3245 struct tm *t;
3246 uint32 len;
3247 SYSTEMTIME st;
3248 char *p;
3250 t=gmtime(&queue->time);
3252 len = sizeof(SYSTEMTIME);
3254 data->notify_data.data.length = len;
3255 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3257 if (!data->notify_data.data.string) {
3258 data->notify_data.data.length = 0;
3259 return;
3262 make_systemtime(&st, t);
3265 * Systemtime must be linearized as a set of UINT16's.
3266 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3269 p = (char *)data->notify_data.data.string;
3270 SSVAL(p, 0, st.year);
3271 SSVAL(p, 2, st.month);
3272 SSVAL(p, 4, st.dayofweek);
3273 SSVAL(p, 6, st.day);
3274 SSVAL(p, 8, st.hour);
3275 SSVAL(p, 10, st.minute);
3276 SSVAL(p, 12, st.second);
3277 SSVAL(p, 14, st.milliseconds);
3280 struct s_notify_info_data_table
3282 uint16 type;
3283 uint16 field;
3284 const char *name;
3285 uint32 size;
3286 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3287 print_queue_struct *queue,
3288 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3291 /* A table describing the various print notification constants and
3292 whether the notification data is a pointer to a variable sized
3293 buffer, a one value uint32 or a two value uint32. */
3295 static const struct s_notify_info_data_table notify_info_data_table[] =
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3337 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3338 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3339 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3340 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3341 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3342 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3343 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3344 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3345 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3348 /*******************************************************************
3349 Return the size of info_data structure.
3350 ********************************************************************/
3352 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3354 int i=0;
3356 for (i = 0; i < sizeof(notify_info_data_table); i++)
3358 if ( (notify_info_data_table[i].type == type)
3359 && (notify_info_data_table[i].field == field) )
3361 switch(notify_info_data_table[i].size)
3363 case NOTIFY_ONE_VALUE:
3364 case NOTIFY_TWO_VALUE:
3365 return 1;
3366 case NOTIFY_STRING:
3367 return 2;
3369 /* The only pointer notify data I have seen on
3370 the wire is the submitted time and this has
3371 the notify size set to 4. -tpot */
3373 case NOTIFY_POINTER:
3374 return 4;
3376 case NOTIFY_SECDESC:
3377 return 5;
3382 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3384 return 0;
3387 /*******************************************************************
3388 Return the type of notify_info_data.
3389 ********************************************************************/
3391 static int type_of_notify_info_data(uint16 type, uint16 field)
3393 int i=0;
3395 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3396 if (notify_info_data_table[i].type == type &&
3397 notify_info_data_table[i].field == field)
3398 return notify_info_data_table[i].size;
3401 return False;
3404 /****************************************************************************
3405 ****************************************************************************/
3407 static int search_notify(uint16 type, uint16 field, int *value)
3409 int i;
3411 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3412 if (notify_info_data_table[i].type == type &&
3413 notify_info_data_table[i].field == field &&
3414 notify_info_data_table[i].fn != NULL) {
3415 *value = i;
3416 return True;
3420 return False;
3423 /****************************************************************************
3424 ****************************************************************************/
3426 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3428 info_data->type = type;
3429 info_data->field = field;
3430 info_data->reserved = 0;
3432 info_data->size = size_of_notify_info_data(type, field);
3433 info_data->enc_type = type_of_notify_info_data(type, field);
3435 info_data->id = id;
3440 /*******************************************************************
3442 * fill a notify_info struct with info asked
3444 ********************************************************************/
3446 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
3447 snum, SPOOL_NOTIFY_OPTION_TYPE
3448 *option_type, uint32 id,
3449 TALLOC_CTX *mem_ctx)
3451 int field_num,j;
3452 uint16 type;
3453 uint16 field;
3455 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3456 NT_PRINTER_INFO_LEVEL *printer = NULL;
3457 print_queue_struct *queue=NULL;
3459 type=option_type->type;
3461 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3462 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3463 option_type->count, lp_servicename(snum)));
3465 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3466 return False;
3468 for(field_num=0; field_num<option_type->count; field_num++)
3470 field = option_type->fields[field_num];
3472 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3474 if (!search_notify(type, field, &j) )
3475 continue;
3477 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
3479 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3480 return False;
3482 else
3483 info->data = tid;
3485 current_data = &info->data[info->count];
3487 construct_info_data(current_data, type, field, id);
3489 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3490 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3492 notify_info_data_table[j].fn(snum, current_data, queue,
3493 printer, mem_ctx);
3495 info->count++;
3498 free_a_printer(&printer, 2);
3499 return True;
3502 /*******************************************************************
3504 * fill a notify_info struct with info asked
3506 ********************************************************************/
3508 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3509 SPOOL_NOTIFY_INFO *info,
3510 NT_PRINTER_INFO_LEVEL *printer,
3511 int snum, SPOOL_NOTIFY_OPTION_TYPE
3512 *option_type, uint32 id,
3513 TALLOC_CTX *mem_ctx)
3515 int field_num,j;
3516 uint16 type;
3517 uint16 field;
3519 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3521 DEBUG(4,("construct_notify_jobs_info\n"));
3523 type = option_type->type;
3525 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3526 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3527 option_type->count));
3529 for(field_num=0; field_num<option_type->count; field_num++) {
3530 field = option_type->fields[field_num];
3532 if (!search_notify(type, field, &j) )
3533 continue;
3535 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3536 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3537 return False;
3539 else info->data = tid;
3541 current_data=&(info->data[info->count]);
3543 construct_info_data(current_data, type, field, id);
3544 notify_info_data_table[j].fn(snum, current_data, queue,
3545 printer, mem_ctx);
3546 info->count++;
3549 return True;
3553 * JFM: The enumeration is not that simple, it's even non obvious.
3555 * let's take an example: I want to monitor the PRINTER SERVER for
3556 * the printer's name and the number of jobs currently queued.
3557 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3558 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3560 * I have 3 printers on the back of my server.
3562 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3563 * structures.
3564 * Number Data Id
3565 * 1 printer 1 name 1
3566 * 2 printer 1 cjob 1
3567 * 3 printer 2 name 2
3568 * 4 printer 2 cjob 2
3569 * 5 printer 3 name 3
3570 * 6 printer 3 name 3
3572 * that's the print server case, the printer case is even worse.
3575 /*******************************************************************
3577 * enumerate all printers on the printserver
3578 * fill a notify_info struct with info asked
3580 ********************************************************************/
3582 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3583 SPOOL_NOTIFY_INFO *info,
3584 TALLOC_CTX *mem_ctx)
3586 int snum;
3587 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3588 int n_services=lp_numservices();
3589 int i;
3590 uint32 id;
3591 SPOOL_NOTIFY_OPTION *option;
3592 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3594 DEBUG(4,("printserver_notify_info\n"));
3596 if (!Printer)
3597 return WERR_BADFID;
3599 option=Printer->notify.option;
3600 id=1;
3601 info->version=2;
3602 info->data=NULL;
3603 info->count=0;
3605 for (i=0; i<option->count; i++) {
3606 option_type=&(option->ctr.type[i]);
3608 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3609 continue;
3611 for (snum=0; snum<n_services; snum++)
3613 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3614 construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
3618 #if 0
3620 * Debugging information, don't delete.
3623 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3624 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3625 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3627 for (i=0; i<info->count; i++) {
3628 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3629 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3630 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3632 #endif
3634 return WERR_OK;
3637 /*******************************************************************
3639 * fill a notify_info struct with info asked
3641 ********************************************************************/
3643 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3644 TALLOC_CTX *mem_ctx)
3646 int snum;
3647 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3648 int i;
3649 uint32 id;
3650 SPOOL_NOTIFY_OPTION *option;
3651 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3652 int count,j;
3653 print_queue_struct *queue=NULL;
3654 print_status_struct status;
3656 DEBUG(4,("printer_notify_info\n"));
3658 if (!Printer)
3659 return WERR_BADFID;
3661 option=Printer->notify.option;
3662 id = 0x0;
3663 info->version=2;
3664 info->data=NULL;
3665 info->count=0;
3667 get_printer_snum(p, hnd, &snum);
3669 for (i=0; i<option->count; i++) {
3670 option_type=&option->ctr.type[i];
3672 switch ( option_type->type ) {
3673 case PRINTER_NOTIFY_TYPE:
3674 if(construct_notify_printer_info(info, snum,
3675 option_type, id,
3676 mem_ctx))
3677 id--;
3678 break;
3680 case JOB_NOTIFY_TYPE: {
3681 NT_PRINTER_INFO_LEVEL *printer = NULL;
3683 count = print_queue_status(snum, &queue, &status);
3685 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2,
3686 lp_servicename(snum))))
3687 goto done;
3689 for (j=0; j<count; j++) {
3690 construct_notify_jobs_info(&queue[j], info,
3691 printer, snum,
3692 option_type,
3693 queue[j].job,
3694 mem_ctx);
3697 free_a_printer(&printer, 2);
3699 done:
3700 SAFE_FREE(queue);
3701 break;
3707 * Debugging information, don't delete.
3710 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3711 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3712 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3714 for (i=0; i<info->count; i++) {
3715 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3716 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3717 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3720 return WERR_OK;
3723 /********************************************************************
3724 * spoolss_rfnpcnex
3725 ********************************************************************/
3727 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3729 POLICY_HND *handle = &q_u->handle;
3730 SPOOL_NOTIFY_INFO *info = &r_u->info;
3732 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3733 WERROR result = WERR_BADFID;
3735 /* we always have a NOTIFY_INFO struct */
3736 r_u->info_ptr=0x1;
3738 if (!Printer) {
3739 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3740 OUR_HANDLE(handle)));
3741 goto done;
3744 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3747 * We are now using the change value, and
3748 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3749 * I don't have a global notification system, I'm sending back all the
3750 * informations even when _NOTHING_ has changed.
3753 /* We need to keep track of the change value to send back in
3754 RRPCN replies otherwise our updates are ignored. */
3756 Printer->notify.fnpcn = True;
3758 if (Printer->notify.client_connected) {
3759 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3760 Printer->notify.change = q_u->change;
3763 /* just ignore the SPOOL_NOTIFY_OPTION */
3765 switch (Printer->printer_type) {
3766 case PRINTER_HANDLE_IS_PRINTSERVER:
3767 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3768 break;
3770 case PRINTER_HANDLE_IS_PRINTER:
3771 result = printer_notify_info(p, handle, info, p->mem_ctx);
3772 break;
3775 Printer->notify.fnpcn = False;
3777 done:
3778 return result;
3781 /********************************************************************
3782 * construct_printer_info_0
3783 * fill a printer_info_0 struct
3784 ********************************************************************/
3786 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
3788 pstring chaine;
3789 int count;
3790 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3791 counter_printer_0 *session_counter;
3792 uint32 global_counter;
3793 struct tm *t;
3794 time_t setuptime;
3795 print_status_struct status;
3797 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3798 return False;
3800 count = print_queue_length(snum, &status);
3802 /* check if we already have a counter for this printer */
3803 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3805 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3806 if (session_counter->snum == snum)
3807 break;
3810 /* it's the first time, add it to the list */
3811 if (session_counter==NULL) {
3812 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3813 free_a_printer(&ntprinter, 2);
3814 return False;
3816 ZERO_STRUCTP(session_counter);
3817 session_counter->snum=snum;
3818 session_counter->counter=0;
3819 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3822 /* increment it */
3823 session_counter->counter++;
3825 /* JFM:
3826 * the global_counter should be stored in a TDB as it's common to all the clients
3827 * and should be zeroed on samba startup
3829 global_counter=session_counter->counter;
3831 pstrcpy(chaine,ntprinter->info_2->printername);
3833 init_unistr(&printer->printername, chaine);
3835 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3836 init_unistr(&printer->servername, chaine);
3838 printer->cjobs = count;
3839 printer->total_jobs = 0;
3840 printer->total_bytes = 0;
3842 setuptime = (time_t)ntprinter->info_2->setuptime;
3843 t=gmtime(&setuptime);
3845 printer->year = t->tm_year+1900;
3846 printer->month = t->tm_mon+1;
3847 printer->dayofweek = t->tm_wday;
3848 printer->day = t->tm_mday;
3849 printer->hour = t->tm_hour;
3850 printer->minute = t->tm_min;
3851 printer->second = t->tm_sec;
3852 printer->milliseconds = 0;
3854 printer->global_counter = global_counter;
3855 printer->total_pages = 0;
3856 #ifdef HAVE_ADS
3857 printer->major_version = 0x0005; /* NT 5 */
3858 printer->build_version = 0x0893; /* build 2195 */
3859 #else
3860 printer->major_version = 0x0004; /* NT 4 */
3861 printer->build_version = 0x0565; /* build 1381 */
3862 #endif
3863 printer->unknown7 = 0x1;
3864 printer->unknown8 = 0x0;
3865 printer->unknown9 = 0x0;
3866 printer->session_counter = session_counter->counter;
3867 printer->unknown11 = 0x0;
3868 printer->printer_errors = 0x0; /* number of print failure */
3869 printer->unknown13 = 0x0;
3870 printer->unknown14 = 0x1;
3871 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3872 printer->unknown16 = 0x0;
3873 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3874 printer->unknown18 = 0x0;
3875 printer->status = nt_printq_status(status.status);
3876 printer->unknown20 = 0x0;
3877 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3878 printer->unknown22 = 0x0;
3879 printer->unknown23 = 0x6; /* 6 ???*/
3880 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3881 printer->unknown25 = 0;
3882 printer->unknown26 = 0;
3883 printer->unknown27 = 0;
3884 printer->unknown28 = 0;
3885 printer->unknown29 = 0;
3887 free_a_printer(&ntprinter,2);
3888 return (True);
3891 /********************************************************************
3892 * construct_printer_info_1
3893 * fill a printer_info_1 struct
3894 ********************************************************************/
3895 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
3897 pstring chaine;
3898 pstring chaine2;
3899 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3901 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
3902 return False;
3904 printer->flags=flags;
3906 if (*ntprinter->info_2->comment == '\0') {
3907 init_unistr(&printer->comment, lp_comment(snum));
3908 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3909 ntprinter->info_2->drivername, lp_comment(snum));
3911 else {
3912 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3913 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3914 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3917 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3919 init_unistr(&printer->description, chaine);
3920 init_unistr(&printer->name, chaine2);
3922 free_a_printer(&ntprinter,2);
3924 return True;
3927 /****************************************************************************
3928 Free a DEVMODE struct.
3929 ****************************************************************************/
3931 static void free_dev_mode(DEVICEMODE *dev)
3933 if (dev == NULL)
3934 return;
3936 SAFE_FREE(dev->private);
3937 SAFE_FREE(dev);
3941 /****************************************************************************
3942 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
3943 should be valid upon entry
3944 ****************************************************************************/
3946 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
3948 if ( !devmode || !ntdevmode )
3949 return False;
3951 init_unistr(&devmode->devicename, ntdevmode->devicename);
3953 init_unistr(&devmode->formname, ntdevmode->formname);
3955 devmode->specversion = ntdevmode->specversion;
3956 devmode->driverversion = ntdevmode->driverversion;
3957 devmode->size = ntdevmode->size;
3958 devmode->driverextra = ntdevmode->driverextra;
3959 devmode->fields = ntdevmode->fields;
3961 devmode->orientation = ntdevmode->orientation;
3962 devmode->papersize = ntdevmode->papersize;
3963 devmode->paperlength = ntdevmode->paperlength;
3964 devmode->paperwidth = ntdevmode->paperwidth;
3965 devmode->scale = ntdevmode->scale;
3966 devmode->copies = ntdevmode->copies;
3967 devmode->defaultsource = ntdevmode->defaultsource;
3968 devmode->printquality = ntdevmode->printquality;
3969 devmode->color = ntdevmode->color;
3970 devmode->duplex = ntdevmode->duplex;
3971 devmode->yresolution = ntdevmode->yresolution;
3972 devmode->ttoption = ntdevmode->ttoption;
3973 devmode->collate = ntdevmode->collate;
3974 devmode->icmmethod = ntdevmode->icmmethod;
3975 devmode->icmintent = ntdevmode->icmintent;
3976 devmode->mediatype = ntdevmode->mediatype;
3977 devmode->dithertype = ntdevmode->dithertype;
3979 if (ntdevmode->private != NULL) {
3980 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
3981 return False;
3984 return True;
3987 /****************************************************************************
3988 Create a DEVMODE struct. Returns malloced memory.
3989 ****************************************************************************/
3991 DEVICEMODE *construct_dev_mode(int snum)
3993 NT_PRINTER_INFO_LEVEL *printer = NULL;
3994 DEVICEMODE *devmode = NULL;
3996 DEBUG(7,("construct_dev_mode\n"));
3998 DEBUGADD(8,("getting printer characteristics\n"));
4000 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4001 return NULL;
4003 if ( !printer->info_2->devmode ) {
4004 DEBUG(5, ("BONG! There was no device mode!\n"));
4005 goto done;
4008 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4009 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4010 goto done;
4013 ZERO_STRUCTP(devmode);
4015 DEBUGADD(8,("loading DEVICEMODE\n"));
4017 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4018 free_dev_mode( devmode );
4019 devmode = NULL;
4022 done:
4023 free_a_printer(&printer,2);
4025 return devmode;
4028 /********************************************************************
4029 * construct_printer_info_2
4030 * fill a printer_info_2 struct
4031 ********************************************************************/
4033 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
4035 int count;
4036 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4038 print_status_struct status;
4040 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4041 return False;
4043 count = print_queue_length(snum, &status);
4045 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4046 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4047 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4048 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4049 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4051 if (*ntprinter->info_2->comment == '\0')
4052 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4053 else
4054 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4056 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4057 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4058 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4059 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4060 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4062 printer->attributes = ntprinter->info_2->attributes;
4064 printer->priority = ntprinter->info_2->priority; /* priority */
4065 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4066 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4067 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4068 printer->status = nt_printq_status(status.status); /* status */
4069 printer->cjobs = count; /* jobs */
4070 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4072 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4073 DEBUG(8, ("Returning NULL Devicemode!\n"));
4076 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4077 /* steal the printer info sec_desc structure. [badly done]. */
4078 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4079 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4080 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4081 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4083 else {
4084 printer->secdesc = NULL;
4087 free_a_printer(&ntprinter, 2);
4088 return True;
4091 /********************************************************************
4092 * construct_printer_info_3
4093 * fill a printer_info_3 struct
4094 ********************************************************************/
4096 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
4098 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4099 PRINTER_INFO_3 *printer = NULL;
4101 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4102 return False;
4104 *pp_printer = NULL;
4105 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4106 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4107 return False;
4110 ZERO_STRUCTP(printer);
4112 printer->flags = 4; /* These are the components of the SD we are returning. */
4113 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4114 /* steal the printer info sec_desc structure. [badly done]. */
4115 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4117 #if 0
4119 * Set the flags for the components we are returning.
4122 if (printer->secdesc->owner_sid)
4123 printer->flags |= OWNER_SECURITY_INFORMATION;
4125 if (printer->secdesc->grp_sid)
4126 printer->flags |= GROUP_SECURITY_INFORMATION;
4128 if (printer->secdesc->dacl)
4129 printer->flags |= DACL_SECURITY_INFORMATION;
4131 if (printer->secdesc->sacl)
4132 printer->flags |= SACL_SECURITY_INFORMATION;
4133 #endif
4135 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4136 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4137 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4140 free_a_printer(&ntprinter, 2);
4142 *pp_printer = printer;
4143 return True;
4146 /********************************************************************
4147 * construct_printer_info_4
4148 * fill a printer_info_4 struct
4149 ********************************************************************/
4151 static BOOL construct_printer_info_4(PRINTER_INFO_4 *printer, int snum)
4153 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4155 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4156 return False;
4158 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4159 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4160 printer->attributes = ntprinter->info_2->attributes;
4162 free_a_printer(&ntprinter, 2);
4163 return True;
4166 /********************************************************************
4167 * construct_printer_info_5
4168 * fill a printer_info_5 struct
4169 ********************************************************************/
4171 static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
4173 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4175 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
4176 return False;
4178 init_unistr(&printer->printername, ntprinter->info_2->printername);
4179 init_unistr(&printer->portname, ntprinter->info_2->portname);
4180 printer->attributes = ntprinter->info_2->attributes;
4182 /* these two are not used by NT+ according to MSDN */
4184 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4185 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4187 free_a_printer(&ntprinter, 2);
4189 return True;
4192 /********************************************************************
4193 * construct_printer_info_7
4194 * fill a printer_info_7 struct
4195 ********************************************************************/
4197 static BOOL construct_printer_info_7(PRINTER_INFO_7 *printer, int snum)
4199 char *guid_str = NULL;
4200 GUID guid;
4202 if (is_printer_published(snum, &guid)) {
4203 asprintf(&guid_str, "{%s}", uuid_string_static(guid));
4204 strupper(guid_str);
4205 init_unistr(&printer->guid, guid_str);
4206 printer->action = SPOOL_DS_PUBLISH;
4207 } else {
4208 init_unistr(&printer->guid, "");
4209 printer->action = SPOOL_DS_UNPUBLISH;
4212 return True;
4215 /********************************************************************
4216 Spoolss_enumprinters.
4217 ********************************************************************/
4219 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4221 int snum;
4222 int i;
4223 int n_services=lp_numservices();
4224 PRINTER_INFO_1 *tp, *printers=NULL;
4225 PRINTER_INFO_1 current_prt;
4227 DEBUG(4,("enum_all_printers_info_1\n"));
4229 for (snum=0; snum<n_services; snum++) {
4230 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4231 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4233 if (construct_printer_info_1(flags, &current_prt, snum)) {
4234 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4235 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4236 SAFE_FREE(printers);
4237 *returned=0;
4238 return WERR_NOMEM;
4240 else printers = tp;
4241 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4243 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4244 (*returned)++;
4249 /* check the required size. */
4250 for (i=0; i<*returned; i++)
4251 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4253 if (!alloc_buffer_size(buffer, *needed))
4254 return WERR_INSUFFICIENT_BUFFER;
4256 /* fill the buffer with the structures */
4257 for (i=0; i<*returned; i++)
4258 smb_io_printer_info_1("", buffer, &printers[i], 0);
4260 /* clear memory */
4261 SAFE_FREE(printers);
4263 if (*needed > offered) {
4264 *returned=0;
4265 return WERR_INSUFFICIENT_BUFFER;
4267 else
4268 return WERR_OK;
4271 /********************************************************************
4272 enum_all_printers_info_1_local.
4273 *********************************************************************/
4275 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4277 DEBUG(4,("enum_all_printers_info_1_local\n"));
4279 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4282 /********************************************************************
4283 enum_all_printers_info_1_name.
4284 *********************************************************************/
4286 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4288 char *s = name;
4290 DEBUG(4,("enum_all_printers_info_1_name\n"));
4292 if ((name[0] == '\\') && (name[1] == '\\'))
4293 s = name + 2;
4295 if (is_myname_or_ipaddr(s)) {
4296 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4298 else
4299 return WERR_INVALID_NAME;
4302 /********************************************************************
4303 enum_all_printers_info_1_remote.
4304 *********************************************************************/
4306 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4308 PRINTER_INFO_1 *printer;
4309 fstring printername;
4310 fstring desc;
4311 fstring comment;
4312 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4314 /* JFM: currently it's more a place holder than anything else.
4315 * In the spooler world there is a notion of server registration.
4316 * the print servers are registring (sp ?) on the PDC (in the same domain)
4318 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4321 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4322 return WERR_NOMEM;
4324 *returned=1;
4326 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4327 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4328 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4330 init_unistr(&printer->description, desc);
4331 init_unistr(&printer->name, printername);
4332 init_unistr(&printer->comment, comment);
4333 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4335 /* check the required size. */
4336 *needed += spoolss_size_printer_info_1(printer);
4338 if (!alloc_buffer_size(buffer, *needed)) {
4339 SAFE_FREE(printer);
4340 return WERR_INSUFFICIENT_BUFFER;
4343 /* fill the buffer with the structures */
4344 smb_io_printer_info_1("", buffer, printer, 0);
4346 /* clear memory */
4347 SAFE_FREE(printer);
4349 if (*needed > offered) {
4350 *returned=0;
4351 return WERR_INSUFFICIENT_BUFFER;
4353 else
4354 return WERR_OK;
4357 /********************************************************************
4358 enum_all_printers_info_1_network.
4359 *********************************************************************/
4361 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4363 char *s = name;
4365 DEBUG(4,("enum_all_printers_info_1_network\n"));
4367 /* If we respond to a enum_printers level 1 on our name with flags
4368 set to PRINTER_ENUM_REMOTE with a list of printers then these
4369 printers incorrectly appear in the APW browse list.
4370 Specifically the printers for the server appear at the workgroup
4371 level where all the other servers in the domain are
4372 listed. Windows responds to this call with a
4373 WERR_CAN_NOT_COMPLETE so we should do the same. */
4375 if (name[0] == '\\' && name[1] == '\\')
4376 s = name + 2;
4378 if (is_myname_or_ipaddr(s))
4379 return WERR_CAN_NOT_COMPLETE;
4381 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4384 /********************************************************************
4385 * api_spoolss_enumprinters
4387 * called from api_spoolss_enumprinters (see this to understand)
4388 ********************************************************************/
4390 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4392 int snum;
4393 int i;
4394 int n_services=lp_numservices();
4395 PRINTER_INFO_2 *tp, *printers=NULL;
4396 PRINTER_INFO_2 current_prt;
4398 for (snum=0; snum<n_services; snum++) {
4399 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4400 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4402 if (construct_printer_info_2(&current_prt, snum)) {
4403 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4404 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4405 SAFE_FREE(printers);
4406 *returned = 0;
4407 return WERR_NOMEM;
4409 else printers = tp;
4410 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4411 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4412 (*returned)++;
4417 /* check the required size. */
4418 for (i=0; i<*returned; i++)
4419 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4421 if (!alloc_buffer_size(buffer, *needed)) {
4422 for (i=0; i<*returned; i++) {
4423 free_devmode(printers[i].devmode);
4425 SAFE_FREE(printers);
4426 return WERR_INSUFFICIENT_BUFFER;
4429 /* fill the buffer with the structures */
4430 for (i=0; i<*returned; i++)
4431 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4433 /* clear memory */
4434 for (i=0; i<*returned; i++) {
4435 free_devmode(printers[i].devmode);
4437 SAFE_FREE(printers);
4439 if (*needed > offered) {
4440 *returned=0;
4441 return WERR_INSUFFICIENT_BUFFER;
4443 else
4444 return WERR_OK;
4447 /********************************************************************
4448 * handle enumeration of printers at level 1
4449 ********************************************************************/
4451 static WERROR enumprinters_level1( uint32 flags, fstring name,
4452 NEW_BUFFER *buffer, uint32 offered,
4453 uint32 *needed, uint32 *returned)
4455 /* Not all the flags are equals */
4457 if (flags & PRINTER_ENUM_LOCAL)
4458 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4460 if (flags & PRINTER_ENUM_NAME)
4461 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4463 if (flags & PRINTER_ENUM_REMOTE)
4464 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4466 if (flags & PRINTER_ENUM_NETWORK)
4467 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4469 return WERR_OK; /* NT4sp5 does that */
4472 /********************************************************************
4473 * handle enumeration of printers at level 2
4474 ********************************************************************/
4476 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4477 NEW_BUFFER *buffer, uint32 offered,
4478 uint32 *needed, uint32 *returned)
4480 char *s = servername;
4482 if (flags & PRINTER_ENUM_LOCAL) {
4483 return enum_all_printers_info_2(buffer, offered, needed, returned);
4486 if (flags & PRINTER_ENUM_NAME) {
4487 if ((servername[0] == '\\') && (servername[1] == '\\'))
4488 s = servername + 2;
4489 if (is_myname_or_ipaddr(s))
4490 return enum_all_printers_info_2(buffer, offered, needed, returned);
4491 else
4492 return WERR_INVALID_NAME;
4495 if (flags & PRINTER_ENUM_REMOTE)
4496 return WERR_UNKNOWN_LEVEL;
4498 return WERR_OK;
4501 /********************************************************************
4502 * handle enumeration of printers at level 5
4503 ********************************************************************/
4505 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4506 NEW_BUFFER *buffer, uint32 offered,
4507 uint32 *needed, uint32 *returned)
4509 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4510 return WERR_OK;
4513 /********************************************************************
4514 * api_spoolss_enumprinters
4516 * called from api_spoolss_enumprinters (see this to understand)
4517 ********************************************************************/
4519 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4521 uint32 flags = q_u->flags;
4522 UNISTR2 *servername = &q_u->servername;
4523 uint32 level = q_u->level;
4524 NEW_BUFFER *buffer = NULL;
4525 uint32 offered = q_u->offered;
4526 uint32 *needed = &r_u->needed;
4527 uint32 *returned = &r_u->returned;
4529 fstring name;
4531 /* that's an [in out] buffer */
4532 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4533 buffer = r_u->buffer;
4535 DEBUG(4,("_spoolss_enumprinters\n"));
4537 *needed=0;
4538 *returned=0;
4541 * Level 1:
4542 * flags==PRINTER_ENUM_NAME
4543 * if name=="" then enumerates all printers
4544 * if name!="" then enumerate the printer
4545 * flags==PRINTER_ENUM_REMOTE
4546 * name is NULL, enumerate printers
4547 * Level 2: name!="" enumerates printers, name can't be NULL
4548 * Level 3: doesn't exist
4549 * Level 4: does a local registry lookup
4550 * Level 5: same as Level 2
4553 unistr2_to_ascii(name, servername, sizeof(name)-1);
4554 strupper(name);
4556 switch (level) {
4557 case 1:
4558 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4559 case 2:
4560 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4561 case 5:
4562 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4563 case 3:
4564 case 4:
4565 break;
4567 return WERR_UNKNOWN_LEVEL;
4570 /****************************************************************************
4571 ****************************************************************************/
4573 static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4575 PRINTER_INFO_0 *printer=NULL;
4577 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4578 return WERR_NOMEM;
4580 construct_printer_info_0(printer, snum);
4582 /* check the required size. */
4583 *needed += spoolss_size_printer_info_0(printer);
4585 if (!alloc_buffer_size(buffer, *needed)) {
4586 SAFE_FREE(printer);
4587 return WERR_INSUFFICIENT_BUFFER;
4590 /* fill the buffer with the structures */
4591 smb_io_printer_info_0("", buffer, printer, 0);
4593 /* clear memory */
4594 SAFE_FREE(printer);
4596 if (*needed > offered) {
4597 return WERR_INSUFFICIENT_BUFFER;
4600 return WERR_OK;
4603 /****************************************************************************
4604 ****************************************************************************/
4606 static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4608 PRINTER_INFO_1 *printer=NULL;
4610 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4611 return WERR_NOMEM;
4613 construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
4615 /* check the required size. */
4616 *needed += spoolss_size_printer_info_1(printer);
4618 if (!alloc_buffer_size(buffer, *needed)) {
4619 SAFE_FREE(printer);
4620 return WERR_INSUFFICIENT_BUFFER;
4623 /* fill the buffer with the structures */
4624 smb_io_printer_info_1("", buffer, printer, 0);
4626 /* clear memory */
4627 SAFE_FREE(printer);
4629 if (*needed > offered) {
4630 return WERR_INSUFFICIENT_BUFFER;
4633 return WERR_OK;
4636 /****************************************************************************
4637 ****************************************************************************/
4639 static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4641 PRINTER_INFO_2 *printer=NULL;
4643 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4644 return WERR_NOMEM;
4646 construct_printer_info_2(printer, snum);
4648 /* check the required size. */
4649 *needed += spoolss_size_printer_info_2(printer);
4651 if (!alloc_buffer_size(buffer, *needed)) {
4652 free_printer_info_2(printer);
4653 return WERR_INSUFFICIENT_BUFFER;
4656 /* fill the buffer with the structures */
4657 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4658 free_printer_info_2(printer);
4659 return WERR_NOMEM;
4662 /* clear memory */
4663 free_printer_info_2(printer);
4665 if (*needed > offered) {
4666 return WERR_INSUFFICIENT_BUFFER;
4669 return WERR_OK;
4672 /****************************************************************************
4673 ****************************************************************************/
4675 static WERROR getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4677 PRINTER_INFO_3 *printer=NULL;
4679 if (!construct_printer_info_3(&printer, snum))
4680 return WERR_NOMEM;
4682 /* check the required size. */
4683 *needed += spoolss_size_printer_info_3(printer);
4685 if (!alloc_buffer_size(buffer, *needed)) {
4686 free_printer_info_3(printer);
4687 return WERR_INSUFFICIENT_BUFFER;
4690 /* fill the buffer with the structures */
4691 smb_io_printer_info_3("", buffer, printer, 0);
4693 /* clear memory */
4694 free_printer_info_3(printer);
4696 if (*needed > offered) {
4697 return WERR_INSUFFICIENT_BUFFER;
4700 return WERR_OK;
4703 /****************************************************************************
4704 ****************************************************************************/
4706 static WERROR getprinter_level_4(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4708 PRINTER_INFO_4 *printer=NULL;
4710 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4711 return WERR_NOMEM;
4713 if (!construct_printer_info_4(printer, snum))
4714 return WERR_NOMEM;
4716 /* check the required size. */
4717 *needed += spoolss_size_printer_info_4(printer);
4719 if (!alloc_buffer_size(buffer, *needed)) {
4720 free_printer_info_4(printer);
4721 return WERR_INSUFFICIENT_BUFFER;
4724 /* fill the buffer with the structures */
4725 smb_io_printer_info_4("", buffer, printer, 0);
4727 /* clear memory */
4728 free_printer_info_4(printer);
4730 if (*needed > offered) {
4731 return WERR_INSUFFICIENT_BUFFER;
4734 return WERR_OK;
4737 /****************************************************************************
4738 ****************************************************************************/
4740 static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4742 PRINTER_INFO_5 *printer=NULL;
4744 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4745 return WERR_NOMEM;
4747 if (!construct_printer_info_5(printer, snum))
4748 return WERR_NOMEM;
4750 /* check the required size. */
4751 *needed += spoolss_size_printer_info_5(printer);
4753 if (!alloc_buffer_size(buffer, *needed)) {
4754 free_printer_info_5(printer);
4755 return WERR_INSUFFICIENT_BUFFER;
4758 /* fill the buffer with the structures */
4759 smb_io_printer_info_5("", buffer, printer, 0);
4761 /* clear memory */
4762 free_printer_info_5(printer);
4764 if (*needed > offered) {
4765 return WERR_INSUFFICIENT_BUFFER;
4768 return WERR_OK;
4771 static WERROR getprinter_level_7(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4773 PRINTER_INFO_7 *printer=NULL;
4775 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4776 return WERR_NOMEM;
4778 if (!construct_printer_info_7(printer, snum))
4779 return WERR_NOMEM;
4781 /* check the required size. */
4782 *needed += spoolss_size_printer_info_7(printer);
4784 if (!alloc_buffer_size(buffer, *needed)) {
4785 free_printer_info_7(printer);
4786 return WERR_INSUFFICIENT_BUFFER;
4789 /* fill the buffer with the structures */
4790 smb_io_printer_info_7("", buffer, printer, 0);
4792 /* clear memory */
4793 free_printer_info_7(printer);
4795 if (*needed > offered) {
4796 return WERR_INSUFFICIENT_BUFFER;
4799 return WERR_OK;
4802 /****************************************************************************
4803 ****************************************************************************/
4805 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4807 POLICY_HND *handle = &q_u->handle;
4808 uint32 level = q_u->level;
4809 NEW_BUFFER *buffer = NULL;
4810 uint32 offered = q_u->offered;
4811 uint32 *needed = &r_u->needed;
4813 int snum;
4815 /* that's an [in out] buffer */
4816 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4817 buffer = r_u->buffer;
4819 *needed=0;
4821 if (!get_printer_snum(p, handle, &snum))
4822 return WERR_BADFID;
4824 switch (level) {
4825 case 0:
4826 return getprinter_level_0(snum, buffer, offered, needed);
4827 case 1:
4828 return getprinter_level_1(snum, buffer, offered, needed);
4829 case 2:
4830 return getprinter_level_2(snum, buffer, offered, needed);
4831 case 3:
4832 return getprinter_level_3(snum, buffer, offered, needed);
4833 case 4:
4834 return getprinter_level_4(snum, buffer, offered, needed);
4835 case 5:
4836 return getprinter_level_5(snum, buffer, offered, needed);
4837 case 7:
4838 return getprinter_level_7(snum, buffer, offered, needed);
4840 return WERR_UNKNOWN_LEVEL;
4843 /********************************************************************
4844 * fill a DRIVER_INFO_1 struct
4845 ********************************************************************/
4847 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4849 init_unistr( &info->name, driver.info_3->name);
4852 /********************************************************************
4853 * construct_printer_driver_info_1
4854 ********************************************************************/
4856 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4858 NT_PRINTER_INFO_LEVEL *printer = NULL;
4859 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4861 ZERO_STRUCT(driver);
4863 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4864 return WERR_INVALID_PRINTER_NAME;
4866 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4867 return WERR_UNKNOWN_PRINTER_DRIVER;
4869 fill_printer_driver_info_1(info, driver, servername, architecture);
4871 free_a_printer(&printer,2);
4873 return WERR_OK;
4876 /********************************************************************
4877 * construct_printer_driver_info_2
4878 * fill a printer_info_2 struct
4879 ********************************************************************/
4881 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
4883 pstring temp;
4885 info->version=driver.info_3->cversion;
4887 init_unistr( &info->name, driver.info_3->name );
4888 init_unistr( &info->architecture, driver.info_3->environment );
4891 if (strlen(driver.info_3->driverpath)) {
4892 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
4893 init_unistr( &info->driverpath, temp );
4894 } else
4895 init_unistr( &info->driverpath, "" );
4897 if (strlen(driver.info_3->datafile)) {
4898 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
4899 init_unistr( &info->datafile, temp );
4900 } else
4901 init_unistr( &info->datafile, "" );
4903 if (strlen(driver.info_3->configfile)) {
4904 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
4905 init_unistr( &info->configfile, temp );
4906 } else
4907 init_unistr( &info->configfile, "" );
4910 /********************************************************************
4911 * construct_printer_driver_info_2
4912 * fill a printer_info_2 struct
4913 ********************************************************************/
4915 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
4917 NT_PRINTER_INFO_LEVEL *printer = NULL;
4918 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4920 ZERO_STRUCT(printer);
4921 ZERO_STRUCT(driver);
4923 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4924 return WERR_INVALID_PRINTER_NAME;
4926 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4927 return WERR_UNKNOWN_PRINTER_DRIVER;
4929 fill_printer_driver_info_2(info, driver, servername);
4931 free_a_printer(&printer,2);
4933 return WERR_OK;
4936 /********************************************************************
4937 * copy a strings array and convert to UNICODE
4939 * convert an array of ascii string to a UNICODE string
4940 ********************************************************************/
4942 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
4944 int i=0;
4945 int j=0;
4946 const char *v;
4947 pstring line;
4948 uint16 *tuary;
4950 DEBUG(6,("init_unistr_array\n"));
4951 *uni_array=NULL;
4953 while (True)
4955 if ( !char_array )
4956 v = "";
4957 else
4959 v = char_array[i];
4960 if (!v)
4961 v = ""; /* hack to handle null lists */
4964 /* hack to allow this to be used in places other than when generating
4965 the list of dependent files */
4967 if ( servername )
4968 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
4969 else
4970 pstrcpy( line, v );
4972 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
4974 /* add one extra unit16 for the second terminating NULL */
4976 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
4977 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4978 return 0;
4979 } else
4980 *uni_array = tuary;
4982 if ( !strlen(v) )
4983 break;
4985 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
4986 i++;
4989 if (*uni_array) {
4990 /* special case for ""; we need to add both NULL's here */
4991 if (!j)
4992 (*uni_array)[j++]=0x0000;
4993 (*uni_array)[j]=0x0000;
4996 DEBUGADD(6,("last one:done\n"));
4998 /* return size of array in uint16's */
5000 return j+1;
5003 /********************************************************************
5004 * construct_printer_info_3
5005 * fill a printer_info_3 struct
5006 ********************************************************************/
5008 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5010 pstring temp;
5012 ZERO_STRUCTP(info);
5014 info->version=driver.info_3->cversion;
5016 init_unistr( &info->name, driver.info_3->name );
5017 init_unistr( &info->architecture, driver.info_3->environment );
5019 if (strlen(driver.info_3->driverpath)) {
5020 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5021 init_unistr( &info->driverpath, temp );
5022 } else
5023 init_unistr( &info->driverpath, "" );
5025 if (strlen(driver.info_3->datafile)) {
5026 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5027 init_unistr( &info->datafile, temp );
5028 } else
5029 init_unistr( &info->datafile, "" );
5031 if (strlen(driver.info_3->configfile)) {
5032 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5033 init_unistr( &info->configfile, temp );
5034 } else
5035 init_unistr( &info->configfile, "" );
5037 if (strlen(driver.info_3->helpfile)) {
5038 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5039 init_unistr( &info->helpfile, temp );
5040 } else
5041 init_unistr( &info->helpfile, "" );
5043 init_unistr( &info->monitorname, driver.info_3->monitorname );
5044 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5046 info->dependentfiles=NULL;
5047 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5050 /********************************************************************
5051 * construct_printer_info_3
5052 * fill a printer_info_3 struct
5053 ********************************************************************/
5055 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5057 NT_PRINTER_INFO_LEVEL *printer = NULL;
5058 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5059 WERROR status;
5060 ZERO_STRUCT(driver);
5062 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5063 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5064 if (!W_ERROR_IS_OK(status))
5065 return WERR_INVALID_PRINTER_NAME;
5067 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5068 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5070 #if 0 /* JERRY */
5073 * I put this code in during testing. Helpful when commenting out the
5074 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5075 * as win2k always queries the driver using an infor level of 6.
5076 * I've left it in (but ifdef'd out) because I'll probably
5077 * use it in experimentation again in the future. --jerry 22/01/2002
5080 if (!W_ERROR_IS_OK(status)) {
5082 * Is this a W2k client ?
5084 if (version == 3) {
5085 /* Yes - try again with a WinNT driver. */
5086 version = 2;
5087 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5088 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5090 #endif
5092 if (!W_ERROR_IS_OK(status)) {
5093 free_a_printer(&printer,2);
5094 return WERR_UNKNOWN_PRINTER_DRIVER;
5097 #if 0 /* JERRY */
5099 #endif
5102 fill_printer_driver_info_3(info, driver, servername);
5104 free_a_printer(&printer,2);
5106 return WERR_OK;
5109 /********************************************************************
5110 * construct_printer_info_6
5111 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5112 ********************************************************************/
5114 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5116 pstring temp;
5117 fstring nullstr;
5119 ZERO_STRUCTP(info);
5120 memset(&nullstr, '\0', sizeof(fstring));
5122 info->version=driver.info_3->cversion;
5124 init_unistr( &info->name, driver.info_3->name );
5125 init_unistr( &info->architecture, driver.info_3->environment );
5127 if (strlen(driver.info_3->driverpath)) {
5128 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5129 init_unistr( &info->driverpath, temp );
5130 } else
5131 init_unistr( &info->driverpath, "" );
5133 if (strlen(driver.info_3->datafile)) {
5134 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5135 init_unistr( &info->datafile, temp );
5136 } else
5137 init_unistr( &info->datafile, "" );
5139 if (strlen(driver.info_3->configfile)) {
5140 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5141 init_unistr( &info->configfile, temp );
5142 } else
5143 init_unistr( &info->configfile, "" );
5145 if (strlen(driver.info_3->helpfile)) {
5146 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5147 init_unistr( &info->helpfile, temp );
5148 } else
5149 init_unistr( &info->helpfile, "" );
5151 init_unistr( &info->monitorname, driver.info_3->monitorname );
5152 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5154 info->dependentfiles = NULL;
5155 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5157 info->previousdrivernames=NULL;
5158 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5160 info->driver_date.low=0;
5161 info->driver_date.high=0;
5163 info->padding=0;
5164 info->driver_version_low=0;
5165 info->driver_version_high=0;
5167 init_unistr( &info->mfgname, "");
5168 init_unistr( &info->oem_url, "");
5169 init_unistr( &info->hardware_id, "");
5170 init_unistr( &info->provider, "");
5173 /********************************************************************
5174 * construct_printer_info_6
5175 * fill a printer_info_6 struct
5176 ********************************************************************/
5178 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5179 fstring servername, fstring architecture, uint32 version)
5181 NT_PRINTER_INFO_LEVEL *printer = NULL;
5182 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5183 WERROR status;
5185 ZERO_STRUCT(driver);
5187 status=get_a_printer(&printer, 2, lp_servicename(snum) );
5189 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5191 if (!W_ERROR_IS_OK(status))
5192 return WERR_INVALID_PRINTER_NAME;
5194 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5196 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5198 if (!W_ERROR_IS_OK(status))
5201 * Is this a W2k client ?
5204 if (version < 3) {
5205 free_a_printer(&printer,2);
5206 return WERR_UNKNOWN_PRINTER_DRIVER;
5209 /* Yes - try again with a WinNT driver. */
5210 version = 2;
5211 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5212 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5213 if (!W_ERROR_IS_OK(status)) {
5214 free_a_printer(&printer,2);
5215 return WERR_UNKNOWN_PRINTER_DRIVER;
5219 fill_printer_driver_info_6(info, driver, servername);
5221 free_a_printer(&printer,2);
5222 free_a_printer_driver(driver, 3);
5224 return WERR_OK;
5227 /****************************************************************************
5228 ****************************************************************************/
5230 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5232 SAFE_FREE(info->dependentfiles);
5235 /****************************************************************************
5236 ****************************************************************************/
5238 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5240 SAFE_FREE(info->dependentfiles);
5244 /****************************************************************************
5245 ****************************************************************************/
5247 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5249 DRIVER_INFO_1 *info=NULL;
5250 WERROR status;
5252 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5253 return WERR_NOMEM;
5255 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5256 if (!W_ERROR_IS_OK(status)) {
5257 SAFE_FREE(info);
5258 return status;
5261 /* check the required size. */
5262 *needed += spoolss_size_printer_driver_info_1(info);
5264 if (!alloc_buffer_size(buffer, *needed)) {
5265 SAFE_FREE(info);
5266 return WERR_INSUFFICIENT_BUFFER;
5269 /* fill the buffer with the structures */
5270 smb_io_printer_driver_info_1("", buffer, info, 0);
5272 /* clear memory */
5273 SAFE_FREE(info);
5275 if (*needed > offered)
5276 return WERR_INSUFFICIENT_BUFFER;
5278 return WERR_OK;
5281 /****************************************************************************
5282 ****************************************************************************/
5284 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5286 DRIVER_INFO_2 *info=NULL;
5287 WERROR status;
5289 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5290 return WERR_NOMEM;
5292 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5293 if (!W_ERROR_IS_OK(status)) {
5294 SAFE_FREE(info);
5295 return status;
5298 /* check the required size. */
5299 *needed += spoolss_size_printer_driver_info_2(info);
5301 if (!alloc_buffer_size(buffer, *needed)) {
5302 SAFE_FREE(info);
5303 return WERR_INSUFFICIENT_BUFFER;
5306 /* fill the buffer with the structures */
5307 smb_io_printer_driver_info_2("", buffer, info, 0);
5309 /* clear memory */
5310 SAFE_FREE(info);
5312 if (*needed > offered)
5313 return WERR_INSUFFICIENT_BUFFER;
5315 return WERR_OK;
5318 /****************************************************************************
5319 ****************************************************************************/
5321 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5323 DRIVER_INFO_3 info;
5324 WERROR status;
5326 ZERO_STRUCT(info);
5328 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5329 if (!W_ERROR_IS_OK(status)) {
5330 return status;
5333 /* check the required size. */
5334 *needed += spoolss_size_printer_driver_info_3(&info);
5336 if (!alloc_buffer_size(buffer, *needed)) {
5337 free_printer_driver_info_3(&info);
5338 return WERR_INSUFFICIENT_BUFFER;
5341 /* fill the buffer with the structures */
5342 smb_io_printer_driver_info_3("", buffer, &info, 0);
5344 free_printer_driver_info_3(&info);
5346 if (*needed > offered)
5347 return WERR_INSUFFICIENT_BUFFER;
5349 return WERR_OK;
5352 /****************************************************************************
5353 ****************************************************************************/
5355 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5357 DRIVER_INFO_6 info;
5358 WERROR status;
5360 ZERO_STRUCT(info);
5362 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5363 if (!W_ERROR_IS_OK(status)) {
5364 return status;
5367 /* check the required size. */
5368 *needed += spoolss_size_printer_driver_info_6(&info);
5370 if (!alloc_buffer_size(buffer, *needed)) {
5371 free_printer_driver_info_6(&info);
5372 return WERR_INSUFFICIENT_BUFFER;
5375 /* fill the buffer with the structures */
5376 smb_io_printer_driver_info_6("", buffer, &info, 0);
5378 free_printer_driver_info_6(&info);
5380 if (*needed > offered)
5381 return WERR_INSUFFICIENT_BUFFER;
5383 return WERR_OK;
5386 /****************************************************************************
5387 ****************************************************************************/
5389 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5391 POLICY_HND *handle = &q_u->handle;
5392 UNISTR2 *uni_arch = &q_u->architecture;
5393 uint32 level = q_u->level;
5394 uint32 clientmajorversion = q_u->clientmajorversion;
5395 NEW_BUFFER *buffer = NULL;
5396 uint32 offered = q_u->offered;
5397 uint32 *needed = &r_u->needed;
5398 uint32 *servermajorversion = &r_u->servermajorversion;
5399 uint32 *serverminorversion = &r_u->serverminorversion;
5401 fstring servername;
5402 fstring architecture;
5403 int snum;
5405 /* that's an [in out] buffer */
5406 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5407 buffer = r_u->buffer;
5409 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5411 *needed = 0;
5412 *servermajorversion = 0;
5413 *serverminorversion = 0;
5415 fstrcpy(servername, get_called_name());
5416 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5418 if (!get_printer_snum(p, handle, &snum))
5419 return WERR_BADFID;
5421 switch (level) {
5422 case 1:
5423 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5424 case 2:
5425 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5426 case 3:
5427 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5428 case 6:
5429 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5432 return WERR_UNKNOWN_LEVEL;
5435 /****************************************************************************
5436 ****************************************************************************/
5438 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5440 POLICY_HND *handle = &q_u->handle;
5442 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5444 if (!Printer) {
5445 DEBUG(3,("Error in startpageprinter printer handle\n"));
5446 return WERR_BADFID;
5449 Printer->page_started=True;
5450 return WERR_OK;
5453 /****************************************************************************
5454 ****************************************************************************/
5456 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5458 POLICY_HND *handle = &q_u->handle;
5459 int snum;
5461 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5463 if (!Printer) {
5464 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5465 return WERR_BADFID;
5468 if (!get_printer_snum(p, handle, &snum))
5469 return WERR_BADFID;
5471 Printer->page_started=False;
5472 print_job_endpage(snum, Printer->jobid);
5474 return WERR_OK;
5477 /********************************************************************
5478 * api_spoolss_getprinter
5479 * called from the spoolss dispatcher
5481 ********************************************************************/
5483 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5485 POLICY_HND *handle = &q_u->handle;
5486 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5487 uint32 *jobid = &r_u->jobid;
5489 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5490 int snum;
5491 pstring jobname;
5492 fstring datatype;
5493 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5494 struct current_user user;
5496 if (!Printer) {
5497 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5498 return WERR_BADFID;
5501 get_current_user(&user, p);
5504 * a nice thing with NT is it doesn't listen to what you tell it.
5505 * when asked to send _only_ RAW datas, it tries to send datas
5506 * in EMF format.
5508 * So I add checks like in NT Server ...
5511 if (info_1->p_datatype != 0) {
5512 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5513 if (strcmp(datatype, "RAW") != 0) {
5514 (*jobid)=0;
5515 return WERR_INVALID_DATATYPE;
5519 /* get the share number of the printer */
5520 if (!get_printer_snum(p, handle, &snum)) {
5521 return WERR_BADFID;
5524 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5526 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5528 /* An error occured in print_job_start() so return an appropriate
5529 NT error code. */
5531 if (Printer->jobid == -1) {
5532 return map_werror_from_unix(errno);
5535 Printer->document_started=True;
5536 (*jobid) = Printer->jobid;
5538 return WERR_OK;
5541 /********************************************************************
5542 * api_spoolss_getprinter
5543 * called from the spoolss dispatcher
5545 ********************************************************************/
5547 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5549 POLICY_HND *handle = &q_u->handle;
5551 return _spoolss_enddocprinter_internal(p, handle);
5554 /****************************************************************************
5555 ****************************************************************************/
5557 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5559 POLICY_HND *handle = &q_u->handle;
5560 uint32 buffer_size = q_u->buffer_size;
5561 uint8 *buffer = q_u->buffer;
5562 uint32 *buffer_written = &q_u->buffer_size2;
5563 int snum;
5564 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5566 if (!Printer) {
5567 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5568 r_u->buffer_written = q_u->buffer_size2;
5569 return WERR_BADFID;
5572 if (!get_printer_snum(p, handle, &snum))
5573 return WERR_BADFID;
5575 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5576 if (*buffer_written == -1) {
5577 r_u->buffer_written = 0;
5578 if (errno == ENOSPC)
5579 return WERR_NO_SPOOL_SPACE;
5580 else
5581 return WERR_ACCESS_DENIED;
5584 r_u->buffer_written = q_u->buffer_size2;
5586 return WERR_OK;
5589 /********************************************************************
5590 * api_spoolss_getprinter
5591 * called from the spoolss dispatcher
5593 ********************************************************************/
5595 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5596 pipes_struct *p)
5598 struct current_user user;
5599 int snum;
5600 WERROR errcode = WERR_BADFUNC;
5601 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5603 get_current_user(&user, p);
5605 if (!Printer) {
5606 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5607 return WERR_BADFID;
5610 if (!get_printer_snum(p, handle, &snum))
5611 return WERR_BADFID;
5613 switch (command) {
5614 case PRINTER_CONTROL_PAUSE:
5615 if (print_queue_pause(&user, snum, &errcode)) {
5616 errcode = WERR_OK;
5618 break;
5619 case PRINTER_CONTROL_RESUME:
5620 case PRINTER_CONTROL_UNPAUSE:
5621 if (print_queue_resume(&user, snum, &errcode)) {
5622 errcode = WERR_OK;
5624 break;
5625 case PRINTER_CONTROL_PURGE:
5626 if (print_queue_purge(&user, snum, &errcode)) {
5627 errcode = WERR_OK;
5629 break;
5630 default:
5631 return WERR_UNKNOWN_LEVEL;
5634 return errcode;
5637 /********************************************************************
5638 * api_spoolss_abortprinter
5639 * From MSDN: "Deletes printer's spool file if printer is configured
5640 * for spooling"
5641 ********************************************************************/
5643 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5645 POLICY_HND *handle = &q_u->handle;
5646 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5647 int snum;
5648 struct current_user user;
5649 WERROR errcode = WERR_OK;
5651 if (!Printer) {
5652 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5653 return WERR_BADFID;
5656 if (!get_printer_snum(p, handle, &snum))
5657 return WERR_BADFID;
5659 get_current_user( &user, p );
5661 print_job_delete( &user, snum, Printer->jobid, &errcode );
5663 return errcode;
5666 /********************************************************************
5667 * called by spoolss_api_setprinter
5668 * when updating a printer description
5669 ********************************************************************/
5671 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5672 const SPOOL_PRINTER_INFO_LEVEL *info,
5673 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5675 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5676 struct current_user user;
5677 WERROR result;
5678 int snum;
5680 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5682 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5683 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5684 OUR_HANDLE(handle)));
5686 result = WERR_BADFID;
5687 goto done;
5690 /* NT seems to like setting the security descriptor even though
5691 nothing may have actually changed. This causes annoying
5692 dialog boxes when the user doesn't have permission to change
5693 the security descriptor. */
5695 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5697 if (DEBUGLEVEL >= 10) {
5698 SEC_ACL *the_acl;
5699 int i;
5701 the_acl = old_secdesc_ctr->sec->dacl;
5702 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5703 PRINTERNAME(snum), the_acl->num_aces));
5705 for (i = 0; i < the_acl->num_aces; i++) {
5706 fstring sid_str;
5708 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5710 DEBUG(10, ("%s 0x%08x\n", sid_str,
5711 the_acl->ace[i].info.mask));
5714 the_acl = secdesc_ctr->sec->dacl;
5716 if (the_acl) {
5717 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5718 PRINTERNAME(snum), the_acl->num_aces));
5720 for (i = 0; i < the_acl->num_aces; i++) {
5721 fstring sid_str;
5723 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5725 DEBUG(10, ("%s 0x%08x\n", sid_str,
5726 the_acl->ace[i].info.mask));
5728 } else {
5729 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5733 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5735 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5736 result = WERR_OK;
5737 goto done;
5740 /* Work out which user is performing the operation */
5742 get_current_user(&user, p);
5744 /* Check the user has permissions to change the security
5745 descriptor. By experimentation with two NT machines, the user
5746 requires Full Access to the printer to change security
5747 information. */
5749 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5750 result = WERR_ACCESS_DENIED;
5751 goto done;
5754 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5756 done:
5758 return result;
5761 /********************************************************************
5762 Do Samba sanity checks on a printer info struct.
5763 this has changed purpose: it now "canonicalises" printer
5764 info from a client rather than just checking it is correct
5765 ********************************************************************/
5767 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5769 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5770 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5772 /* we force some elements to "correct" values */
5773 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5774 fstrcpy(info->sharename, lp_servicename(snum));
5775 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5776 get_called_name(), info->sharename);
5777 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5780 return True;
5783 /****************************************************************************
5784 ****************************************************************************/
5786 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5788 extern userdom_struct current_user_info;
5789 char *cmd = lp_addprinter_cmd();
5790 char **qlines;
5791 pstring command;
5792 int numlines;
5793 int ret;
5794 int fd;
5795 fstring remote_machine = "%m";
5797 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5799 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5800 cmd, printer->info_2->printername, printer->info_2->sharename,
5801 printer->info_2->portname, printer->info_2->drivername,
5802 printer->info_2->location, printer->info_2->comment, remote_machine);
5804 DEBUG(10,("Running [%s]\n", command));
5805 ret = smbrun(command, &fd);
5806 DEBUGADD(10,("returned [%d]\n", ret));
5808 if ( ret != 0 ) {
5809 if (fd != -1)
5810 close(fd);
5811 return False;
5814 numlines = 0;
5815 /* Get lines and convert them back to dos-codepage */
5816 qlines = fd_lines_load(fd, &numlines);
5817 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5818 close(fd);
5820 if(numlines) {
5821 /* Set the portname to what the script says the portname should be. */
5822 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5823 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5825 /* Send SIGHUP to process group... is there a better way? */
5826 kill(0, SIGHUP);
5828 /* reload our services immediately */
5829 reload_services( False );
5832 file_lines_free(qlines);
5833 return True;
5836 /********************************************************************
5837 * Called by spoolss_api_setprinter
5838 * when updating a printer description.
5839 ********************************************************************/
5841 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5842 const SPOOL_PRINTER_INFO_LEVEL *info,
5843 DEVICEMODE *devmode)
5845 int snum;
5846 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5847 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5848 WERROR result;
5849 UNISTR2 buffer;
5850 fstring asc_buffer;
5852 DEBUG(8,("update_printer\n"));
5854 result = WERR_OK;
5856 if (level!=2) {
5857 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5858 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5859 result = WERR_UNKNOWN_LEVEL;
5860 goto done;
5863 if (!Printer) {
5864 result = WERR_BADFID;
5865 goto done;
5868 if (!get_printer_snum(p, handle, &snum)) {
5869 result = WERR_BADFID;
5870 goto done;
5873 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ||
5874 (!W_ERROR_IS_OK(get_a_printer(&old_printer, 2, lp_servicename(snum))))) {
5875 result = WERR_BADFID;
5876 goto done;
5879 DEBUGADD(8,("Converting info_2 struct\n"));
5882 * convert_printer_info converts the incoming
5883 * info from the client and overwrites the info
5884 * just read from the tdb in the pointer 'printer'.
5887 if (!convert_printer_info(info, printer, level)) {
5888 result = WERR_NOMEM;
5889 goto done;
5892 if (devmode) {
5893 /* we have a valid devmode
5894 convert it and link it*/
5896 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5897 if (!convert_devicemode(printer->info_2->printername, devmode,
5898 &printer->info_2->devmode)) {
5899 result = WERR_NOMEM;
5900 goto done;
5904 * make sure we actually reload the services after
5905 * this as smb.conf could have a new section in it
5906 * .... shouldn't .... but could
5908 reload_services(False);
5911 /* Do sanity check on the requested changes for Samba */
5913 if (!check_printer_ok(printer->info_2, snum)) {
5914 result = WERR_INVALID_PARAM;
5915 goto done;
5918 /* Check calling user has permission to update printer description */
5920 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5921 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5922 result = WERR_ACCESS_DENIED;
5923 goto done;
5926 /* Call addprinter hook */
5927 /* Check changes to see if this is really needed */
5929 if ( *lp_addprinter_cmd()
5930 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5931 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5932 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5933 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5935 if ( !add_printer_hook(printer) ) {
5936 result = WERR_ACCESS_DENIED;
5937 goto done;
5941 * make sure we actually reload the services after
5942 * this as smb.conf could have a new section in it
5943 * .... shouldn't .... but could
5945 reload_services(False);
5949 * When a *new* driver is bound to a printer, the drivername is used to
5950 * lookup previously saved driver initialization info, which is then
5951 * bound to the printer, simulating what happens in the Windows arch.
5953 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5955 if (!set_driver_init(printer, 2))
5957 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5958 printer->info_2->drivername));
5961 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5962 printer->info_2->drivername));
5964 notify_printer_driver(snum, printer->info_2->drivername);
5967 /* Update printer info */
5968 result = mod_a_printer(*printer, 2);
5971 * flag which changes actually occured. This is a small subset of
5972 * all the possible changes. We also have to update things in the
5973 * DsSpooler key.
5976 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5977 init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 );
5978 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5979 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5981 notify_printer_comment(snum, printer->info_2->comment);
5984 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5985 init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 );
5986 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5987 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5988 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5989 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5991 notify_printer_sharename(snum, printer->info_2->sharename);
5994 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5995 init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 );
5996 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5997 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5999 notify_printer_port(snum, printer->info_2->portname);
6002 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6003 init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 );
6004 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6005 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6007 notify_printer_location(snum, printer->info_2->location);
6010 /* here we need to update some more DsSpooler keys */
6011 /* uNCName, serverName, shortServerName */
6013 init_unistr2( &buffer, global_myname(), strlen(global_myname())+1 );
6014 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6015 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6016 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6017 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6019 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6020 global_myname(), printer->info_2->sharename );
6021 init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 );
6022 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6023 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6025 done:
6026 free_a_printer(&printer, 2);
6027 free_a_printer(&old_printer, 2);
6030 return result;
6033 /****************************************************************************
6034 ****************************************************************************/
6035 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6036 const SPOOL_PRINTER_INFO_LEVEL *info)
6038 #ifdef HAVE_ADS
6039 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6040 int snum;
6041 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6042 WERROR result;
6044 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6046 result = WERR_OK;
6048 if (!Printer)
6049 return WERR_BADFID;
6051 if (!get_printer_snum(p, handle, &snum))
6052 return WERR_BADFID;
6054 nt_printer_publish(snum, info7->action);
6056 return WERR_OK;
6057 #else
6058 return WERR_UNKNOWN_LEVEL;
6059 #endif
6061 /****************************************************************************
6062 ****************************************************************************/
6064 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6066 POLICY_HND *handle = &q_u->handle;
6067 uint32 level = q_u->level;
6068 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6069 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6070 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6071 uint32 command = q_u->command;
6073 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6075 if (!Printer) {
6076 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6077 return WERR_BADFID;
6080 /* check the level */
6081 switch (level) {
6082 case 0:
6083 return control_printer(handle, command, p);
6084 case 2:
6085 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6086 case 3:
6087 return update_printer_sec(handle, level, info, p,
6088 secdesc_ctr);
6089 case 7:
6090 return publish_or_unpublish_printer(p, handle, info);
6091 default:
6092 return WERR_UNKNOWN_LEVEL;
6096 /****************************************************************************
6097 ****************************************************************************/
6099 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6101 POLICY_HND *handle = &q_u->handle;
6102 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6104 if (!Printer) {
6105 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6106 return WERR_BADFID;
6109 if (Printer->notify.client_connected==True) {
6110 int snum = -1;
6112 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6113 snum = -1;
6114 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6115 !get_printer_snum(p, handle, &snum) )
6116 return WERR_BADFID;
6118 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6121 Printer->notify.flags=0;
6122 Printer->notify.options=0;
6123 Printer->notify.localmachine[0]='\0';
6124 Printer->notify.printerlocal=0;
6125 if (Printer->notify.option)
6126 free_spool_notify_option(&Printer->notify.option);
6127 Printer->notify.client_connected=False;
6129 return WERR_OK;
6132 /****************************************************************************
6133 ****************************************************************************/
6135 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6137 /* that's an [in out] buffer (despite appearences to the contrary) */
6138 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6140 r_u->needed = 0;
6141 return WERR_INVALID_PARAM; /* this is what a NT server
6142 returns for AddJob. AddJob
6143 must fail on non-local
6144 printers */
6147 /****************************************************************************
6148 ****************************************************************************/
6150 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6151 int position, int snum)
6153 pstring temp_name;
6155 struct tm *t;
6157 t=gmtime(&queue->time);
6158 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6160 job_info->jobid=queue->job;
6161 init_unistr(&job_info->printername, lp_servicename(snum));
6162 init_unistr(&job_info->machinename, temp_name);
6163 init_unistr(&job_info->username, queue->fs_user);
6164 init_unistr(&job_info->document, queue->fs_file);
6165 init_unistr(&job_info->datatype, "RAW");
6166 init_unistr(&job_info->text_status, "");
6167 job_info->status=nt_printj_status(queue->status);
6168 job_info->priority=queue->priority;
6169 job_info->position=position;
6170 job_info->totalpages=queue->page_count;
6171 job_info->pagesprinted=0;
6173 make_systemtime(&job_info->submitted, t);
6176 /****************************************************************************
6177 ****************************************************************************/
6179 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6180 int position, int snum,
6181 NT_PRINTER_INFO_LEVEL *ntprinter,
6182 DEVICEMODE *devmode)
6184 pstring temp_name;
6185 struct tm *t;
6187 t=gmtime(&queue->time);
6188 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6190 job_info->jobid=queue->job;
6192 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6194 init_unistr(&job_info->machinename, temp_name);
6195 init_unistr(&job_info->username, queue->fs_user);
6196 init_unistr(&job_info->document, queue->fs_file);
6197 init_unistr(&job_info->notifyname, queue->fs_user);
6198 init_unistr(&job_info->datatype, "RAW");
6199 init_unistr(&job_info->printprocessor, "winprint");
6200 init_unistr(&job_info->parameters, "");
6201 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6202 init_unistr(&job_info->text_status, "");
6204 /* and here the security descriptor */
6206 job_info->status=nt_printj_status(queue->status);
6207 job_info->priority=queue->priority;
6208 job_info->position=position;
6209 job_info->starttime=0;
6210 job_info->untiltime=0;
6211 job_info->totalpages=queue->page_count;
6212 job_info->size=queue->size;
6213 make_systemtime(&(job_info->submitted), t);
6214 job_info->timeelapsed=0;
6215 job_info->pagesprinted=0;
6217 job_info->devmode = devmode;
6219 return (True);
6222 /****************************************************************************
6223 Enumjobs at level 1.
6224 ****************************************************************************/
6226 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6227 NEW_BUFFER *buffer, uint32 offered,
6228 uint32 *needed, uint32 *returned)
6230 JOB_INFO_1 *info;
6231 int i;
6233 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6234 if (info==NULL) {
6235 SAFE_FREE(queue);
6236 *returned=0;
6237 return WERR_NOMEM;
6240 for (i=0; i<*returned; i++)
6241 fill_job_info_1(&info[i], &queue[i], i, snum);
6243 SAFE_FREE(queue);
6245 /* check the required size. */
6246 for (i=0; i<*returned; i++)
6247 (*needed) += spoolss_size_job_info_1(&info[i]);
6249 if (!alloc_buffer_size(buffer, *needed)) {
6250 SAFE_FREE(info);
6251 return WERR_INSUFFICIENT_BUFFER;
6254 /* fill the buffer with the structures */
6255 for (i=0; i<*returned; i++)
6256 smb_io_job_info_1("", buffer, &info[i], 0);
6258 /* clear memory */
6259 SAFE_FREE(info);
6261 if (*needed > offered) {
6262 *returned=0;
6263 return WERR_INSUFFICIENT_BUFFER;
6266 return WERR_OK;
6269 /****************************************************************************
6270 Enumjobs at level 2.
6271 ****************************************************************************/
6273 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6274 NEW_BUFFER *buffer, uint32 offered,
6275 uint32 *needed, uint32 *returned)
6277 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6278 JOB_INFO_2 *info = NULL;
6279 int i;
6280 WERROR result;
6281 DEVICEMODE *devmode = NULL;
6283 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6284 if (info==NULL) {
6285 *returned=0;
6286 result = WERR_NOMEM;
6287 goto done;
6290 result = get_a_printer(&ntprinter, 2, lp_servicename(snum));
6291 if (!W_ERROR_IS_OK(result)) {
6292 *returned = 0;
6293 goto done;
6296 /* this should not be a failure condition if the devmode is NULL */
6298 devmode = construct_dev_mode(snum);
6300 for (i=0; i<*returned; i++)
6301 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6302 devmode);
6304 free_a_printer(&ntprinter, 2);
6305 SAFE_FREE(queue);
6307 /* check the required size. */
6308 for (i=0; i<*returned; i++)
6309 (*needed) += spoolss_size_job_info_2(&info[i]);
6311 if (*needed > offered) {
6312 *returned=0;
6313 result = WERR_INSUFFICIENT_BUFFER;
6314 goto done;
6317 if (!alloc_buffer_size(buffer, *needed)) {
6318 SAFE_FREE(info);
6319 result = WERR_INSUFFICIENT_BUFFER;
6320 goto done;
6323 /* fill the buffer with the structures */
6324 for (i=0; i<*returned; i++)
6325 smb_io_job_info_2("", buffer, &info[i], 0);
6327 result = WERR_OK;
6329 done:
6330 free_a_printer(&ntprinter, 2);
6331 free_devmode(devmode);
6332 SAFE_FREE(queue);
6333 SAFE_FREE(info);
6335 return result;
6339 /****************************************************************************
6340 Enumjobs.
6341 ****************************************************************************/
6343 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6345 POLICY_HND *handle = &q_u->handle;
6346 uint32 level = q_u->level;
6347 NEW_BUFFER *buffer = NULL;
6348 uint32 offered = q_u->offered;
6349 uint32 *needed = &r_u->needed;
6350 uint32 *returned = &r_u->returned;
6352 int snum;
6353 print_status_struct prt_status;
6354 print_queue_struct *queue=NULL;
6356 /* that's an [in out] buffer */
6357 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6358 buffer = r_u->buffer;
6360 DEBUG(4,("_spoolss_enumjobs\n"));
6362 *needed=0;
6363 *returned=0;
6365 if (!get_printer_snum(p, handle, &snum))
6366 return WERR_BADFID;
6368 *returned = print_queue_status(snum, &queue, &prt_status);
6369 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6371 if (*returned == 0) {
6372 SAFE_FREE(queue);
6373 return WERR_OK;
6376 switch (level) {
6377 case 1:
6378 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6379 case 2:
6380 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6381 default:
6382 SAFE_FREE(queue);
6383 *returned=0;
6384 return WERR_UNKNOWN_LEVEL;
6388 /****************************************************************************
6389 ****************************************************************************/
6391 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6393 return WERR_OK;
6396 /****************************************************************************
6397 ****************************************************************************/
6399 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6401 POLICY_HND *handle = &q_u->handle;
6402 uint32 jobid = q_u->jobid;
6403 uint32 command = q_u->command;
6405 struct current_user user;
6406 int snum;
6407 WERROR errcode = WERR_BADFUNC;
6409 if (!get_printer_snum(p, handle, &snum)) {
6410 return WERR_BADFID;
6413 if (!print_job_exists(snum, jobid)) {
6414 return WERR_INVALID_PRINTER_NAME;
6417 get_current_user(&user, p);
6419 switch (command) {
6420 case JOB_CONTROL_CANCEL:
6421 case JOB_CONTROL_DELETE:
6422 if (print_job_delete(&user, snum, jobid, &errcode)) {
6423 errcode = WERR_OK;
6425 break;
6426 case JOB_CONTROL_PAUSE:
6427 if (print_job_pause(&user, snum, jobid, &errcode)) {
6428 errcode = WERR_OK;
6430 break;
6431 case JOB_CONTROL_RESTART:
6432 case JOB_CONTROL_RESUME:
6433 if (print_job_resume(&user, snum, jobid, &errcode)) {
6434 errcode = WERR_OK;
6436 break;
6437 default:
6438 return WERR_UNKNOWN_LEVEL;
6441 return errcode;
6444 /****************************************************************************
6445 Enumerates all printer drivers at level 1.
6446 ****************************************************************************/
6448 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6450 int i;
6451 int ndrivers;
6452 uint32 version;
6453 fstring *list = NULL;
6455 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6456 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6458 *returned=0;
6460 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6461 list=NULL;
6462 ndrivers=get_ntdrivers(&list, architecture, version);
6463 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6465 if(ndrivers == -1)
6466 return WERR_NOMEM;
6468 if(ndrivers != 0) {
6469 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6470 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6471 SAFE_FREE(driver_info_1);
6472 SAFE_FREE(list);
6473 return WERR_NOMEM;
6475 else driver_info_1 = tdi1;
6478 for (i=0; i<ndrivers; i++) {
6479 WERROR status;
6480 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6481 ZERO_STRUCT(driver);
6482 status = get_a_printer_driver(&driver, 3, list[i],
6483 architecture, version);
6484 if (!W_ERROR_IS_OK(status)) {
6485 SAFE_FREE(list);
6486 return status;
6488 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6489 free_a_printer_driver(driver, 3);
6492 *returned+=ndrivers;
6493 SAFE_FREE(list);
6496 /* check the required size. */
6497 for (i=0; i<*returned; i++) {
6498 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6499 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6502 if (!alloc_buffer_size(buffer, *needed)) {
6503 SAFE_FREE(driver_info_1);
6504 return WERR_INSUFFICIENT_BUFFER;
6507 /* fill the buffer with the driver structures */
6508 for (i=0; i<*returned; i++) {
6509 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6510 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6513 SAFE_FREE(driver_info_1);
6515 if (*needed > offered) {
6516 *returned=0;
6517 return WERR_INSUFFICIENT_BUFFER;
6520 return WERR_OK;
6523 /****************************************************************************
6524 Enumerates all printer drivers at level 2.
6525 ****************************************************************************/
6527 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6529 int i;
6530 int ndrivers;
6531 uint32 version;
6532 fstring *list = NULL;
6534 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6535 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6537 *returned=0;
6539 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6540 list=NULL;
6541 ndrivers=get_ntdrivers(&list, architecture, version);
6542 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6544 if(ndrivers == -1)
6545 return WERR_NOMEM;
6547 if(ndrivers != 0) {
6548 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6549 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6550 SAFE_FREE(driver_info_2);
6551 SAFE_FREE(list);
6552 return WERR_NOMEM;
6554 else driver_info_2 = tdi2;
6557 for (i=0; i<ndrivers; i++) {
6558 WERROR status;
6560 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6561 ZERO_STRUCT(driver);
6562 status = get_a_printer_driver(&driver, 3, list[i],
6563 architecture, version);
6564 if (!W_ERROR_IS_OK(status)) {
6565 SAFE_FREE(list);
6566 return status;
6568 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6569 free_a_printer_driver(driver, 3);
6572 *returned+=ndrivers;
6573 SAFE_FREE(list);
6576 /* check the required size. */
6577 for (i=0; i<*returned; i++) {
6578 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6579 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6582 if (!alloc_buffer_size(buffer, *needed)) {
6583 SAFE_FREE(driver_info_2);
6584 return WERR_INSUFFICIENT_BUFFER;
6587 /* fill the buffer with the form structures */
6588 for (i=0; i<*returned; i++) {
6589 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6590 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6593 SAFE_FREE(driver_info_2);
6595 if (*needed > offered) {
6596 *returned=0;
6597 return WERR_INSUFFICIENT_BUFFER;
6600 return WERR_OK;
6603 /****************************************************************************
6604 Enumerates all printer drivers at level 3.
6605 ****************************************************************************/
6607 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6609 int i;
6610 int ndrivers;
6611 uint32 version;
6612 fstring *list = NULL;
6614 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6615 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6617 *returned=0;
6619 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6620 list=NULL;
6621 ndrivers=get_ntdrivers(&list, architecture, version);
6622 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6624 if(ndrivers == -1)
6625 return WERR_NOMEM;
6627 if(ndrivers != 0) {
6628 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6629 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6630 SAFE_FREE(driver_info_3);
6631 SAFE_FREE(list);
6632 return WERR_NOMEM;
6634 else driver_info_3 = tdi3;
6637 for (i=0; i<ndrivers; i++) {
6638 WERROR status;
6640 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6641 ZERO_STRUCT(driver);
6642 status = get_a_printer_driver(&driver, 3, list[i],
6643 architecture, version);
6644 if (!W_ERROR_IS_OK(status)) {
6645 SAFE_FREE(list);
6646 return status;
6648 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6649 free_a_printer_driver(driver, 3);
6652 *returned+=ndrivers;
6653 SAFE_FREE(list);
6656 /* check the required size. */
6657 for (i=0; i<*returned; i++) {
6658 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6659 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6662 if (!alloc_buffer_size(buffer, *needed)) {
6663 SAFE_FREE(driver_info_3);
6664 return WERR_INSUFFICIENT_BUFFER;
6667 /* fill the buffer with the driver structures */
6668 for (i=0; i<*returned; i++) {
6669 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6670 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6673 for (i=0; i<*returned; i++)
6674 SAFE_FREE(driver_info_3[i].dependentfiles);
6676 SAFE_FREE(driver_info_3);
6678 if (*needed > offered) {
6679 *returned=0;
6680 return WERR_INSUFFICIENT_BUFFER;
6683 return WERR_OK;
6686 /****************************************************************************
6687 Enumerates all printer drivers.
6688 ****************************************************************************/
6690 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6692 UNISTR2 *environment = &q_u->environment;
6693 uint32 level = q_u->level;
6694 NEW_BUFFER *buffer = NULL;
6695 uint32 offered = q_u->offered;
6696 uint32 *needed = &r_u->needed;
6697 uint32 *returned = &r_u->returned;
6699 fstring *list = NULL;
6700 fstring servername;
6701 fstring architecture;
6703 /* that's an [in out] buffer */
6704 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6705 buffer = r_u->buffer;
6707 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6708 fstrcpy(servername, get_called_name());
6709 *needed=0;
6710 *returned=0;
6712 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6714 switch (level) {
6715 case 1:
6716 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6717 case 2:
6718 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6719 case 3:
6720 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6721 default:
6722 *returned=0;
6723 SAFE_FREE(list);
6724 return WERR_UNKNOWN_LEVEL;
6728 /****************************************************************************
6729 ****************************************************************************/
6731 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6733 form->flag=list->flag;
6734 init_unistr(&form->name, list->name);
6735 form->width=list->width;
6736 form->length=list->length;
6737 form->left=list->left;
6738 form->top=list->top;
6739 form->right=list->right;
6740 form->bottom=list->bottom;
6743 /****************************************************************************
6744 ****************************************************************************/
6746 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6748 uint32 level = q_u->level;
6749 NEW_BUFFER *buffer = NULL;
6750 uint32 offered = q_u->offered;
6751 uint32 *needed = &r_u->needed;
6752 uint32 *numofforms = &r_u->numofforms;
6753 uint32 numbuiltinforms;
6755 nt_forms_struct *list=NULL;
6756 nt_forms_struct *builtinlist=NULL;
6757 FORM_1 *forms_1;
6758 int buffer_size=0;
6759 int i;
6761 /* that's an [in out] buffer */
6762 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6763 buffer = r_u->buffer;
6765 DEBUG(4,("_spoolss_enumforms\n"));
6766 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6767 DEBUGADD(5,("Info level [%d]\n", level));
6769 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6770 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6771 *numofforms = get_ntforms(&list);
6772 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6773 *numofforms += numbuiltinforms;
6775 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6777 switch (level) {
6778 case 1:
6779 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6780 *numofforms=0;
6781 return WERR_NOMEM;
6784 /* construct the list of form structures */
6785 for (i=0; i<numbuiltinforms; i++) {
6786 DEBUGADD(6,("Filling form number [%d]\n",i));
6787 fill_form_1(&forms_1[i], &builtinlist[i]);
6790 SAFE_FREE(builtinlist);
6792 for (; i<*numofforms; i++) {
6793 DEBUGADD(6,("Filling form number [%d]\n",i));
6794 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6797 SAFE_FREE(list);
6799 /* check the required size. */
6800 for (i=0; i<numbuiltinforms; i++) {
6801 DEBUGADD(6,("adding form [%d]'s size\n",i));
6802 buffer_size += spoolss_size_form_1(&forms_1[i]);
6804 for (; i<*numofforms; i++) {
6805 DEBUGADD(6,("adding form [%d]'s size\n",i));
6806 buffer_size += spoolss_size_form_1(&forms_1[i]);
6809 *needed=buffer_size;
6811 if (!alloc_buffer_size(buffer, buffer_size)){
6812 SAFE_FREE(forms_1);
6813 return WERR_INSUFFICIENT_BUFFER;
6816 /* fill the buffer with the form structures */
6817 for (i=0; i<numbuiltinforms; i++) {
6818 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6819 smb_io_form_1("", buffer, &forms_1[i], 0);
6821 for (; i<*numofforms; i++) {
6822 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6823 smb_io_form_1("", buffer, &forms_1[i], 0);
6826 SAFE_FREE(forms_1);
6828 if (*needed > offered) {
6829 *numofforms=0;
6830 return WERR_INSUFFICIENT_BUFFER;
6832 else
6833 return WERR_OK;
6835 default:
6836 SAFE_FREE(list);
6837 SAFE_FREE(builtinlist);
6838 return WERR_UNKNOWN_LEVEL;
6843 /****************************************************************************
6844 ****************************************************************************/
6846 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6848 uint32 level = q_u->level;
6849 UNISTR2 *uni_formname = &q_u->formname;
6850 NEW_BUFFER *buffer = NULL;
6851 uint32 offered = q_u->offered;
6852 uint32 *needed = &r_u->needed;
6854 nt_forms_struct *list=NULL;
6855 nt_forms_struct builtin_form;
6856 BOOL foundBuiltin;
6857 FORM_1 form_1;
6858 fstring form_name;
6859 int buffer_size=0;
6860 int numofforms=0, i=0;
6862 /* that's an [in out] buffer */
6863 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6864 buffer = r_u->buffer;
6866 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
6868 DEBUG(4,("_spoolss_getform\n"));
6869 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6870 DEBUGADD(5,("Info level [%d]\n", level));
6872 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
6873 if (!foundBuiltin) {
6874 numofforms = get_ntforms(&list);
6875 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
6877 if (numofforms == 0)
6878 return WERR_BADFID;
6881 switch (level) {
6882 case 1:
6883 if (foundBuiltin) {
6884 fill_form_1(&form_1, &builtin_form);
6885 } else {
6887 /* Check if the requested name is in the list of form structures */
6888 for (i=0; i<numofforms; i++) {
6890 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
6892 if (strequal(form_name, list[i].name)) {
6893 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
6894 fill_form_1(&form_1, &list[i]);
6895 break;
6899 SAFE_FREE(list);
6900 if (i == numofforms) {
6901 return WERR_BADFID;
6904 /* check the required size. */
6906 *needed=spoolss_size_form_1(&form_1);
6908 if (!alloc_buffer_size(buffer, buffer_size)){
6909 return WERR_INSUFFICIENT_BUFFER;
6912 if (*needed > offered) {
6913 return WERR_INSUFFICIENT_BUFFER;
6916 /* fill the buffer with the form structures */
6917 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
6918 smb_io_form_1("", buffer, &form_1, 0);
6920 return WERR_OK;
6922 default:
6923 SAFE_FREE(list);
6924 return WERR_UNKNOWN_LEVEL;
6928 /****************************************************************************
6929 ****************************************************************************/
6931 static void fill_port_1(PORT_INFO_1 *port, const char *name)
6933 init_unistr(&port->port_name, name);
6936 /****************************************************************************
6937 ****************************************************************************/
6939 static void fill_port_2(PORT_INFO_2 *port, const char *name)
6941 init_unistr(&port->port_name, name);
6942 init_unistr(&port->monitor_name, "Local Monitor");
6943 init_unistr(&port->description, "Local Port");
6944 #define PORT_TYPE_WRITE 1
6945 port->port_type=PORT_TYPE_WRITE;
6946 port->reserved=0x0;
6949 /****************************************************************************
6950 enumports level 1.
6951 ****************************************************************************/
6953 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6955 PORT_INFO_1 *ports=NULL;
6956 int i=0;
6958 if (*lp_enumports_cmd()) {
6959 char *cmd = lp_enumports_cmd();
6960 char **qlines;
6961 pstring command;
6962 int numlines;
6963 int ret;
6964 int fd;
6966 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
6968 DEBUG(10,("Running [%s]\n", command));
6969 ret = smbrun(command, &fd);
6970 DEBUG(10,("Returned [%d]\n", ret));
6971 if (ret != 0) {
6972 if (fd != -1)
6973 close(fd);
6974 /* Is this the best error to return here? */
6975 return WERR_ACCESS_DENIED;
6978 numlines = 0;
6979 qlines = fd_lines_load(fd, &numlines);
6980 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6981 close(fd);
6983 if(numlines) {
6984 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
6985 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6986 dos_errstr(WERR_NOMEM)));
6987 file_lines_free(qlines);
6988 return WERR_NOMEM;
6991 for (i=0; i<numlines; i++) {
6992 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6993 fill_port_1(&ports[i], qlines[i]);
6996 file_lines_free(qlines);
6999 *returned = numlines;
7001 } else {
7002 *returned = 1; /* Sole Samba port returned. */
7004 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7005 return WERR_NOMEM;
7007 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7009 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7012 /* check the required size. */
7013 for (i=0; i<*returned; i++) {
7014 DEBUGADD(6,("adding port [%d]'s size\n", i));
7015 *needed += spoolss_size_port_info_1(&ports[i]);
7018 if (!alloc_buffer_size(buffer, *needed)) {
7019 SAFE_FREE(ports);
7020 return WERR_INSUFFICIENT_BUFFER;
7023 /* fill the buffer with the ports structures */
7024 for (i=0; i<*returned; i++) {
7025 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7026 smb_io_port_1("", buffer, &ports[i], 0);
7029 SAFE_FREE(ports);
7031 if (*needed > offered) {
7032 *returned=0;
7033 return WERR_INSUFFICIENT_BUFFER;
7036 return WERR_OK;
7039 /****************************************************************************
7040 enumports level 2.
7041 ****************************************************************************/
7043 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7045 PORT_INFO_2 *ports=NULL;
7046 int i=0;
7048 if (*lp_enumports_cmd()) {
7049 char *cmd = lp_enumports_cmd();
7050 char *path;
7051 char **qlines;
7052 pstring tmp_file;
7053 pstring command;
7054 int numlines;
7055 int ret;
7056 int fd;
7058 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7059 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7060 else
7061 path = lp_lockdir();
7063 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7064 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7066 unlink(tmp_file);
7067 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7068 ret = smbrun(command, &fd);
7069 DEBUGADD(10,("returned [%d]\n", ret));
7070 if (ret != 0) {
7071 if (fd != -1)
7072 close(fd);
7073 /* Is this the best error to return here? */
7074 return WERR_ACCESS_DENIED;
7077 numlines = 0;
7078 qlines = fd_lines_load(fd, &numlines);
7079 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7080 close(fd);
7082 if(numlines) {
7083 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7084 file_lines_free(qlines);
7085 return WERR_NOMEM;
7088 for (i=0; i<numlines; i++) {
7089 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7090 fill_port_2(&(ports[i]), qlines[i]);
7093 file_lines_free(qlines);
7096 *returned = numlines;
7098 } else {
7100 *returned = 1;
7102 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7103 return WERR_NOMEM;
7105 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7107 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7110 /* check the required size. */
7111 for (i=0; i<*returned; i++) {
7112 DEBUGADD(6,("adding port [%d]'s size\n", i));
7113 *needed += spoolss_size_port_info_2(&ports[i]);
7116 if (!alloc_buffer_size(buffer, *needed)) {
7117 SAFE_FREE(ports);
7118 return WERR_INSUFFICIENT_BUFFER;
7121 /* fill the buffer with the ports structures */
7122 for (i=0; i<*returned; i++) {
7123 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7124 smb_io_port_2("", buffer, &ports[i], 0);
7127 SAFE_FREE(ports);
7129 if (*needed > offered) {
7130 *returned=0;
7131 return WERR_INSUFFICIENT_BUFFER;
7134 return WERR_OK;
7137 /****************************************************************************
7138 enumports.
7139 ****************************************************************************/
7141 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7143 uint32 level = q_u->level;
7144 NEW_BUFFER *buffer = NULL;
7145 uint32 offered = q_u->offered;
7146 uint32 *needed = &r_u->needed;
7147 uint32 *returned = &r_u->returned;
7149 /* that's an [in out] buffer */
7150 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7151 buffer = r_u->buffer;
7153 DEBUG(4,("_spoolss_enumports\n"));
7155 *returned=0;
7156 *needed=0;
7158 switch (level) {
7159 case 1:
7160 return enumports_level_1(buffer, offered, needed, returned);
7161 case 2:
7162 return enumports_level_2(buffer, offered, needed, returned);
7163 default:
7164 return WERR_UNKNOWN_LEVEL;
7168 /****************************************************************************
7169 ****************************************************************************/
7171 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7172 const SPOOL_PRINTER_INFO_LEVEL *info,
7173 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7174 uint32 user_switch, const SPOOL_USER_CTR *user,
7175 POLICY_HND *handle)
7177 NT_PRINTER_INFO_LEVEL *printer = NULL;
7178 fstring name;
7179 int snum;
7180 WERROR err = WERR_OK;
7182 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7183 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7184 return WERR_NOMEM;
7187 ZERO_STRUCTP(printer);
7189 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7190 if (!convert_printer_info(info, printer, 2)) {
7191 free_a_printer(&printer, 2);
7192 return WERR_NOMEM;
7195 /* check to see if the printer already exists */
7197 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7198 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7199 printer->info_2->sharename));
7200 free_a_printer(&printer, 2);
7201 return WERR_PRINTER_ALREADY_EXISTS;
7204 if (*lp_addprinter_cmd() ) {
7205 if ( !add_printer_hook(printer) ) {
7206 free_a_printer(&printer,2);
7207 return WERR_ACCESS_DENIED;
7211 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7212 printer->info_2->sharename);
7215 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7216 free_a_printer(&printer,2);
7217 return WERR_ACCESS_DENIED;
7220 /* you must be a printer admin to add a new printer */
7221 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7222 free_a_printer(&printer,2);
7223 return WERR_ACCESS_DENIED;
7227 * Do sanity check on the requested changes for Samba.
7230 if (!check_printer_ok(printer->info_2, snum)) {
7231 free_a_printer(&printer,2);
7232 return WERR_INVALID_PARAM;
7236 * When a printer is created, the drivername bound to the printer is used
7237 * to lookup previously saved driver initialization info, which is then
7238 * bound to the new printer, simulating what happens in the Windows arch.
7241 if (!devmode)
7243 set_driver_init(printer, 2);
7245 else
7247 /* A valid devmode was included, convert and link it
7249 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7251 if (!convert_devicemode(printer->info_2->printername, devmode,
7252 &printer->info_2->devmode))
7253 return WERR_NOMEM;
7256 /* write the ASCII on disk */
7257 err = mod_a_printer(*printer, 2);
7258 if (!W_ERROR_IS_OK(err)) {
7259 free_a_printer(&printer,2);
7260 return err;
7263 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7264 /* Handle open failed - remove addition. */
7265 del_a_printer(printer->info_2->sharename);
7266 free_a_printer(&printer,2);
7267 return WERR_ACCESS_DENIED;
7270 update_c_setprinter(False);
7271 free_a_printer(&printer,2);
7273 return WERR_OK;
7276 /****************************************************************************
7277 ****************************************************************************/
7279 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7281 UNISTR2 *uni_srv_name = &q_u->server_name;
7282 uint32 level = q_u->level;
7283 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7284 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7285 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7286 uint32 user_switch = q_u->user_switch;
7287 SPOOL_USER_CTR *user = &q_u->user_ctr;
7288 POLICY_HND *handle = &r_u->handle;
7290 switch (level) {
7291 case 1:
7292 /* we don't handle yet */
7293 /* but I know what to do ... */
7294 return WERR_UNKNOWN_LEVEL;
7295 case 2:
7296 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7297 devmode, sdb,
7298 user_switch, user, handle);
7299 default:
7300 return WERR_UNKNOWN_LEVEL;
7304 /****************************************************************************
7305 ****************************************************************************/
7307 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7309 uint32 level = q_u->level;
7310 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7311 WERROR err = WERR_OK;
7312 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7313 struct current_user user;
7314 fstring driver_name;
7315 uint32 version;
7317 ZERO_STRUCT(driver);
7319 get_current_user(&user, p);
7321 if (!convert_printer_driver_info(info, &driver, level)) {
7322 err = WERR_NOMEM;
7323 goto done;
7326 DEBUG(5,("Cleaning driver's information\n"));
7327 err = clean_up_driver_struct(driver, level, &user);
7328 if (!W_ERROR_IS_OK(err))
7329 goto done;
7331 DEBUG(5,("Moving driver to final destination\n"));
7332 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7333 if (W_ERROR_IS_OK(err))
7334 err = WERR_ACCESS_DENIED;
7335 goto done;
7338 if (add_a_printer_driver(driver, level)!=0) {
7339 err = WERR_ACCESS_DENIED;
7340 goto done;
7343 /* BEGIN_ADMIN_LOG */
7344 switch(level) {
7345 case 3:
7346 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7347 driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
7348 fstrcpy(driver_name, driver.info_3->name);
7349 break;
7350 case 6:
7351 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7352 driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
7353 fstrcpy(driver_name, driver.info_6->name);
7354 break;
7356 /* END_ADMIN_LOG */
7359 * I think this is where he DrvUpgradePrinter() hook would be
7360 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7361 * server. Right now, we just need to send ourselves a message
7362 * to update each printer bound to this driver. --jerry
7365 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7366 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7367 driver_name));
7371 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7372 * decide if the driver init data should be deleted. The rules are:
7373 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7374 * 2) delete init data only if there is no 2k/Xp driver
7375 * 3) always delete init data
7376 * The generalized rule is always use init data from the highest order driver.
7377 * It is necessary to follow the driver install by an initialization step to
7378 * finish off this process.
7380 if (level == 3)
7381 version = driver.info_3->cversion;
7382 else if (level == 6)
7383 version = driver.info_6->version;
7384 else
7385 version = -1;
7386 switch (version) {
7388 * 9x printer driver - never delete init data
7390 case 0:
7391 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7392 driver_name));
7393 break;
7396 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7397 * there is no 2k/Xp driver init data for this driver name.
7399 case 2:
7401 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7403 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7405 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7407 if (!del_driver_init(driver_name))
7408 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7409 } else {
7411 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7413 free_a_printer_driver(driver1,3);
7414 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7415 driver_name));
7418 break;
7421 * 2k or Xp printer driver - always delete init data
7423 case 3:
7424 if (!del_driver_init(driver_name))
7425 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7426 break;
7428 default:
7429 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7430 break;
7434 done:
7435 free_a_printer_driver(driver, level);
7436 return err;
7439 /********************************************************************
7440 * spoolss_addprinterdriverex
7441 ********************************************************************/
7443 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7445 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7446 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7449 * we only support the semantics of AddPrinterDriver()
7450 * i.e. only copy files that are newer than existing ones
7453 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7454 return WERR_ACCESS_DENIED;
7456 ZERO_STRUCT(q_u_local);
7457 ZERO_STRUCT(r_u_local);
7459 /* just pass the information off to _spoolss_addprinterdriver() */
7460 q_u_local.server_name_ptr = q_u->server_name_ptr;
7461 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7462 q_u_local.level = q_u->level;
7463 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7465 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7468 /****************************************************************************
7469 ****************************************************************************/
7471 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7473 init_unistr(&info->name, name);
7476 /****************************************************************************
7477 ****************************************************************************/
7479 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7481 pstring path;
7482 pstring long_archi;
7483 pstring short_archi;
7484 DRIVER_DIRECTORY_1 *info=NULL;
7486 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7488 if (get_short_archi(short_archi, long_archi)==False)
7489 return WERR_INVALID_ENVIRONMENT;
7491 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7492 return WERR_NOMEM;
7494 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7496 DEBUG(4,("printer driver directory: [%s]\n", path));
7498 fill_driverdir_1(info, path);
7500 *needed += spoolss_size_driverdir_info_1(info);
7502 if (!alloc_buffer_size(buffer, *needed)) {
7503 SAFE_FREE(info);
7504 return WERR_INSUFFICIENT_BUFFER;
7507 smb_io_driverdir_1("", buffer, info, 0);
7509 SAFE_FREE(info);
7511 if (*needed > offered)
7512 return WERR_INSUFFICIENT_BUFFER;
7514 return WERR_OK;
7517 /****************************************************************************
7518 ****************************************************************************/
7520 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7522 UNISTR2 *name = &q_u->name;
7523 UNISTR2 *uni_environment = &q_u->environment;
7524 uint32 level = q_u->level;
7525 NEW_BUFFER *buffer = NULL;
7526 uint32 offered = q_u->offered;
7527 uint32 *needed = &r_u->needed;
7529 /* that's an [in out] buffer */
7530 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7531 buffer = r_u->buffer;
7533 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7535 *needed=0;
7537 switch(level) {
7538 case 1:
7539 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7540 default:
7541 return WERR_UNKNOWN_LEVEL;
7545 /****************************************************************************
7546 ****************************************************************************/
7548 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7550 POLICY_HND *handle = &q_u->handle;
7551 uint32 idx = q_u->index;
7552 uint32 in_value_len = q_u->valuesize;
7553 uint32 in_data_len = q_u->datasize;
7554 uint32 *out_max_value_len = &r_u->valuesize;
7555 uint16 **out_value = &r_u->value;
7556 uint32 *out_value_len = &r_u->realvaluesize;
7557 uint32 *out_type = &r_u->type;
7558 uint32 *out_max_data_len = &r_u->datasize;
7559 uint8 **data_out = &r_u->data;
7560 uint32 *out_data_len = &r_u->realdatasize;
7562 NT_PRINTER_INFO_LEVEL *printer = NULL;
7564 uint32 param_index;
7565 uint32 biggest_valuesize;
7566 uint32 biggest_datasize;
7567 uint32 data_len;
7568 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7569 int snum;
7570 WERROR result;
7571 REGISTRY_VALUE *val;
7572 NT_PRINTER_DATA *p_data;
7573 int i, key_index, num_values;
7574 int name_length;
7576 ZERO_STRUCT( printer );
7578 *out_type = 0;
7580 *out_max_data_len = 0;
7581 *data_out = NULL;
7582 *out_data_len = 0;
7584 DEBUG(5,("spoolss_enumprinterdata\n"));
7586 if (!Printer) {
7587 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7588 return WERR_BADFID;
7591 if (!get_printer_snum(p,handle, &snum))
7592 return WERR_BADFID;
7594 result = get_a_printer(&printer, 2, lp_servicename(snum));
7595 if (!W_ERROR_IS_OK(result))
7596 return result;
7598 p_data = &printer->info_2->data;
7599 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7601 result = WERR_OK;
7604 * The NT machine wants to know the biggest size of value and data
7606 * cf: MSDN EnumPrinterData remark section
7609 if ( !in_value_len && !in_data_len )
7611 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7613 param_index = 0;
7614 biggest_valuesize = 0;
7615 biggest_datasize = 0;
7617 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7619 for ( i=0; i<num_values; i++ )
7621 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7623 name_length = strlen(val->valuename);
7624 if ( strlen(val->valuename) > biggest_valuesize )
7625 biggest_valuesize = name_length;
7627 if ( val->size > biggest_datasize )
7628 biggest_datasize = val->size;
7630 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7631 biggest_datasize));
7634 /* the value is an UNICODE string but real_value_size is the length
7635 in bytes including the trailing 0 */
7637 *out_value_len = 2 * (1+biggest_valuesize);
7638 *out_data_len = biggest_datasize;
7640 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7642 goto done;
7646 * the value len is wrong in NT sp3
7647 * that's the number of bytes not the number of unicode chars
7650 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7652 if ( !val )
7655 /* out_value should default to "" or else NT4 has
7656 problems unmarshalling the response */
7658 *out_max_value_len = (in_value_len/sizeof(uint16));
7660 if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7662 result = WERR_NOMEM;
7663 goto done;
7666 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7668 /* the data is counted in bytes */
7670 *out_max_data_len = in_data_len;
7671 *out_data_len = in_data_len;
7673 /* only allocate when given a non-zero data_len */
7675 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7677 result = WERR_NOMEM;
7678 goto done;
7681 result = WERR_NO_MORE_ITEMS;
7683 else
7686 * the value is:
7687 * - counted in bytes in the request
7688 * - counted in UNICODE chars in the max reply
7689 * - counted in bytes in the real size
7691 * take a pause *before* coding not *during* coding
7694 /* name */
7695 *out_max_value_len = ( in_value_len / sizeof(uint16) );
7696 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7698 result = WERR_NOMEM;
7699 goto done;
7702 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7704 /* type */
7706 *out_type = regval_type( val );
7708 /* data - counted in bytes */
7710 *out_max_data_len = in_data_len;
7711 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7713 result = WERR_NOMEM;
7714 goto done;
7716 data_len = (size_t)regval_size(val);
7717 memcpy( *data_out, regval_data_p(val), data_len );
7718 *out_data_len = data_len;
7721 done:
7722 free_a_printer(&printer, 2);
7723 return result;
7726 /****************************************************************************
7727 ****************************************************************************/
7729 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7731 POLICY_HND *handle = &q_u->handle;
7732 UNISTR2 *value = &q_u->value;
7733 uint32 type = q_u->type;
7734 uint8 *data = q_u->data;
7735 uint32 real_len = q_u->real_len;
7737 NT_PRINTER_INFO_LEVEL *printer = NULL;
7738 int snum=0;
7739 WERROR status = WERR_OK;
7740 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7741 fstring valuename;
7743 DEBUG(5,("spoolss_setprinterdata\n"));
7745 if (!Printer) {
7746 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7747 return WERR_BADFID;
7750 if (!get_printer_snum(p,handle, &snum))
7751 return WERR_BADFID;
7754 * Access check : NT returns "access denied" if you make a
7755 * SetPrinterData call without the necessary privildge.
7756 * we were originally returning OK if nothing changed
7757 * which made Win2k issue **a lot** of SetPrinterData
7758 * when connecting to a printer --jerry
7761 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7763 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7764 status = WERR_ACCESS_DENIED;
7765 goto done;
7768 status = get_a_printer(&printer, 2, lp_servicename(snum));
7769 if (!W_ERROR_IS_OK(status))
7770 return status;
7772 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7775 * When client side code sets a magic printer data key, detect it and save
7776 * the current printer data and the magic key's data (its the DEVMODE) for
7777 * future printer/driver initializations.
7779 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7781 /* Set devmode and printer initialization info */
7782 status = save_driver_init( printer, 2, data, real_len );
7784 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7786 else
7788 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7789 type, data, real_len );
7790 if ( W_ERROR_IS_OK(status) )
7791 status = mod_a_printer(*printer, 2);
7794 done:
7795 free_a_printer(&printer, 2);
7797 return status;
7800 /****************************************************************************
7801 ****************************************************************************/
7803 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7805 POLICY_HND *handle = &q_u->handle;
7806 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7807 int snum;
7809 DEBUG(5,("_spoolss_resetprinter\n"));
7812 * All we do is to check to see if the handle and queue is valid.
7813 * This call really doesn't mean anything to us because we only
7814 * support RAW printing. --jerry
7817 if (!Printer) {
7818 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7819 return WERR_BADFID;
7822 if (!get_printer_snum(p,handle, &snum))
7823 return WERR_BADFID;
7826 /* blindly return success */
7827 return WERR_OK;
7831 /****************************************************************************
7832 ****************************************************************************/
7834 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7836 POLICY_HND *handle = &q_u->handle;
7837 UNISTR2 *value = &q_u->valuename;
7839 NT_PRINTER_INFO_LEVEL *printer = NULL;
7840 int snum=0;
7841 WERROR status = WERR_OK;
7842 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7843 pstring valuename;
7845 DEBUG(5,("spoolss_deleteprinterdata\n"));
7847 if (!Printer) {
7848 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7849 return WERR_BADFID;
7852 if (!get_printer_snum(p, handle, &snum))
7853 return WERR_BADFID;
7855 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7856 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7857 return WERR_ACCESS_DENIED;
7860 status = get_a_printer(&printer, 2, lp_servicename(snum));
7861 if (!W_ERROR_IS_OK(status))
7862 return status;
7864 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7866 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
7868 free_a_printer(&printer, 2);
7870 return status;
7873 /****************************************************************************
7874 ****************************************************************************/
7876 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
7878 POLICY_HND *handle = &q_u->handle;
7879 FORM *form = &q_u->form;
7880 nt_forms_struct tmpForm;
7881 int snum;
7882 WERROR status = WERR_OK;
7883 NT_PRINTER_INFO_LEVEL *printer = NULL;
7885 int count=0;
7886 nt_forms_struct *list=NULL;
7887 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7889 DEBUG(5,("spoolss_addform\n"));
7891 if (!Printer) {
7892 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7893 return WERR_BADFID;
7897 /* forms can be added on printer of on the print server handle */
7899 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7901 if (!get_printer_snum(p,handle, &snum))
7902 return WERR_BADFID;
7904 status = get_a_printer(&printer, 2, lp_servicename(snum));
7905 if (!W_ERROR_IS_OK(status))
7906 goto done;
7909 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7910 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7911 status = WERR_ACCESS_DENIED;
7912 goto done;
7915 /* can't add if builtin */
7917 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
7918 status = WERR_ALREADY_EXISTS;
7919 goto done;
7922 count = get_ntforms(&list);
7924 if(!add_a_form(&list, form, &count)) {
7925 status = WERR_NOMEM;
7926 goto done;
7929 write_ntforms(&list, count);
7932 * ChangeID must always be set if this is a printer
7935 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7936 status = mod_a_printer(*printer, 2);
7938 done:
7939 if ( printer )
7940 free_a_printer(&printer, 2);
7941 SAFE_FREE(list);
7943 return status;
7946 /****************************************************************************
7947 ****************************************************************************/
7949 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
7951 POLICY_HND *handle = &q_u->handle;
7952 UNISTR2 *form_name = &q_u->name;
7953 nt_forms_struct tmpForm;
7954 int count=0;
7955 nt_forms_struct *list=NULL;
7956 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7957 int snum;
7958 WERROR status = WERR_OK;
7959 NT_PRINTER_INFO_LEVEL *printer = NULL;
7961 DEBUG(5,("spoolss_deleteform\n"));
7963 if (!Printer) {
7964 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7965 return WERR_BADFID;
7968 /* forms can be deleted on printer of on the print server handle */
7970 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
7972 if (!get_printer_snum(p,handle, &snum))
7973 return WERR_BADFID;
7975 status = get_a_printer(&printer, 2, lp_servicename(snum));
7976 if (!W_ERROR_IS_OK(status))
7977 goto done;
7980 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7981 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7982 status = WERR_ACCESS_DENIED;
7983 goto done;
7986 /* can't delete if builtin */
7988 if (get_a_builtin_ntform(form_name,&tmpForm)) {
7989 status = WERR_INVALID_PARAM;
7990 goto done;
7993 count = get_ntforms(&list);
7995 if ( !delete_a_form(&list, form_name, &count, &status ))
7996 goto done;
7999 * ChangeID must always be set if this is a printer
8002 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8003 status = mod_a_printer(*printer, 2);
8005 done:
8006 if ( printer )
8007 free_a_printer(&printer, 2);
8008 SAFE_FREE(list);
8010 return status;
8013 /****************************************************************************
8014 ****************************************************************************/
8016 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8018 POLICY_HND *handle = &q_u->handle;
8019 FORM *form = &q_u->form;
8020 nt_forms_struct tmpForm;
8021 int snum;
8022 WERROR status = WERR_OK;
8023 NT_PRINTER_INFO_LEVEL *printer = NULL;
8025 int count=0;
8026 nt_forms_struct *list=NULL;
8027 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8029 DEBUG(5,("spoolss_setform\n"));
8031 if (!Printer) {
8032 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8033 return WERR_BADFID;
8036 /* forms can be modified on printer of on the print server handle */
8038 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8040 if (!get_printer_snum(p,handle, &snum))
8041 return WERR_BADFID;
8043 status = get_a_printer(&printer, 2, lp_servicename(snum));
8044 if (!W_ERROR_IS_OK(status))
8045 goto done;
8048 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8049 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8050 status = WERR_ACCESS_DENIED;
8051 goto done;
8054 /* can't set if builtin */
8055 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8056 status = WERR_INVALID_PARAM;
8057 goto done;
8060 count = get_ntforms(&list);
8061 update_a_form(&list, form, count);
8062 write_ntforms(&list, count);
8065 * ChangeID must always be set if this is a printer
8068 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8069 status = mod_a_printer(*printer, 2);
8072 done:
8073 if ( printer )
8074 free_a_printer(&printer, 2);
8075 SAFE_FREE(list);
8077 return status;
8080 /****************************************************************************
8081 enumprintprocessors level 1.
8082 ****************************************************************************/
8084 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8086 PRINTPROCESSOR_1 *info_1=NULL;
8088 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8089 return WERR_NOMEM;
8091 (*returned) = 0x1;
8093 init_unistr(&info_1->name, "winprint");
8095 *needed += spoolss_size_printprocessor_info_1(info_1);
8097 if (!alloc_buffer_size(buffer, *needed))
8098 return WERR_INSUFFICIENT_BUFFER;
8100 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8102 SAFE_FREE(info_1);
8104 if (*needed > offered) {
8105 *returned=0;
8106 return WERR_INSUFFICIENT_BUFFER;
8109 return WERR_OK;
8112 /****************************************************************************
8113 ****************************************************************************/
8115 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8117 uint32 level = q_u->level;
8118 NEW_BUFFER *buffer = NULL;
8119 uint32 offered = q_u->offered;
8120 uint32 *needed = &r_u->needed;
8121 uint32 *returned = &r_u->returned;
8123 /* that's an [in out] buffer */
8124 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8125 buffer = r_u->buffer;
8127 DEBUG(5,("spoolss_enumprintprocessors\n"));
8130 * Enumerate the print processors ...
8132 * Just reply with "winprint", to keep NT happy
8133 * and I can use my nice printer checker.
8136 *returned=0;
8137 *needed=0;
8139 switch (level) {
8140 case 1:
8141 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8142 default:
8143 return WERR_UNKNOWN_LEVEL;
8147 /****************************************************************************
8148 enumprintprocdatatypes level 1.
8149 ****************************************************************************/
8151 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8153 PRINTPROCDATATYPE_1 *info_1=NULL;
8155 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8156 return WERR_NOMEM;
8158 (*returned) = 0x1;
8160 init_unistr(&info_1->name, "RAW");
8162 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8164 if (!alloc_buffer_size(buffer, *needed))
8165 return WERR_INSUFFICIENT_BUFFER;
8167 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8169 SAFE_FREE(info_1);
8171 if (*needed > offered) {
8172 *returned=0;
8173 return WERR_INSUFFICIENT_BUFFER;
8176 return WERR_OK;
8179 /****************************************************************************
8180 ****************************************************************************/
8182 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8184 uint32 level = q_u->level;
8185 NEW_BUFFER *buffer = NULL;
8186 uint32 offered = q_u->offered;
8187 uint32 *needed = &r_u->needed;
8188 uint32 *returned = &r_u->returned;
8190 /* that's an [in out] buffer */
8191 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8192 buffer = r_u->buffer;
8194 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8196 *returned=0;
8197 *needed=0;
8199 switch (level) {
8200 case 1:
8201 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8202 default:
8203 return WERR_UNKNOWN_LEVEL;
8207 /****************************************************************************
8208 enumprintmonitors level 1.
8209 ****************************************************************************/
8211 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8213 PRINTMONITOR_1 *info_1=NULL;
8215 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8216 return WERR_NOMEM;
8218 (*returned) = 0x1;
8220 init_unistr(&info_1->name, "Local Port");
8222 *needed += spoolss_size_printmonitor_info_1(info_1);
8224 if (!alloc_buffer_size(buffer, *needed))
8225 return WERR_INSUFFICIENT_BUFFER;
8227 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8229 SAFE_FREE(info_1);
8231 if (*needed > offered) {
8232 *returned=0;
8233 return WERR_INSUFFICIENT_BUFFER;
8236 return WERR_OK;
8239 /****************************************************************************
8240 enumprintmonitors level 2.
8241 ****************************************************************************/
8243 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8245 PRINTMONITOR_2 *info_2=NULL;
8247 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8248 return WERR_NOMEM;
8250 (*returned) = 0x1;
8252 init_unistr(&info_2->name, "Local Port");
8253 init_unistr(&info_2->environment, "Windows NT X86");
8254 init_unistr(&info_2->dll_name, "localmon.dll");
8256 *needed += spoolss_size_printmonitor_info_2(info_2);
8258 if (!alloc_buffer_size(buffer, *needed))
8259 return WERR_INSUFFICIENT_BUFFER;
8261 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8263 SAFE_FREE(info_2);
8265 if (*needed > offered) {
8266 *returned=0;
8267 return WERR_INSUFFICIENT_BUFFER;
8270 return WERR_OK;
8273 /****************************************************************************
8274 ****************************************************************************/
8276 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8278 uint32 level = q_u->level;
8279 NEW_BUFFER *buffer = NULL;
8280 uint32 offered = q_u->offered;
8281 uint32 *needed = &r_u->needed;
8282 uint32 *returned = &r_u->returned;
8284 /* that's an [in out] buffer */
8285 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8286 buffer = r_u->buffer;
8288 DEBUG(5,("spoolss_enumprintmonitors\n"));
8291 * Enumerate the print monitors ...
8293 * Just reply with "Local Port", to keep NT happy
8294 * and I can use my nice printer checker.
8297 *returned=0;
8298 *needed=0;
8300 switch (level) {
8301 case 1:
8302 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8303 case 2:
8304 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8305 default:
8306 return WERR_UNKNOWN_LEVEL;
8310 /****************************************************************************
8311 ****************************************************************************/
8313 static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8315 int i=0;
8316 BOOL found=False;
8317 JOB_INFO_1 *info_1=NULL;
8319 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8321 if (info_1 == NULL) {
8322 SAFE_FREE(queue);
8323 return WERR_NOMEM;
8326 for (i=0; i<count && found==False; i++) {
8327 if (queue[i].job==(int)jobid)
8328 found=True;
8331 if (found==False) {
8332 SAFE_FREE(queue);
8333 SAFE_FREE(info_1);
8334 /* NT treats not found as bad param... yet another bad choice */
8335 return WERR_INVALID_PARAM;
8338 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
8340 *needed += spoolss_size_job_info_1(info_1);
8342 if (!alloc_buffer_size(buffer, *needed)) {
8343 SAFE_FREE(info_1);
8344 return WERR_INSUFFICIENT_BUFFER;
8347 smb_io_job_info_1("", buffer, info_1, 0);
8349 SAFE_FREE(info_1);
8351 if (*needed > offered)
8352 return WERR_INSUFFICIENT_BUFFER;
8354 return WERR_OK;
8357 /****************************************************************************
8358 ****************************************************************************/
8360 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8362 int i = 0;
8363 BOOL found = False;
8364 JOB_INFO_2 *info_2;
8365 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8366 WERROR ret;
8367 DEVICEMODE *devmode = NULL;
8368 NT_DEVICEMODE *nt_devmode = NULL;
8370 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8372 ZERO_STRUCTP(info_2);
8374 if (info_2 == NULL) {
8375 ret = WERR_NOMEM;
8376 goto done;
8379 for ( i=0; i<count && found==False; i++ )
8381 if (queue[i].job == (int)jobid)
8382 found = True;
8385 if ( !found )
8387 /* NT treats not found as bad param... yet another bad
8388 choice */
8389 ret = WERR_INVALID_PARAM;
8390 goto done;
8393 ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
8394 if (!W_ERROR_IS_OK(ret))
8395 goto done;
8398 * if the print job does not have a DEVMODE associated with it,
8399 * just use the one for the printer. A NULL devicemode is not
8400 * a failure condition
8403 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8404 devmode = construct_dev_mode(snum);
8405 else {
8406 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8407 ZERO_STRUCTP( devmode );
8408 convert_nt_devicemode( devmode, nt_devmode );
8412 fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
8414 *needed += spoolss_size_job_info_2(info_2);
8416 if (!alloc_buffer_size(buffer, *needed)) {
8417 ret = WERR_INSUFFICIENT_BUFFER;
8418 goto done;
8421 smb_io_job_info_2("", buffer, info_2, 0);
8423 if (*needed > offered) {
8424 ret = WERR_INSUFFICIENT_BUFFER;
8425 goto done;
8428 ret = WERR_OK;
8430 done:
8431 /* Cleanup allocated memory */
8433 free_job_info_2(info_2); /* Also frees devmode */
8434 SAFE_FREE(info_2);
8435 free_a_printer(&ntprinter, 2);
8437 return ret;
8440 /****************************************************************************
8441 ****************************************************************************/
8443 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8445 POLICY_HND *handle = &q_u->handle;
8446 uint32 jobid = q_u->jobid;
8447 uint32 level = q_u->level;
8448 NEW_BUFFER *buffer = NULL;
8449 uint32 offered = q_u->offered;
8450 uint32 *needed = &r_u->needed;
8451 WERROR wstatus = WERR_OK;
8453 int snum;
8454 int count;
8455 print_queue_struct *queue = NULL;
8456 print_status_struct prt_status;
8458 /* that's an [in out] buffer */
8459 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8460 buffer = r_u->buffer;
8462 DEBUG(5,("spoolss_getjob\n"));
8464 *needed = 0;
8466 if (!get_printer_snum(p, handle, &snum))
8467 return WERR_BADFID;
8469 count = print_queue_status(snum, &queue, &prt_status);
8471 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8472 count, prt_status.status, prt_status.message));
8474 switch ( level ) {
8475 case 1:
8476 wstatus = getjob_level_1(queue, count, snum, jobid,
8477 buffer, offered, needed);
8478 break;
8479 case 2:
8480 wstatus = getjob_level_2(queue, count, snum, jobid,
8481 buffer, offered, needed);
8482 break;
8483 default:
8484 wstatus = WERR_UNKNOWN_LEVEL;
8485 break;
8488 SAFE_FREE(queue);
8489 return wstatus;
8492 /********************************************************************
8493 spoolss_getprinterdataex
8495 From MSDN documentation of GetPrinterDataEx: pass request
8496 to GetPrinterData if key is "PrinterDriverData".
8497 ********************************************************************/
8499 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8501 POLICY_HND *handle = &q_u->handle;
8502 uint32 in_size = q_u->size;
8503 uint32 *type = &r_u->type;
8504 uint32 *out_size = &r_u->size;
8505 uint8 **data = &r_u->data;
8506 uint32 *needed = &r_u->needed;
8507 fstring keyname, valuename;
8509 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8511 NT_PRINTER_INFO_LEVEL *printer = NULL;
8512 int snum = 0;
8513 WERROR status = WERR_OK;
8515 DEBUG(4,("_spoolss_getprinterdataex\n"));
8517 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8518 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8520 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8521 keyname, valuename));
8523 /* in case of problem, return some default values */
8525 *needed = 0;
8526 *type = 0;
8527 *out_size = in_size;
8529 if (!Printer) {
8530 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8531 status = WERR_BADFID;
8532 goto done;
8535 /* Is the handle to a printer or to the server? */
8537 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8538 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
8539 status = WERR_INVALID_PARAM;
8540 goto done;
8543 if ( !get_printer_snum(p,handle, &snum) )
8544 return WERR_BADFID;
8546 status = get_a_printer(&printer, 2, lp_servicename(snum));
8547 if ( !W_ERROR_IS_OK(status) )
8548 goto done;
8550 /* check to see if the keyname is valid */
8551 if ( !strlen(keyname) ) {
8552 status = WERR_INVALID_PARAM;
8553 goto done;
8556 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8557 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8558 free_a_printer( &printer, 2 );
8559 status = WERR_BADFILE;
8560 goto done;
8563 /* When given a new keyname, we should just create it */
8565 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8567 if (*needed > *out_size)
8568 status = WERR_MORE_DATA;
8570 done:
8571 if ( !W_ERROR_IS_OK(status) )
8573 DEBUG(5, ("error: allocating %d\n", *out_size));
8575 /* reply this param doesn't exist */
8577 if ( *out_size )
8579 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8580 status = WERR_NOMEM;
8581 goto done;
8584 else {
8585 *data = NULL;
8589 if ( printer )
8590 free_a_printer( &printer, 2 );
8592 return status;
8595 /********************************************************************
8596 * spoolss_setprinterdataex
8597 ********************************************************************/
8599 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8601 POLICY_HND *handle = &q_u->handle;
8602 uint32 type = q_u->type;
8603 uint8 *data = q_u->data;
8604 uint32 real_len = q_u->real_len;
8606 NT_PRINTER_INFO_LEVEL *printer = NULL;
8607 int snum = 0;
8608 WERROR status = WERR_OK;
8609 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8610 fstring valuename;
8611 fstring keyname;
8612 char *oid_string;
8614 DEBUG(4,("_spoolss_setprinterdataex\n"));
8616 /* From MSDN documentation of SetPrinterDataEx: pass request to
8617 SetPrinterData if key is "PrinterDriverData" */
8619 if (!Printer) {
8620 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8621 return WERR_BADFID;
8624 if ( !get_printer_snum(p,handle, &snum) )
8625 return WERR_BADFID;
8628 * Access check : NT returns "access denied" if you make a
8629 * SetPrinterData call without the necessary privildge.
8630 * we were originally returning OK if nothing changed
8631 * which made Win2k issue **a lot** of SetPrinterData
8632 * when connecting to a printer --jerry
8635 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8637 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8638 return WERR_ACCESS_DENIED;
8641 status = get_a_printer(&printer, 2, lp_servicename(snum));
8642 if (!W_ERROR_IS_OK(status))
8643 return status;
8645 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8646 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8648 /* check for OID in valuename */
8650 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8652 *oid_string = '\0';
8653 oid_string++;
8656 /* save the registry data */
8658 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8660 /* save the OID if one was specified and the previous set call succeeded */
8662 if ( W_ERROR_IS_OK(status) && oid_string )
8665 fstrcat( keyname, "\\" );
8666 fstrcat( keyname, SPOOL_OID_KEY );
8669 * I'm not checking the status here on purpose. Don't know
8670 * if this is right, but I'm returning the status from the
8671 * previous set_printer_dataex() call. I have no idea if
8672 * this is right. --jerry
8675 set_printer_dataex( printer, keyname, valuename,
8676 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8679 free_a_printer(&printer, 2);
8681 return status;
8685 /********************************************************************
8686 * spoolss_deleteprinterdataex
8687 ********************************************************************/
8689 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8691 POLICY_HND *handle = &q_u->handle;
8692 UNISTR2 *value = &q_u->valuename;
8693 UNISTR2 *key = &q_u->keyname;
8695 NT_PRINTER_INFO_LEVEL *printer = NULL;
8696 int snum=0;
8697 WERROR status = WERR_OK;
8698 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8699 pstring valuename, keyname;
8701 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8703 if (!Printer) {
8704 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8705 return WERR_BADFID;
8708 if (!get_printer_snum(p, handle, &snum))
8709 return WERR_BADFID;
8711 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8712 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8713 return WERR_ACCESS_DENIED;
8716 status = get_a_printer(&printer, 2, lp_servicename(snum));
8717 if (!W_ERROR_IS_OK(status))
8718 return status;
8720 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8721 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8723 status = delete_printer_dataex( printer, keyname, valuename );
8725 free_a_printer(&printer, 2);
8727 return status;
8730 /********************************************************************
8731 * spoolss_enumprinterkey
8732 ********************************************************************/
8735 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8737 fstring key;
8738 fstring *keynames = NULL;
8739 uint16 *enumkeys = NULL;
8740 int num_keys;
8741 int printerkey_len;
8742 POLICY_HND *handle = &q_u->handle;
8743 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8744 NT_PRINTER_DATA *data;
8745 NT_PRINTER_INFO_LEVEL *printer = NULL;
8746 int snum = 0;
8747 WERROR status = WERR_BADFILE;
8750 DEBUG(4,("_spoolss_enumprinterkey\n"));
8752 if (!Printer) {
8753 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8754 return WERR_BADFID;
8757 if ( !get_printer_snum(p,handle, &snum) )
8758 return WERR_BADFID;
8760 status = get_a_printer(&printer, 2, lp_servicename(snum));
8761 if (!W_ERROR_IS_OK(status))
8762 return status;
8764 /* get the list of subkey names */
8766 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8767 data = &printer->info_2->data;
8769 num_keys = get_printer_subkeys( data, key, &keynames );
8771 if ( num_keys == -1 ) {
8772 status = WERR_BADFILE;
8773 goto done;
8776 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8778 r_u->needed = printerkey_len*2;
8780 if ( q_u->size < r_u->needed ) {
8781 status = WERR_MORE_DATA;
8782 goto done;
8785 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8786 status = WERR_NOMEM;
8787 goto done;
8790 status = WERR_OK;
8792 if ( q_u->size < r_u->needed )
8793 status = WERR_MORE_DATA;
8795 done:
8796 free_a_printer( &printer, 2 );
8797 SAFE_FREE( keynames );
8799 return status;
8802 /********************************************************************
8803 * spoolss_deleteprinterkey
8804 ********************************************************************/
8806 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8808 POLICY_HND *handle = &q_u->handle;
8809 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8810 fstring key;
8811 NT_PRINTER_INFO_LEVEL *printer = NULL;
8812 int snum=0;
8813 WERROR status;
8815 DEBUG(5,("spoolss_deleteprinterkey\n"));
8817 if (!Printer) {
8818 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8819 return WERR_BADFID;
8822 /* if keyname == NULL, return error */
8824 if ( !q_u->keyname.buffer )
8825 return WERR_INVALID_PARAM;
8827 if (!get_printer_snum(p, handle, &snum))
8828 return WERR_BADFID;
8830 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8831 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8832 return WERR_ACCESS_DENIED;
8835 status = get_a_printer(&printer, 2, lp_servicename(snum));
8836 if (!W_ERROR_IS_OK(status))
8837 return status;
8839 /* delete the key and all subneys */
8841 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8843 status = delete_all_printer_data( printer->info_2, key );
8845 if ( W_ERROR_IS_OK(status) )
8846 status = mod_a_printer(*printer, 2);
8848 free_a_printer( &printer, 2 );
8850 return status;
8854 /********************************************************************
8855 * spoolss_enumprinterdataex
8856 ********************************************************************/
8858 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
8860 POLICY_HND *handle = &q_u->handle;
8861 uint32 in_size = q_u->size;
8862 uint32 num_entries,
8863 needed;
8864 NT_PRINTER_INFO_LEVEL *printer = NULL;
8865 PRINTER_ENUM_VALUES *enum_values = NULL;
8866 NT_PRINTER_DATA *p_data;
8867 fstring key;
8868 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8869 int snum;
8870 WERROR result;
8871 int key_index;
8872 int i;
8873 REGISTRY_VALUE *val;
8874 char *value_name;
8875 int data_len;
8878 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8880 if (!Printer) {
8881 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
8882 return WERR_BADFID;
8886 * first check for a keyname of NULL or "". Win2k seems to send
8887 * this a lot and we should send back WERR_INVALID_PARAM
8888 * no need to spend time looking up the printer in this case.
8889 * --jerry
8892 unistr2_to_dos(key, &q_u->key, sizeof(key) - 1);
8893 if ( !strlen(key) ) {
8894 result = WERR_INVALID_PARAM;
8895 goto done;
8898 /* get the printer off of disk */
8900 if (!get_printer_snum(p,handle, &snum))
8901 return WERR_BADFID;
8903 ZERO_STRUCT(printer);
8904 result = get_a_printer(&printer, 2, lp_servicename(snum));
8905 if (!W_ERROR_IS_OK(result))
8906 return result;
8908 /* now look for a match on the key name */
8910 p_data = &printer->info_2->data;
8912 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
8913 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
8915 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
8916 result = WERR_INVALID_PARAM;
8917 goto done;
8920 result = WERR_OK;
8921 needed = 0;
8923 /* allocate the memory for the array of pointers -- if necessary */
8925 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
8926 if ( num_entries )
8928 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
8930 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8931 num_entries*sizeof(PRINTER_ENUM_VALUES)));
8932 result = WERR_NOMEM;
8933 goto done;
8936 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
8940 * loop through all params and build the array to pass
8941 * back to the client
8944 for ( i=0; i<num_entries; i++ )
8946 /* lookup the registry value */
8948 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
8949 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
8951 /* copy the data */
8953 value_name = regval_name( val );
8954 init_unistr( &enum_values[i].valuename, value_name );
8955 enum_values[i].value_len = (strlen(value_name)+1) * 2;
8956 enum_values[i].type = regval_type( val );
8958 data_len = regval_size( val );
8959 if ( data_len ) {
8960 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
8962 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8963 data_len ));
8964 result = WERR_NOMEM;
8965 goto done;
8968 enum_values[i].data_len = data_len;
8970 /* keep track of the size of the array in bytes */
8972 needed += spoolss_size_printer_enum_values(&enum_values[i]);
8975 /* housekeeping information in the reply */
8977 r_u->needed = needed;
8978 r_u->returned = num_entries;
8980 if (needed > in_size) {
8981 result = WERR_MORE_DATA;
8982 goto done;
8985 /* copy data into the reply */
8987 r_u->ctr.size = r_u->needed;
8988 r_u->ctr.size_of_array = r_u->returned;
8989 r_u->ctr.values = enum_values;
8993 done:
8994 if ( printer )
8995 free_a_printer(&printer, 2);
8997 return result;
9000 /****************************************************************************
9001 ****************************************************************************/
9003 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9005 init_unistr(&info->name, name);
9008 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9009 UNISTR2 *environment,
9010 NEW_BUFFER *buffer,
9011 uint32 offered,
9012 uint32 *needed)
9014 pstring path;
9015 pstring long_archi;
9016 pstring short_archi;
9017 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9019 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9021 if (get_short_archi(short_archi, long_archi)==False)
9022 return WERR_INVALID_ENVIRONMENT;
9024 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9025 return WERR_NOMEM;
9027 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9029 fill_printprocessordirectory_1(info, path);
9031 *needed += spoolss_size_printprocessordirectory_info_1(info);
9033 if (!alloc_buffer_size(buffer, *needed)) {
9034 safe_free(info);
9035 return WERR_INSUFFICIENT_BUFFER;
9038 smb_io_printprocessordirectory_1("", buffer, info, 0);
9040 safe_free(info);
9042 if (*needed > offered)
9043 return WERR_INSUFFICIENT_BUFFER;
9044 else
9045 return WERR_OK;
9048 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9050 uint32 level = q_u->level;
9051 NEW_BUFFER *buffer = NULL;
9052 uint32 offered = q_u->offered;
9053 uint32 *needed = &r_u->needed;
9054 WERROR result;
9056 /* that's an [in out] buffer */
9057 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9058 buffer = r_u->buffer;
9060 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9062 *needed=0;
9064 switch(level) {
9065 case 1:
9066 result = getprintprocessordirectory_level_1
9067 (&q_u->name, &q_u->environment, buffer, offered, needed);
9068 break;
9069 default:
9070 result = WERR_UNKNOWN_LEVEL;
9073 return result;
9076 #if 0
9078 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9079 SPOOL_R_REPLYOPENPRINTER *r_u)
9081 DEBUG(5,("_spoolss_replyopenprinter\n"));
9083 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9085 return WERR_OK;
9088 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9089 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9091 DEBUG(5,("_spoolss_replycloseprinter\n"));
9092 return WERR_OK;
9095 #endif