Remove more fstring/pstring bad useage. Go talloc !
[Samba/vl.git] / source / rpc_server / srv_spoolss_nt.c
blobfe7a12940ee331c01f55a91de5a1adb39efc93c7
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-2004,
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 3 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, see <http://www.gnu.org/licenses/>.
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
28 #include "includes.h"
30 extern userdom_struct current_user_info;
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 struct table_node {
43 const char *long_archi;
44 const char *short_archi;
45 int version;
48 static Printer_entry *printers_list;
50 typedef struct _counter_printer_0 {
51 struct _counter_printer_0 *next;
52 struct _counter_printer_0 *prev;
54 int snum;
55 uint32 counter;
56 } counter_printer_0;
58 static counter_printer_0 *counter_list;
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
64 /* in printing/nt_printing.c */
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
68 /* API table for Xcv Monitor functions */
70 struct xcv_api_table {
71 const char *name;
72 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
76 /* translate between internal status numbers and NT status numbers */
77 static int nt_printj_status(int v)
79 switch (v) {
80 case LPQ_QUEUED:
81 return 0;
82 case LPQ_PAUSED:
83 return JOB_STATUS_PAUSED;
84 case LPQ_SPOOLING:
85 return JOB_STATUS_SPOOLING;
86 case LPQ_PRINTING:
87 return JOB_STATUS_PRINTING;
88 case LPQ_ERROR:
89 return JOB_STATUS_ERROR;
90 case LPQ_DELETING:
91 return JOB_STATUS_DELETING;
92 case LPQ_OFFLINE:
93 return JOB_STATUS_OFFLINE;
94 case LPQ_PAPEROUT:
95 return JOB_STATUS_PAPEROUT;
96 case LPQ_PRINTED:
97 return JOB_STATUS_PRINTED;
98 case LPQ_DELETED:
99 return JOB_STATUS_DELETED;
100 case LPQ_BLOCKED:
101 return JOB_STATUS_BLOCKED;
102 case LPQ_USER_INTERVENTION:
103 return JOB_STATUS_USER_INTERVENTION;
105 return 0;
108 static int nt_printq_status(int v)
110 switch (v) {
111 case LPQ_PAUSED:
112 return PRINTER_STATUS_PAUSED;
113 case LPQ_QUEUED:
114 case LPQ_SPOOLING:
115 case LPQ_PRINTING:
116 return 0;
118 return 0;
121 /****************************************************************************
122 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
123 ****************************************************************************/
125 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
127 if (*pp == NULL)
128 return;
130 SAFE_FREE((*pp)->ctr.type);
131 SAFE_FREE(*pp);
134 /***************************************************************************
135 Disconnect from the client
136 ****************************************************************************/
138 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
140 WERROR result;
143 * Tell the specific printing tdb we no longer want messages for this printer
144 * by deregistering our PID.
147 if (!print_notify_deregister_pid(snum))
148 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
150 /* weird if the test succeds !!! */
151 if (smb_connections==0) {
152 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
153 return;
156 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
158 if (!W_ERROR_IS_OK(result))
159 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
160 dos_errstr(result)));
162 /* if it's the last connection, deconnect the IPC$ share */
163 if (smb_connections==1) {
165 cli_shutdown( notify_cli_pipe->cli );
166 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
168 messaging_deregister(smbd_messaging_context(),
169 MSG_PRINTER_NOTIFY2, NULL);
171 /* Tell the connections db we're no longer interested in
172 * printer notify messages. */
174 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
177 smb_connections--;
180 /****************************************************************************
181 Functions to free a printer entry datastruct.
182 ****************************************************************************/
184 static void free_printer_entry(void *ptr)
186 Printer_entry *Printer = (Printer_entry *)ptr;
188 if (Printer->notify.client_connected==True) {
189 int snum = -1;
191 if ( Printer->printer_type == SPLHND_SERVER) {
192 snum = -1;
193 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
194 } else if (Printer->printer_type == SPLHND_PRINTER) {
195 snum = print_queue_snum(Printer->sharename);
196 if (snum != -1)
197 srv_spoolss_replycloseprinter(snum,
198 &Printer->notify.client_hnd);
202 Printer->notify.flags=0;
203 Printer->notify.options=0;
204 Printer->notify.localmachine[0]='\0';
205 Printer->notify.printerlocal=0;
206 free_spool_notify_option(&Printer->notify.option);
207 Printer->notify.option=NULL;
208 Printer->notify.client_connected=False;
210 free_nt_devicemode( &Printer->nt_devmode );
211 free_a_printer( &Printer->printer_info, 2 );
213 talloc_destroy( Printer->ctx );
215 /* Remove from the internal list. */
216 DLIST_REMOVE(printers_list, Printer);
218 SAFE_FREE(Printer);
221 /****************************************************************************
222 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
223 ****************************************************************************/
225 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
227 SPOOL_NOTIFY_OPTION *new_sp = NULL;
229 if (!sp)
230 return NULL;
232 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
233 if (!new_sp)
234 return NULL;
236 *new_sp = *sp;
238 if (sp->ctr.count) {
239 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
241 if (!new_sp->ctr.type) {
242 SAFE_FREE(new_sp);
243 return NULL;
247 return new_sp;
250 /****************************************************************************
251 find printer index by handle
252 ****************************************************************************/
254 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
256 Printer_entry *find_printer = NULL;
258 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
259 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
260 return NULL;
263 return find_printer;
266 /****************************************************************************
267 Close printer index by handle.
268 ****************************************************************************/
270 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
272 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
274 if (!Printer) {
275 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
276 return False;
279 close_policy_hnd(p, hnd);
281 return True;
284 /****************************************************************************
285 Delete a printer given a handle.
286 ****************************************************************************/
287 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
289 char *cmd = lp_deleteprinter_cmd();
290 pstring command;
291 int ret;
292 SE_PRIV se_printop = SE_PRINT_OPERATOR;
293 bool is_print_op = False;
295 /* can't fail if we don't try */
297 if ( !*cmd )
298 return WERR_OK;
300 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
302 if ( token )
303 is_print_op = user_has_privileges( token, &se_printop );
305 DEBUG(10,("Running [%s]\n", command));
307 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
309 if ( is_print_op )
310 become_root();
312 if ( (ret = smbrun(command, NULL)) == 0 ) {
313 /* Tell everyone we updated smb.conf. */
314 message_send_all(smbd_messaging_context(),
315 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
318 if ( is_print_op )
319 unbecome_root();
321 /********** END SePrintOperatorPrivlege BLOCK **********/
323 DEBUGADD(10,("returned [%d]\n", ret));
325 if (ret != 0)
326 return WERR_BADFID; /* What to return here? */
328 /* go ahead and re-read the services immediately */
329 reload_services( False );
331 if ( lp_servicenumber( sharename ) < 0 )
332 return WERR_ACCESS_DENIED;
334 return WERR_OK;
337 /****************************************************************************
338 Delete a printer given a handle.
339 ****************************************************************************/
341 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
343 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
345 if (!Printer) {
346 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
347 return WERR_BADFID;
351 * It turns out that Windows allows delete printer on a handle
352 * opened by an admin user, then used on a pipe handle created
353 * by an anonymous user..... but they're working on security.... riiight !
354 * JRA.
357 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
358 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
359 return WERR_ACCESS_DENIED;
362 /* this does not need a become root since the access check has been
363 done on the handle already */
365 if (del_a_printer( Printer->sharename ) != 0) {
366 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
367 return WERR_BADFID;
370 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
373 /****************************************************************************
374 Return the snum of a printer corresponding to an handle.
375 ****************************************************************************/
377 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
378 struct share_params **params)
380 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
382 if (!Printer) {
383 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
384 return False;
387 switch (Printer->printer_type) {
388 case SPLHND_PRINTER:
389 DEBUG(4,("short name:%s\n", Printer->sharename));
390 *number = print_queue_snum(Printer->sharename);
391 return (*number != -1);
392 case SPLHND_SERVER:
393 return False;
394 default:
395 return False;
399 /****************************************************************************
400 Set printer handle type.
401 Check if it's \\server or \\server\printer
402 ****************************************************************************/
404 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
406 DEBUG(3,("Setting printer type=%s\n", handlename));
408 if ( strlen(handlename) < 3 ) {
409 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
410 return False;
413 /* it's a print server */
414 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
415 DEBUGADD(4,("Printer is a print server\n"));
416 Printer->printer_type = SPLHND_SERVER;
418 /* it's a printer (set_printer_hnd_name() will handle port monitors */
419 else {
420 DEBUGADD(4,("Printer is a printer\n"));
421 Printer->printer_type = SPLHND_PRINTER;
424 return True;
427 /****************************************************************************
428 Set printer handle name.. Accept names like \\server, \\server\printer,
429 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
430 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
431 XcvDataPort() interface.
432 ****************************************************************************/
434 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
436 int snum;
437 int n_services=lp_numservices();
438 char *aprinter, *printername;
439 const char *servername;
440 fstring sname;
441 bool found=False;
442 NT_PRINTER_INFO_LEVEL *printer = NULL;
443 WERROR result;
445 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
447 aprinter = handlename;
448 if ( *handlename == '\\' ) {
449 servername = handlename + 2;
450 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
451 *aprinter = '\0';
452 aprinter++;
455 else {
456 servername = "";
459 /* save the servername to fill in replies on this handle */
461 if ( !is_myname_or_ipaddr( servername ) )
462 return False;
464 fstrcpy( Printer->servername, servername );
466 if ( Printer->printer_type == SPLHND_SERVER )
467 return True;
469 if ( Printer->printer_type != SPLHND_PRINTER )
470 return False;
472 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
474 /* check for the Port Monitor Interface */
476 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
477 Printer->printer_type = SPLHND_PORTMON_TCP;
478 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
479 found = True;
481 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
482 Printer->printer_type = SPLHND_PORTMON_LOCAL;
483 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
484 found = True;
487 /* Search all sharenames first as this is easier than pulling
488 the printer_info_2 off of disk. Don't use find_service() since
489 that calls out to map_username() */
491 /* do another loop to look for printernames */
493 for (snum=0; !found && snum<n_services; snum++) {
495 /* no point going on if this is not a printer */
497 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
498 continue;
500 fstrcpy(sname, lp_servicename(snum));
501 if ( strequal( aprinter, sname ) ) {
502 found = True;
503 break;
506 /* no point looking up the printer object if
507 we aren't allowing printername != sharename */
509 if ( lp_force_printername(snum) )
510 continue;
512 fstrcpy(sname, lp_servicename(snum));
514 printer = NULL;
515 result = get_a_printer( NULL, &printer, 2, sname );
516 if ( !W_ERROR_IS_OK(result) ) {
517 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
518 sname, dos_errstr(result)));
519 continue;
522 /* printername is always returned as \\server\printername */
523 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
524 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
525 printer->info_2->printername));
526 free_a_printer( &printer, 2);
527 continue;
530 printername++;
532 if ( strequal(printername, aprinter) ) {
533 free_a_printer( &printer, 2);
534 found = True;
535 break;
538 DEBUGADD(10, ("printername: %s\n", printername));
540 free_a_printer( &printer, 2);
543 free_a_printer( &printer, 2);
545 if ( !found ) {
546 DEBUGADD(4,("Printer not found\n"));
547 return False;
550 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
552 fstrcpy(Printer->sharename, sname);
554 return True;
557 /****************************************************************************
558 Find first available printer slot. creates a printer handle for you.
559 ****************************************************************************/
561 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
563 Printer_entry *new_printer;
565 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
567 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
568 return False;
570 ZERO_STRUCTP(new_printer);
572 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
573 SAFE_FREE(new_printer);
574 return False;
577 /* Add to the internal list. */
578 DLIST_ADD(printers_list, new_printer);
580 new_printer->notify.option=NULL;
582 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
583 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
584 close_printer_handle(p, hnd);
585 return False;
588 if (!set_printer_hnd_printertype(new_printer, name)) {
589 close_printer_handle(p, hnd);
590 return False;
593 if (!set_printer_hnd_name(new_printer, name)) {
594 close_printer_handle(p, hnd);
595 return False;
598 new_printer->access_granted = access_granted;
600 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
602 return True;
605 /***************************************************************************
606 check to see if the client motify handle is monitoring the notification
607 given by (notify_type, notify_field).
608 **************************************************************************/
610 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
611 uint16 notify_field)
613 return True;
616 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
617 uint16 notify_field)
619 SPOOL_NOTIFY_OPTION *option = p->notify.option;
620 uint32 i, j;
623 * Flags should always be zero when the change notify
624 * is registered by the client's spooler. A user Win32 app
625 * might use the flags though instead of the NOTIFY_OPTION_INFO
626 * --jerry
629 if (!option) {
630 return False;
633 if (p->notify.flags)
634 return is_monitoring_event_flags(
635 p->notify.flags, notify_type, notify_field);
637 for (i = 0; i < option->count; i++) {
639 /* Check match for notify_type */
641 if (option->ctr.type[i].type != notify_type)
642 continue;
644 /* Check match for field */
646 for (j = 0; j < option->ctr.type[i].count; j++) {
647 if (option->ctr.type[i].fields[j] == notify_field) {
648 return True;
653 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
654 p->servername, p->sharename, notify_type, notify_field));
656 return False;
659 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
661 static void notify_one_value(struct spoolss_notify_msg *msg,
662 SPOOL_NOTIFY_INFO_DATA *data,
663 TALLOC_CTX *mem_ctx)
665 data->notify_data.value[0] = msg->notify.value[0];
666 data->notify_data.value[1] = 0;
669 static void notify_string(struct spoolss_notify_msg *msg,
670 SPOOL_NOTIFY_INFO_DATA *data,
671 TALLOC_CTX *mem_ctx)
673 UNISTR2 unistr;
675 /* The length of the message includes the trailing \0 */
677 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
679 data->notify_data.data.length = msg->len * 2;
680 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
682 if (!data->notify_data.data.string) {
683 data->notify_data.data.length = 0;
684 return;
687 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
690 static void notify_system_time(struct spoolss_notify_msg *msg,
691 SPOOL_NOTIFY_INFO_DATA *data,
692 TALLOC_CTX *mem_ctx)
694 SYSTEMTIME systime;
695 prs_struct ps;
697 if (msg->len != sizeof(time_t)) {
698 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
699 msg->len));
700 return;
703 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
704 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
705 return;
708 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
709 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
710 prs_mem_free(&ps);
711 return;
714 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
715 prs_mem_free(&ps);
716 return;
719 data->notify_data.data.length = prs_offset(&ps);
720 if (prs_offset(&ps)) {
721 data->notify_data.data.string = (uint16 *)
722 TALLOC(mem_ctx, prs_offset(&ps));
723 if (!data->notify_data.data.string) {
724 prs_mem_free(&ps);
725 return;
727 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
728 } else {
729 data->notify_data.data.string = NULL;
732 prs_mem_free(&ps);
735 struct notify2_message_table {
736 const char *name;
737 void (*fn)(struct spoolss_notify_msg *msg,
738 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
741 static struct notify2_message_table printer_notify_table[] = {
742 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
743 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
744 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
745 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
746 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
747 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
748 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
749 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
750 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
751 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
752 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
753 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
754 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
755 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
756 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
757 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
758 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
759 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
760 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
763 static struct notify2_message_table job_notify_table[] = {
764 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
765 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
766 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
767 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
768 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
769 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
770 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
771 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
772 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
773 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
774 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
775 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
776 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
777 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
778 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
779 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
780 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
781 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
782 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
783 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
784 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
785 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
786 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
787 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
791 /***********************************************************************
792 Allocate talloc context for container object
793 **********************************************************************/
795 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
797 if ( !ctr )
798 return;
800 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
802 return;
805 /***********************************************************************
806 release all allocated memory and zero out structure
807 **********************************************************************/
809 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
811 if ( !ctr )
812 return;
814 if ( ctr->ctx )
815 talloc_destroy(ctr->ctx);
817 ZERO_STRUCTP(ctr);
819 return;
822 /***********************************************************************
823 **********************************************************************/
825 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
827 if ( !ctr )
828 return NULL;
830 return ctr->ctx;
833 /***********************************************************************
834 **********************************************************************/
836 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
838 if ( !ctr || !ctr->msg_groups )
839 return NULL;
841 if ( idx >= ctr->num_groups )
842 return NULL;
844 return &ctr->msg_groups[idx];
848 /***********************************************************************
849 How many groups of change messages do we have ?
850 **********************************************************************/
852 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
854 if ( !ctr )
855 return 0;
857 return ctr->num_groups;
860 /***********************************************************************
861 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
862 **********************************************************************/
864 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
866 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
867 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
868 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
869 int i, new_slot;
871 if ( !ctr || !msg )
872 return 0;
874 /* loop over all groups looking for a matching printer name */
876 for ( i=0; i<ctr->num_groups; i++ ) {
877 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
878 break;
881 /* add a new group? */
883 if ( i == ctr->num_groups ) {
884 ctr->num_groups++;
886 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
887 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
888 return 0;
890 ctr->msg_groups = groups;
892 /* clear the new entry and set the printer name */
894 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
895 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
898 /* add the change messages; 'i' is the correct index now regardless */
900 msg_grp = &ctr->msg_groups[i];
902 msg_grp->num_msgs++;
904 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
905 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
906 return 0;
908 msg_grp->msgs = msg_list;
910 new_slot = msg_grp->num_msgs-1;
911 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
913 /* need to allocate own copy of data */
915 if ( msg->len != 0 )
916 msg_grp->msgs[new_slot].notify.data = (char *)
917 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
919 return ctr->num_groups;
922 /***********************************************************************
923 Send a change notication message on all handles which have a call
924 back registered
925 **********************************************************************/
927 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
929 Printer_entry *p;
930 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
931 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
932 SPOOLSS_NOTIFY_MSG *messages;
933 int sending_msg_count;
935 if ( !msg_group ) {
936 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
937 return;
940 messages = msg_group->msgs;
942 if ( !messages ) {
943 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
944 return;
947 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
949 /* loop over all printers */
951 for (p = printers_list; p; p = p->next) {
952 SPOOL_NOTIFY_INFO_DATA *data;
953 uint32 data_len = 0;
954 uint32 id;
955 int i;
957 /* Is there notification on this handle? */
959 if ( !p->notify.client_connected )
960 continue;
962 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
964 /* For this printer? Print servers always receive
965 notifications. */
967 if ( ( p->printer_type == SPLHND_PRINTER ) &&
968 ( !strequal(msg_group->printername, p->sharename) ) )
969 continue;
971 DEBUG(10,("Our printer\n"));
973 /* allocate the max entries possible */
975 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
976 if (!data) {
977 return;
980 ZERO_STRUCTP(data);
982 /* build the array of change notifications */
984 sending_msg_count = 0;
986 for ( i=0; i<msg_group->num_msgs; i++ ) {
987 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
989 /* Are we monitoring this event? */
991 if (!is_monitoring_event(p, msg->type, msg->field))
992 continue;
994 sending_msg_count++;
997 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
998 msg->type, msg->field, p->sharename));
1001 * if the is a printer notification handle and not a job notification
1002 * type, then set the id to 0. Other wise just use what was specified
1003 * in the message.
1005 * When registering change notification on a print server handle
1006 * we always need to send back the id (snum) matching the printer
1007 * for which the change took place. For change notify registered
1008 * on a printer handle, this does not matter and the id should be 0.
1010 * --jerry
1013 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1014 id = 0;
1015 else
1016 id = msg->id;
1019 /* Convert unix jobid to smb jobid */
1021 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1022 id = sysjob_to_jobid(msg->id);
1024 if (id == -1) {
1025 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1026 goto done;
1030 construct_info_data( &data[data_len], msg->type, msg->field, id );
1032 switch(msg->type) {
1033 case PRINTER_NOTIFY_TYPE:
1034 if ( printer_notify_table[msg->field].fn )
1035 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1036 break;
1038 case JOB_NOTIFY_TYPE:
1039 if ( job_notify_table[msg->field].fn )
1040 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1041 break;
1043 default:
1044 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1045 goto done;
1048 data_len++;
1051 if ( sending_msg_count ) {
1052 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1053 data_len, data, p->notify.change, 0 );
1057 done:
1058 DEBUG(8,("send_notify2_changes: Exit...\n"));
1059 return;
1062 /***********************************************************************
1063 **********************************************************************/
1065 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1068 uint32 tv_sec, tv_usec;
1069 size_t offset = 0;
1071 /* Unpack message */
1073 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1074 msg->printer);
1076 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1077 &tv_sec, &tv_usec,
1078 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1080 if (msg->len == 0)
1081 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1082 &msg->notify.value[0], &msg->notify.value[1]);
1083 else
1084 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1085 &msg->len, &msg->notify.data);
1087 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1088 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1090 tv->tv_sec = tv_sec;
1091 tv->tv_usec = tv_usec;
1093 if (msg->len == 0)
1094 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1095 msg->notify.value[1]));
1096 else
1097 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1099 return True;
1102 /********************************************************************
1103 Receive a notify2 message list
1104 ********************************************************************/
1106 static void receive_notify2_message_list(struct messaging_context *msg,
1107 void *private_data,
1108 uint32_t msg_type,
1109 struct server_id server_id,
1110 DATA_BLOB *data)
1112 size_t msg_count, i;
1113 char *buf = (char *)data->data;
1114 char *msg_ptr;
1115 size_t msg_len;
1116 SPOOLSS_NOTIFY_MSG notify;
1117 SPOOLSS_NOTIFY_MSG_CTR messages;
1118 int num_groups;
1120 if (data->length < 4) {
1121 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1122 return;
1125 msg_count = IVAL(buf, 0);
1126 msg_ptr = buf + 4;
1128 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1130 if (msg_count == 0) {
1131 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1132 return;
1135 /* initialize the container */
1137 ZERO_STRUCT( messages );
1138 notify_msg_ctr_init( &messages );
1141 * build message groups for each printer identified
1142 * in a change_notify msg. Remember that a PCN message
1143 * includes the handle returned for the srv_spoolss_replyopenprinter()
1144 * call. Therefore messages are grouped according to printer handle.
1147 for ( i=0; i<msg_count; i++ ) {
1148 struct timeval msg_tv;
1150 if (msg_ptr + 4 - buf > data->length) {
1151 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1152 return;
1155 msg_len = IVAL(msg_ptr,0);
1156 msg_ptr += 4;
1158 if (msg_ptr + msg_len - buf > data->length) {
1159 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1160 return;
1163 /* unpack messages */
1165 ZERO_STRUCT( notify );
1166 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1167 msg_ptr += msg_len;
1169 /* add to correct list in container */
1171 notify_msg_ctr_addmsg( &messages, &notify );
1173 /* free memory that might have been allocated by notify2_unpack_msg() */
1175 if ( notify.len != 0 )
1176 SAFE_FREE( notify.notify.data );
1179 /* process each group of messages */
1181 num_groups = notify_msg_ctr_numgroups( &messages );
1182 for ( i=0; i<num_groups; i++ )
1183 send_notify2_changes( &messages, i );
1186 /* cleanup */
1188 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1190 notify_msg_ctr_destroy( &messages );
1192 return;
1195 /********************************************************************
1196 Send a message to ourself about new driver being installed
1197 so we can upgrade the information for each printer bound to this
1198 driver
1199 ********************************************************************/
1201 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1203 int len = strlen(drivername);
1205 if (!len)
1206 return False;
1208 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1209 drivername));
1211 messaging_send_buf(smbd_messaging_context(), procid_self(),
1212 MSG_PRINTER_DRVUPGRADE,
1213 (uint8 *)drivername, len+1);
1215 return True;
1218 /**********************************************************************
1219 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1220 over all printers, upgrading ones as necessary
1221 **********************************************************************/
1223 void do_drv_upgrade_printer(struct messaging_context *msg,
1224 void *private_data,
1225 uint32_t msg_type,
1226 struct server_id server_id,
1227 DATA_BLOB *data)
1229 fstring drivername;
1230 int snum;
1231 int n_services = lp_numservices();
1232 size_t len;
1234 len = MIN(data->length,sizeof(drivername)-1);
1235 strncpy(drivername, (const char *)data->data, len);
1237 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1239 /* Iterate the printer list */
1241 for (snum=0; snum<n_services; snum++)
1243 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1245 WERROR result;
1246 NT_PRINTER_INFO_LEVEL *printer = NULL;
1248 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1249 if (!W_ERROR_IS_OK(result))
1250 continue;
1252 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1254 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1256 /* all we care about currently is the change_id */
1258 result = mod_a_printer(printer, 2);
1259 if (!W_ERROR_IS_OK(result)) {
1260 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1261 dos_errstr(result)));
1265 free_a_printer(&printer, 2);
1269 /* all done */
1272 /********************************************************************
1273 Update the cache for all printq's with a registered client
1274 connection
1275 ********************************************************************/
1277 void update_monitored_printq_cache( void )
1279 Printer_entry *printer = printers_list;
1280 int snum;
1282 /* loop through all printers and update the cache where
1283 client_connected == True */
1284 while ( printer )
1286 if ( (printer->printer_type == SPLHND_PRINTER)
1287 && printer->notify.client_connected )
1289 snum = print_queue_snum(printer->sharename);
1290 print_queue_status( snum, NULL, NULL );
1293 printer = printer->next;
1296 return;
1298 /********************************************************************
1299 Send a message to ourself about new driver being installed
1300 so we can upgrade the information for each printer bound to this
1301 driver
1302 ********************************************************************/
1304 static bool srv_spoolss_reset_printerdata(char* drivername)
1306 int len = strlen(drivername);
1308 if (!len)
1309 return False;
1311 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1312 drivername));
1314 messaging_send_buf(smbd_messaging_context(), procid_self(),
1315 MSG_PRINTERDATA_INIT_RESET,
1316 (uint8 *)drivername, len+1);
1318 return True;
1321 /**********************************************************************
1322 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1323 over all printers, resetting printer data as neessary
1324 **********************************************************************/
1326 void reset_all_printerdata(struct messaging_context *msg,
1327 void *private_data,
1328 uint32_t msg_type,
1329 struct server_id server_id,
1330 DATA_BLOB *data)
1332 fstring drivername;
1333 int snum;
1334 int n_services = lp_numservices();
1335 size_t len;
1337 len = MIN( data->length, sizeof(drivername)-1 );
1338 strncpy( drivername, (const char *)data->data, len );
1340 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1342 /* Iterate the printer list */
1344 for ( snum=0; snum<n_services; snum++ )
1346 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1348 WERROR result;
1349 NT_PRINTER_INFO_LEVEL *printer = NULL;
1351 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1352 if ( !W_ERROR_IS_OK(result) )
1353 continue;
1356 * if the printer is bound to the driver,
1357 * then reset to the new driver initdata
1360 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1362 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1364 if ( !set_driver_init(printer, 2) ) {
1365 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1366 printer->info_2->printername, printer->info_2->drivername));
1369 result = mod_a_printer( printer, 2 );
1370 if ( !W_ERROR_IS_OK(result) ) {
1371 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1372 get_dos_error_msg(result)));
1376 free_a_printer( &printer, 2 );
1380 /* all done */
1382 return;
1385 /********************************************************************
1386 Copy routines used by convert_to_openprinterex()
1387 *******************************************************************/
1389 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1391 DEVICEMODE *d;
1392 int len;
1394 if (!devmode)
1395 return NULL;
1397 DEBUG (8,("dup_devmode\n"));
1399 /* bulk copy first */
1401 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1402 if (!d)
1403 return NULL;
1405 /* dup the pointer members separately */
1407 len = unistrlen(devmode->devicename.buffer);
1408 if (len != -1) {
1409 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1410 if (!d->devicename.buffer) {
1411 return NULL;
1413 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1414 return NULL;
1418 len = unistrlen(devmode->formname.buffer);
1419 if (len != -1) {
1420 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1421 if (!d->devicename.buffer) {
1422 return NULL;
1424 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1425 return NULL;
1428 if (devmode->driverextra) {
1429 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1430 devmode->driverextra);
1431 if (!d->dev_private) {
1432 return NULL;
1434 } else {
1435 d->dev_private = NULL;
1437 return d;
1440 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1442 if (!new_ctr || !ctr)
1443 return;
1445 DEBUG(8,("copy_devmode_ctr\n"));
1447 new_ctr->size = ctr->size;
1448 new_ctr->devmode_ptr = ctr->devmode_ptr;
1450 if(ctr->devmode_ptr)
1451 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1454 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1456 if (!new_def || !def)
1457 return;
1459 DEBUG(8,("copy_printer_defaults\n"));
1461 new_def->datatype_ptr = def->datatype_ptr;
1463 if (def->datatype_ptr)
1464 copy_unistr2(&new_def->datatype, &def->datatype);
1466 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1468 new_def->access_required = def->access_required;
1471 /********************************************************************
1472 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1473 * SPOOL_Q_OPEN_PRINTER_EX structure
1474 ********************************************************************/
1476 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1478 if (!q_u_ex || !q_u)
1479 return WERR_OK;
1481 DEBUG(8,("convert_to_openprinterex\n"));
1483 if ( q_u->printername ) {
1484 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1485 if (q_u_ex->printername == NULL)
1486 return WERR_NOMEM;
1487 copy_unistr2(q_u_ex->printername, q_u->printername);
1490 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1492 return WERR_OK;
1495 /********************************************************************
1496 * spoolss_open_printer
1498 * called from the spoolss dispatcher
1499 ********************************************************************/
1501 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1503 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1504 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1506 if (!q_u || !r_u)
1507 return WERR_NOMEM;
1509 ZERO_STRUCT(q_u_ex);
1510 ZERO_STRUCT(r_u_ex);
1512 /* convert the OpenPrinter() call to OpenPrinterEx() */
1514 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1515 if (!W_ERROR_IS_OK(r_u_ex.status))
1516 return r_u_ex.status;
1518 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1520 /* convert back to OpenPrinter() */
1522 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1524 return r_u->status;
1527 /********************************************************************
1528 ********************************************************************/
1530 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1532 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1533 POLICY_HND *handle = &r_u->handle;
1535 fstring name;
1536 int snum;
1537 Printer_entry *Printer=NULL;
1539 if ( !q_u->printername )
1540 return WERR_INVALID_PRINTER_NAME;
1542 /* some sanity check because you can open a printer or a print server */
1543 /* aka: \\server\printer or \\server */
1545 unistr2_to_ascii(name, q_u->printername, sizeof(name));
1547 DEBUGADD(3,("checking name: %s\n",name));
1549 if (!open_printer_hnd(p, handle, name, 0))
1550 return WERR_INVALID_PRINTER_NAME;
1552 Printer=find_printer_index_by_hnd(p, handle);
1553 if ( !Printer ) {
1554 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1555 "handle we created for printer %s\n", name ));
1556 close_printer_handle(p,handle);
1557 return WERR_INVALID_PRINTER_NAME;
1561 * First case: the user is opening the print server:
1563 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1564 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1566 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1567 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1568 * or if the user is listed in the smb.conf printer admin parameter.
1570 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1571 * client view printer folder, but does not show the MSAPW.
1573 * Note: this test needs code to check access rights here too. Jeremy
1574 * could you look at this?
1576 * Second case: the user is opening a printer:
1577 * NT doesn't let us connect to a printer if the connecting user
1578 * doesn't have print permission.
1580 * Third case: user is opening a Port Monitor
1581 * access checks same as opening a handle to the print server.
1584 switch (Printer->printer_type )
1586 case SPLHND_SERVER:
1587 case SPLHND_PORTMON_TCP:
1588 case SPLHND_PORTMON_LOCAL:
1589 /* Printserver handles use global struct... */
1591 snum = -1;
1593 /* Map standard access rights to object specific access rights */
1595 se_map_standard(&printer_default->access_required,
1596 &printserver_std_mapping);
1598 /* Deny any object specific bits that don't apply to print
1599 servers (i.e printer and job specific bits) */
1601 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1603 if (printer_default->access_required &
1604 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1605 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1606 close_printer_handle(p, handle);
1607 return WERR_ACCESS_DENIED;
1610 /* Allow admin access */
1612 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1614 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1616 if (!lp_ms_add_printer_wizard()) {
1617 close_printer_handle(p, handle);
1618 return WERR_ACCESS_DENIED;
1621 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1622 and not a printer admin, then fail */
1624 if ((p->pipe_user.ut.uid != 0) &&
1625 !user_has_privileges(p->pipe_user.nt_user_token,
1626 &se_printop ) &&
1627 !token_contains_name_in_list(
1628 uidtoname(p->pipe_user.ut.uid), NULL,
1629 p->pipe_user.nt_user_token,
1630 lp_printer_admin(snum))) {
1631 close_printer_handle(p, handle);
1632 return WERR_ACCESS_DENIED;
1635 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1637 else
1639 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1642 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1643 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1645 /* We fall through to return WERR_OK */
1646 break;
1648 case SPLHND_PRINTER:
1649 /* NT doesn't let us connect to a printer if the connecting user
1650 doesn't have print permission. */
1652 if (!get_printer_snum(p, handle, &snum, NULL)) {
1653 close_printer_handle(p, handle);
1654 return WERR_BADFID;
1657 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1659 /* map an empty access mask to the minimum access mask */
1660 if (printer_default->access_required == 0x0)
1661 printer_default->access_required = PRINTER_ACCESS_USE;
1664 * If we are not serving the printer driver for this printer,
1665 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1666 * will keep NT clients happy --jerry
1669 if (lp_use_client_driver(snum)
1670 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1672 printer_default->access_required = PRINTER_ACCESS_USE;
1675 /* check smb.conf parameters and the the sec_desc */
1677 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1678 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1679 return WERR_ACCESS_DENIED;
1682 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1683 p->pipe_user.nt_user_token, snum) ||
1684 !print_access_check(&p->pipe_user, snum,
1685 printer_default->access_required)) {
1686 DEBUG(3, ("access DENIED for printer open\n"));
1687 close_printer_handle(p, handle);
1688 return WERR_ACCESS_DENIED;
1691 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1692 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1693 close_printer_handle(p, handle);
1694 return WERR_ACCESS_DENIED;
1697 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1698 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1699 else
1700 printer_default->access_required = PRINTER_ACCESS_USE;
1702 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1703 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1705 break;
1707 default:
1708 /* sanity check to prevent programmer error */
1709 return WERR_BADFID;
1712 Printer->access_granted = printer_default->access_required;
1715 * If the client sent a devmode in the OpenPrinter() call, then
1716 * save it here in case we get a job submission on this handle
1719 if ( (Printer->printer_type != SPLHND_SERVER)
1720 && q_u->printer_default.devmode_cont.devmode_ptr )
1722 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1723 &Printer->nt_devmode );
1726 #if 0 /* JERRY -- I'm doubtful this is really effective */
1727 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1728 optimization in Windows 2000 clients --jerry */
1730 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1731 && (RA_WIN2K == get_remote_arch()) )
1733 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1734 sys_usleep( 500000 );
1736 #endif
1738 return WERR_OK;
1741 /****************************************************************************
1742 ****************************************************************************/
1744 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1745 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1747 bool ret;
1749 switch (level) {
1750 case 2:
1751 /* allocate memory if needed. Messy because
1752 convert_printer_info is used to update an existing
1753 printer or build a new one */
1755 if ( !printer->info_2 ) {
1756 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1757 if ( !printer->info_2 ) {
1758 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1759 return False;
1763 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1764 printer->info_2->setuptime = time(NULL);
1766 return ret;
1769 return False;
1772 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1773 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1775 bool result = True;
1777 switch (level) {
1778 case 3:
1779 printer->info_3=NULL;
1780 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1781 result = False;
1782 break;
1783 case 6:
1784 printer->info_6=NULL;
1785 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1786 result = False;
1787 break;
1788 default:
1789 break;
1792 return result;
1795 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1796 NT_DEVICEMODE **pp_nt_devmode)
1798 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1801 * Ensure nt_devmode is a valid pointer
1802 * as we will be overwriting it.
1805 if (nt_devmode == NULL) {
1806 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1807 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1808 return False;
1811 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1812 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1814 nt_devmode->specversion=devmode->specversion;
1815 nt_devmode->driverversion=devmode->driverversion;
1816 nt_devmode->size=devmode->size;
1817 nt_devmode->fields=devmode->fields;
1818 nt_devmode->orientation=devmode->orientation;
1819 nt_devmode->papersize=devmode->papersize;
1820 nt_devmode->paperlength=devmode->paperlength;
1821 nt_devmode->paperwidth=devmode->paperwidth;
1822 nt_devmode->scale=devmode->scale;
1823 nt_devmode->copies=devmode->copies;
1824 nt_devmode->defaultsource=devmode->defaultsource;
1825 nt_devmode->printquality=devmode->printquality;
1826 nt_devmode->color=devmode->color;
1827 nt_devmode->duplex=devmode->duplex;
1828 nt_devmode->yresolution=devmode->yresolution;
1829 nt_devmode->ttoption=devmode->ttoption;
1830 nt_devmode->collate=devmode->collate;
1832 nt_devmode->logpixels=devmode->logpixels;
1833 nt_devmode->bitsperpel=devmode->bitsperpel;
1834 nt_devmode->pelswidth=devmode->pelswidth;
1835 nt_devmode->pelsheight=devmode->pelsheight;
1836 nt_devmode->displayflags=devmode->displayflags;
1837 nt_devmode->displayfrequency=devmode->displayfrequency;
1838 nt_devmode->icmmethod=devmode->icmmethod;
1839 nt_devmode->icmintent=devmode->icmintent;
1840 nt_devmode->mediatype=devmode->mediatype;
1841 nt_devmode->dithertype=devmode->dithertype;
1842 nt_devmode->reserved1=devmode->reserved1;
1843 nt_devmode->reserved2=devmode->reserved2;
1844 nt_devmode->panningwidth=devmode->panningwidth;
1845 nt_devmode->panningheight=devmode->panningheight;
1848 * Only change private and driverextra if the incoming devmode
1849 * has a new one. JRA.
1852 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1853 SAFE_FREE(nt_devmode->nt_dev_private);
1854 nt_devmode->driverextra=devmode->driverextra;
1855 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1856 return False;
1857 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1860 *pp_nt_devmode = nt_devmode;
1862 return True;
1865 /********************************************************************
1866 * _spoolss_enddocprinter_internal.
1867 ********************************************************************/
1869 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1871 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1872 int snum;
1874 if (!Printer) {
1875 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1876 return WERR_BADFID;
1879 if (!get_printer_snum(p, handle, &snum, NULL))
1880 return WERR_BADFID;
1882 Printer->document_started=False;
1883 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1884 /* error codes unhandled so far ... */
1886 return WERR_OK;
1889 /********************************************************************
1890 * api_spoolss_closeprinter
1891 ********************************************************************/
1893 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1895 POLICY_HND *handle = &q_u->handle;
1897 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1899 if (Printer && Printer->document_started)
1900 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1902 if (!close_printer_handle(p, handle))
1903 return WERR_BADFID;
1905 /* clear the returned printer handle. Observed behavior
1906 from Win2k server. Don't think this really matters.
1907 Previous code just copied the value of the closed
1908 handle. --jerry */
1910 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1912 return WERR_OK;
1915 /********************************************************************
1916 * api_spoolss_deleteprinter
1918 ********************************************************************/
1920 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1922 POLICY_HND *handle = &q_u->handle;
1923 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1924 WERROR result;
1926 if (Printer && Printer->document_started)
1927 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1929 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1931 result = delete_printer_handle(p, handle);
1933 update_c_setprinter(False);
1935 return result;
1938 /*******************************************************************
1939 * static function to lookup the version id corresponding to an
1940 * long architecture string
1941 ******************************************************************/
1943 static int get_version_id (char * arch)
1945 int i;
1946 struct table_node archi_table[]= {
1948 {"Windows 4.0", "WIN40", 0 },
1949 {"Windows NT x86", "W32X86", 2 },
1950 {"Windows NT R4000", "W32MIPS", 2 },
1951 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1952 {"Windows NT PowerPC", "W32PPC", 2 },
1953 {"Windows IA64", "IA64", 3 },
1954 {"Windows x64", "x64", 3 },
1955 {NULL, "", -1 }
1958 for (i=0; archi_table[i].long_archi != NULL; i++)
1960 if (strcmp(arch, archi_table[i].long_archi) == 0)
1961 return (archi_table[i].version);
1964 return -1;
1967 /********************************************************************
1968 * _spoolss_deleteprinterdriver
1969 ********************************************************************/
1971 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1973 fstring driver;
1974 fstring arch;
1975 NT_PRINTER_DRIVER_INFO_LEVEL info;
1976 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1977 int version;
1978 WERROR status;
1979 WERROR status_win2k = WERR_ACCESS_DENIED;
1980 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1982 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1983 and not a printer admin, then fail */
1985 if ( (p->pipe_user.ut.uid != 0)
1986 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1987 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1988 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1990 return WERR_ACCESS_DENIED;
1993 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
1994 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
1996 /* check that we have a valid driver name first */
1998 if ((version=get_version_id(arch)) == -1)
1999 return WERR_INVALID_ENVIRONMENT;
2001 ZERO_STRUCT(info);
2002 ZERO_STRUCT(info_win2k);
2004 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2006 /* try for Win2k driver if "Windows NT x86" */
2008 if ( version == 2 ) {
2009 version = 3;
2010 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2011 status = WERR_UNKNOWN_PRINTER_DRIVER;
2012 goto done;
2015 /* otherwise it was a failure */
2016 else {
2017 status = WERR_UNKNOWN_PRINTER_DRIVER;
2018 goto done;
2023 if (printer_driver_in_use(info.info_3)) {
2024 status = WERR_PRINTER_DRIVER_IN_USE;
2025 goto done;
2028 if ( version == 2 )
2030 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2032 /* if we get to here, we now have 2 driver info structures to remove */
2033 /* remove the Win2k driver first*/
2035 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2036 free_a_printer_driver( info_win2k, 3 );
2038 /* this should not have failed---if it did, report to client */
2039 if ( !W_ERROR_IS_OK(status_win2k) )
2041 status = status_win2k;
2042 goto done;
2047 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2049 /* if at least one of the deletes succeeded return OK */
2051 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2052 status = WERR_OK;
2054 done:
2055 free_a_printer_driver( info, 3 );
2057 return status;
2060 /********************************************************************
2061 * spoolss_deleteprinterdriverex
2062 ********************************************************************/
2064 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2066 fstring driver;
2067 fstring arch;
2068 NT_PRINTER_DRIVER_INFO_LEVEL info;
2069 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2070 int version;
2071 uint32 flags = q_u->delete_flags;
2072 bool delete_files;
2073 WERROR status;
2074 WERROR status_win2k = WERR_ACCESS_DENIED;
2075 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2077 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2078 and not a printer admin, then fail */
2080 if ( (p->pipe_user.ut.uid != 0)
2081 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2082 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2083 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2085 return WERR_ACCESS_DENIED;
2088 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2089 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2091 /* check that we have a valid driver name first */
2092 if ((version=get_version_id(arch)) == -1) {
2093 /* this is what NT returns */
2094 return WERR_INVALID_ENVIRONMENT;
2097 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2098 version = q_u->version;
2100 ZERO_STRUCT(info);
2101 ZERO_STRUCT(info_win2k);
2103 status = get_a_printer_driver(&info, 3, driver, arch, version);
2105 if ( !W_ERROR_IS_OK(status) )
2108 * if the client asked for a specific version,
2109 * or this is something other than Windows NT x86,
2110 * then we've failed
2113 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2114 goto done;
2116 /* try for Win2k driver if "Windows NT x86" */
2118 version = 3;
2119 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2120 status = WERR_UNKNOWN_PRINTER_DRIVER;
2121 goto done;
2125 if ( printer_driver_in_use(info.info_3) ) {
2126 status = WERR_PRINTER_DRIVER_IN_USE;
2127 goto done;
2131 * we have a couple of cases to consider.
2132 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2133 * then the delete should fail if **any** files overlap with
2134 * other drivers
2135 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2136 * non-overlapping files
2137 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2138 * is set, the do not delete any files
2139 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2142 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2144 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2146 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2147 /* no idea of the correct error here */
2148 status = WERR_ACCESS_DENIED;
2149 goto done;
2153 /* also check for W32X86/3 if necessary; maybe we already have? */
2155 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2156 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2159 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2160 /* no idea of the correct error here */
2161 free_a_printer_driver( info_win2k, 3 );
2162 status = WERR_ACCESS_DENIED;
2163 goto done;
2166 /* if we get to here, we now have 2 driver info structures to remove */
2167 /* remove the Win2k driver first*/
2169 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2170 free_a_printer_driver( info_win2k, 3 );
2172 /* this should not have failed---if it did, report to client */
2174 if ( !W_ERROR_IS_OK(status_win2k) )
2175 goto done;
2179 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2181 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2182 status = WERR_OK;
2183 done:
2184 free_a_printer_driver( info, 3 );
2186 return status;
2190 /****************************************************************************
2191 Internal routine for retreiving printerdata
2192 ***************************************************************************/
2194 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2195 const char *key, const char *value, uint32 *type, uint8 **data,
2196 uint32 *needed, uint32 in_size )
2198 REGISTRY_VALUE *val;
2199 uint32 size;
2200 int data_len;
2202 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2203 return WERR_BADFILE;
2205 *type = regval_type( val );
2207 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2209 size = regval_size( val );
2211 /* copy the min(in_size, len) */
2213 if ( in_size ) {
2214 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2216 /* special case for 0 length values */
2217 if ( data_len ) {
2218 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2219 return WERR_NOMEM;
2221 else {
2222 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2223 return WERR_NOMEM;
2226 else
2227 *data = NULL;
2229 *needed = size;
2231 DEBUG(5,("get_printer_dataex: copy done\n"));
2233 return WERR_OK;
2236 /****************************************************************************
2237 Internal routine for removing printerdata
2238 ***************************************************************************/
2240 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2242 return delete_printer_data( printer->info_2, key, value );
2245 /****************************************************************************
2246 Internal routine for storing printerdata
2247 ***************************************************************************/
2249 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2250 uint32 type, uint8 *data, int real_len )
2252 /* the registry objects enforce uniqueness based on value name */
2254 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2257 /********************************************************************
2258 GetPrinterData on a printer server Handle.
2259 ********************************************************************/
2261 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2263 int i;
2265 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2267 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2268 *type = REG_DWORD;
2269 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2270 return WERR_NOMEM;
2271 SIVAL(*data, 0, 0x00);
2272 *needed = 0x4;
2273 return WERR_OK;
2276 if (!StrCaseCmp(value, "BeepEnabled")) {
2277 *type = REG_DWORD;
2278 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2279 return WERR_NOMEM;
2280 SIVAL(*data, 0, 0x00);
2281 *needed = 0x4;
2282 return WERR_OK;
2285 if (!StrCaseCmp(value, "EventLog")) {
2286 *type = REG_DWORD;
2287 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2288 return WERR_NOMEM;
2289 /* formally was 0x1b */
2290 SIVAL(*data, 0, 0x0);
2291 *needed = 0x4;
2292 return WERR_OK;
2295 if (!StrCaseCmp(value, "NetPopup")) {
2296 *type = REG_DWORD;
2297 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2298 return WERR_NOMEM;
2299 SIVAL(*data, 0, 0x00);
2300 *needed = 0x4;
2301 return WERR_OK;
2304 if (!StrCaseCmp(value, "MajorVersion")) {
2305 *type = REG_DWORD;
2306 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2307 return WERR_NOMEM;
2309 /* Windows NT 4.0 seems to not allow uploading of drivers
2310 to a server that reports 0x3 as the MajorVersion.
2311 need to investigate more how Win2k gets around this .
2312 -- jerry */
2314 if ( RA_WINNT == get_remote_arch() )
2315 SIVAL(*data, 0, 2);
2316 else
2317 SIVAL(*data, 0, 3);
2319 *needed = 0x4;
2320 return WERR_OK;
2323 if (!StrCaseCmp(value, "MinorVersion")) {
2324 *type = REG_DWORD;
2325 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2326 return WERR_NOMEM;
2327 SIVAL(*data, 0, 0);
2328 *needed = 0x4;
2329 return WERR_OK;
2332 /* REG_BINARY
2333 * uint32 size = 0x114
2334 * uint32 major = 5
2335 * uint32 minor = [0|1]
2336 * uint32 build = [2195|2600]
2337 * extra unicode string = e.g. "Service Pack 3"
2339 if (!StrCaseCmp(value, "OSVersion")) {
2340 *type = REG_BINARY;
2341 *needed = 0x114;
2343 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2344 return WERR_NOMEM;
2346 SIVAL(*data, 0, *needed); /* size */
2347 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2348 SIVAL(*data, 8, 0);
2349 SIVAL(*data, 12, 2195); /* build */
2351 /* leave extra string empty */
2353 return WERR_OK;
2357 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2358 const char *string="C:\\PRINTERS";
2359 *type = REG_SZ;
2360 *needed = 2*(strlen(string)+1);
2361 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2362 return WERR_NOMEM;
2363 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2365 /* it's done by hand ready to go on the wire */
2366 for (i=0; i<strlen(string); i++) {
2367 (*data)[2*i]=string[i];
2368 (*data)[2*i+1]='\0';
2370 return WERR_OK;
2373 if (!StrCaseCmp(value, "Architecture")) {
2374 const char *string="Windows NT x86";
2375 *type = REG_SZ;
2376 *needed = 2*(strlen(string)+1);
2377 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2378 return WERR_NOMEM;
2379 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2380 for (i=0; i<strlen(string); i++) {
2381 (*data)[2*i]=string[i];
2382 (*data)[2*i+1]='\0';
2384 return WERR_OK;
2387 if (!StrCaseCmp(value, "DsPresent")) {
2388 *type = REG_DWORD;
2389 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2390 return WERR_NOMEM;
2392 /* only show the publish check box if we are a
2393 memeber of a AD domain */
2395 if ( lp_security() == SEC_ADS )
2396 SIVAL(*data, 0, 0x01);
2397 else
2398 SIVAL(*data, 0, 0x00);
2400 *needed = 0x4;
2401 return WERR_OK;
2404 if (!StrCaseCmp(value, "DNSMachineName")) {
2405 const char *hostname = get_mydnsfullname();
2407 if (!hostname)
2408 return WERR_BADFILE;
2409 *type = REG_SZ;
2410 *needed = 2*(strlen(hostname)+1);
2411 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2412 return WERR_NOMEM;
2413 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2414 for (i=0; i<strlen(hostname); i++) {
2415 (*data)[2*i]=hostname[i];
2416 (*data)[2*i+1]='\0';
2418 return WERR_OK;
2422 return WERR_BADFILE;
2425 /********************************************************************
2426 * spoolss_getprinterdata
2427 ********************************************************************/
2429 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2431 POLICY_HND *handle = &q_u->handle;
2432 UNISTR2 *valuename = &q_u->valuename;
2433 uint32 in_size = q_u->size;
2434 uint32 *type = &r_u->type;
2435 uint32 *out_size = &r_u->size;
2436 uint8 **data = &r_u->data;
2437 uint32 *needed = &r_u->needed;
2438 WERROR status;
2439 fstring value;
2440 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2441 NT_PRINTER_INFO_LEVEL *printer = NULL;
2442 int snum = 0;
2445 * Reminder: when it's a string, the length is in BYTES
2446 * even if UNICODE is negociated.
2448 * JFM, 4/19/1999
2451 *out_size = in_size;
2453 /* in case of problem, return some default values */
2455 *needed = 0;
2456 *type = 0;
2458 DEBUG(4,("_spoolss_getprinterdata\n"));
2460 if ( !Printer ) {
2461 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2462 status = WERR_BADFID;
2463 goto done;
2466 unistr2_to_ascii(value, valuename, sizeof(value));
2468 if ( Printer->printer_type == SPLHND_SERVER )
2469 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2470 else
2472 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2473 status = WERR_BADFID;
2474 goto done;
2477 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2478 if ( !W_ERROR_IS_OK(status) )
2479 goto done;
2481 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2483 if ( strequal(value, "ChangeId") ) {
2484 *type = REG_DWORD;
2485 *needed = sizeof(uint32);
2486 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2487 status = WERR_NOMEM;
2488 goto done;
2490 SIVAL( *data, 0, printer->info_2->changeid );
2491 status = WERR_OK;
2493 else
2494 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2497 if (*needed > *out_size)
2498 status = WERR_MORE_DATA;
2500 done:
2501 if ( !W_ERROR_IS_OK(status) )
2503 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2505 /* reply this param doesn't exist */
2507 if ( *out_size ) {
2508 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2509 if ( printer )
2510 free_a_printer( &printer, 2 );
2511 return WERR_NOMEM;
2513 } else {
2514 *data = NULL;
2518 /* cleanup & exit */
2520 if ( printer )
2521 free_a_printer( &printer, 2 );
2523 return status;
2526 /*********************************************************
2527 Connect to the client machine.
2528 **********************************************************/
2530 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2531 struct sockaddr_storage *client_ss, const char *remote_machine)
2533 NTSTATUS ret;
2534 struct cli_state *the_cli;
2535 struct sockaddr_storage rm_addr;
2537 if ( is_zero_addr(client_ss) ) {
2538 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2539 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2540 return False;
2543 if (ismyaddr(&rm_addr)) {
2544 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2545 return False;
2547 } else {
2548 char addr[INET6_ADDRSTRLEN];
2549 rm_addr = *client_ss;
2550 print_sockaddr(addr, sizeof(addr), &rm_addr);
2551 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2552 addr));
2555 /* setup the connection */
2557 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2558 &rm_addr, 0, "IPC$", "IPC",
2559 "", /* username */
2560 "", /* domain */
2561 "", /* password */
2562 0, lp_client_signing(), NULL );
2564 if ( !NT_STATUS_IS_OK( ret ) ) {
2565 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2566 remote_machine ));
2567 return False;
2570 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2571 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2572 cli_shutdown(the_cli);
2573 return False;
2577 * Ok - we have an anonymous connection to the IPC$ share.
2578 * Now start the NT Domain stuff :-).
2581 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2582 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2583 remote_machine, nt_errstr(ret)));
2584 cli_shutdown(the_cli);
2585 return False;
2588 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2590 (*pp_pipe)->cli = the_cli;
2592 return True;
2595 /***************************************************************************
2596 Connect to the client.
2597 ****************************************************************************/
2599 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2600 uint32 localprinter, uint32 type,
2601 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2603 WERROR result;
2606 * If it's the first connection, contact the client
2607 * and connect to the IPC$ share anonymously
2609 if (smb_connections==0) {
2610 fstring unix_printer;
2612 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2614 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2615 return False;
2617 messaging_register(smbd_messaging_context(), NULL,
2618 MSG_PRINTER_NOTIFY2,
2619 receive_notify2_message_list);
2620 /* Tell the connections db we're now interested in printer
2621 * notify messages. */
2622 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2626 * Tell the specific printing tdb we want messages for this printer
2627 * by registering our PID.
2630 if (!print_notify_register_pid(snum))
2631 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2633 smb_connections++;
2635 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2636 type, handle);
2638 if (!W_ERROR_IS_OK(result))
2639 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2640 dos_errstr(result)));
2642 return (W_ERROR_IS_OK(result));
2645 /********************************************************************
2646 * _spoolss_rffpcnex
2647 * ReplyFindFirstPrinterChangeNotifyEx
2649 * before replying OK: status=0 a rpc call is made to the workstation
2650 * asking ReplyOpenPrinter
2652 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2653 * called from api_spoolss_rffpcnex
2654 ********************************************************************/
2656 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2658 POLICY_HND *handle = &q_u->handle;
2659 uint32 flags = q_u->flags;
2660 uint32 options = q_u->options;
2661 UNISTR2 *localmachine = &q_u->localmachine;
2662 uint32 printerlocal = q_u->printerlocal;
2663 int snum = -1;
2664 SPOOL_NOTIFY_OPTION *option = q_u->option;
2665 struct sockaddr_storage client_ss;
2667 /* store the notify value in the printer struct */
2669 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2671 if (!Printer) {
2672 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2673 return WERR_BADFID;
2676 Printer->notify.flags=flags;
2677 Printer->notify.options=options;
2678 Printer->notify.printerlocal=printerlocal;
2680 if (Printer->notify.option)
2681 free_spool_notify_option(&Printer->notify.option);
2683 Printer->notify.option=dup_spool_notify_option(option);
2685 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2686 sizeof(Printer->notify.localmachine));
2688 /* Connect to the client machine and send a ReplyOpenPrinter */
2690 if ( Printer->printer_type == SPLHND_SERVER)
2691 snum = -1;
2692 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2693 !get_printer_snum(p, handle, &snum, NULL) )
2694 return WERR_BADFID;
2696 if (!interpret_string_addr(&client_ss,
2697 p->conn->client_address,
2698 AI_NUMERICHOST)) {
2699 return WERR_SERVER_UNAVAILABLE;
2702 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2703 Printer->notify.printerlocal, 1,
2704 &Printer->notify.client_hnd, &client_ss))
2705 return WERR_SERVER_UNAVAILABLE;
2707 Printer->notify.client_connected=True;
2709 return WERR_OK;
2712 /*******************************************************************
2713 * fill a notify_info_data with the servername
2714 ********************************************************************/
2716 void spoolss_notify_server_name(int snum,
2717 SPOOL_NOTIFY_INFO_DATA *data,
2718 print_queue_struct *queue,
2719 NT_PRINTER_INFO_LEVEL *printer,
2720 TALLOC_CTX *mem_ctx)
2722 pstring temp;
2723 uint32 len;
2725 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2727 data->notify_data.data.length = len;
2728 if (len) {
2729 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2730 if (!data->notify_data.data.string) {
2731 data->notify_data.data.length = 0;
2732 return;
2735 memcpy(data->notify_data.data.string, temp, len);
2736 } else {
2737 data->notify_data.data.string = NULL;
2741 /*******************************************************************
2742 * fill a notify_info_data with the printername (not including the servername).
2743 ********************************************************************/
2745 void spoolss_notify_printer_name(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 /* the notify name should not contain the \\server\ part */
2755 char *p = strrchr(printer->info_2->printername, '\\');
2757 if (!p) {
2758 p = printer->info_2->printername;
2759 } else {
2760 p++;
2763 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2765 data->notify_data.data.length = len;
2766 if (len) {
2767 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2768 if (!data->notify_data.data.string) {
2769 data->notify_data.data.length = 0;
2770 return;
2772 memcpy(data->notify_data.data.string, temp, len);
2773 } else {
2774 data->notify_data.data.string = NULL;
2778 /*******************************************************************
2779 * fill a notify_info_data with the servicename
2780 ********************************************************************/
2782 void spoolss_notify_share_name(int snum,
2783 SPOOL_NOTIFY_INFO_DATA *data,
2784 print_queue_struct *queue,
2785 NT_PRINTER_INFO_LEVEL *printer,
2786 TALLOC_CTX *mem_ctx)
2788 pstring temp;
2789 uint32 len;
2791 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2793 data->notify_data.data.length = len;
2794 if (len) {
2795 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2796 if (!data->notify_data.data.string) {
2797 data->notify_data.data.length = 0;
2798 return;
2800 memcpy(data->notify_data.data.string, temp, len);
2801 } else {
2802 data->notify_data.data.string = NULL;
2807 /*******************************************************************
2808 * fill a notify_info_data with the port name
2809 ********************************************************************/
2811 void spoolss_notify_port_name(int snum,
2812 SPOOL_NOTIFY_INFO_DATA *data,
2813 print_queue_struct *queue,
2814 NT_PRINTER_INFO_LEVEL *printer,
2815 TALLOC_CTX *mem_ctx)
2817 pstring temp;
2818 uint32 len;
2820 /* even if it's strange, that's consistant in all the code */
2822 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2824 data->notify_data.data.length = len;
2825 if (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);
2834 } else {
2835 data->notify_data.data.string = NULL;
2839 /*******************************************************************
2840 * fill a notify_info_data with the printername
2841 * but it doesn't exist, have to see what to do
2842 ********************************************************************/
2844 void spoolss_notify_driver_name(int snum,
2845 SPOOL_NOTIFY_INFO_DATA *data,
2846 print_queue_struct *queue,
2847 NT_PRINTER_INFO_LEVEL *printer,
2848 TALLOC_CTX *mem_ctx)
2850 pstring temp;
2851 uint32 len;
2853 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2855 data->notify_data.data.length = len;
2856 if (len) {
2857 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2859 if (!data->notify_data.data.string) {
2860 data->notify_data.data.length = 0;
2861 return;
2864 memcpy(data->notify_data.data.string, temp, len);
2865 } else {
2866 data->notify_data.data.string = NULL;
2870 /*******************************************************************
2871 * fill a notify_info_data with the comment
2872 ********************************************************************/
2874 void spoolss_notify_comment(int snum,
2875 SPOOL_NOTIFY_INFO_DATA *data,
2876 print_queue_struct *queue,
2877 NT_PRINTER_INFO_LEVEL *printer,
2878 TALLOC_CTX *mem_ctx)
2880 pstring temp;
2881 uint32 len;
2883 if (*printer->info_2->comment == '\0')
2884 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2885 else
2886 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2888 data->notify_data.data.length = len;
2889 if (len) {
2890 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2892 if (!data->notify_data.data.string) {
2893 data->notify_data.data.length = 0;
2894 return;
2897 memcpy(data->notify_data.data.string, temp, len);
2898 } else {
2899 data->notify_data.data.string = NULL;
2903 /*******************************************************************
2904 * fill a notify_info_data with the comment
2905 * location = "Room 1, floor 2, building 3"
2906 ********************************************************************/
2908 void spoolss_notify_location(int snum,
2909 SPOOL_NOTIFY_INFO_DATA *data,
2910 print_queue_struct *queue,
2911 NT_PRINTER_INFO_LEVEL *printer,
2912 TALLOC_CTX *mem_ctx)
2914 pstring temp;
2915 uint32 len;
2917 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2919 data->notify_data.data.length = len;
2920 if (len) {
2921 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2923 if (!data->notify_data.data.string) {
2924 data->notify_data.data.length = 0;
2925 return;
2928 memcpy(data->notify_data.data.string, temp, len);
2929 } else {
2930 data->notify_data.data.string = NULL;
2934 /*******************************************************************
2935 * fill a notify_info_data with the device mode
2936 * jfm:xxxx don't to it for know but that's a real problem !!!
2937 ********************************************************************/
2939 static void spoolss_notify_devmode(int snum,
2940 SPOOL_NOTIFY_INFO_DATA *data,
2941 print_queue_struct *queue,
2942 NT_PRINTER_INFO_LEVEL *printer,
2943 TALLOC_CTX *mem_ctx)
2945 /* for a dummy implementation we have to zero the fields */
2946 data->notify_data.data.length = 0;
2947 data->notify_data.data.string = NULL;
2950 /*******************************************************************
2951 * fill a notify_info_data with the separator file name
2952 ********************************************************************/
2954 void spoolss_notify_sepfile(int snum,
2955 SPOOL_NOTIFY_INFO_DATA *data,
2956 print_queue_struct *queue,
2957 NT_PRINTER_INFO_LEVEL *printer,
2958 TALLOC_CTX *mem_ctx)
2960 pstring temp;
2961 uint32 len;
2963 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2965 data->notify_data.data.length = len;
2966 if (len) {
2967 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2969 if (!data->notify_data.data.string) {
2970 data->notify_data.data.length = 0;
2971 return;
2974 memcpy(data->notify_data.data.string, temp, len);
2975 } else {
2976 data->notify_data.data.string = NULL;
2980 /*******************************************************************
2981 * fill a notify_info_data with the print processor
2982 * jfm:xxxx return always winprint to indicate we don't do anything to it
2983 ********************************************************************/
2985 void spoolss_notify_print_processor(int snum,
2986 SPOOL_NOTIFY_INFO_DATA *data,
2987 print_queue_struct *queue,
2988 NT_PRINTER_INFO_LEVEL *printer,
2989 TALLOC_CTX *mem_ctx)
2991 pstring temp;
2992 uint32 len;
2994 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2996 data->notify_data.data.length = len;
2997 if (len) {
2998 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3000 if (!data->notify_data.data.string) {
3001 data->notify_data.data.length = 0;
3002 return;
3005 memcpy(data->notify_data.data.string, temp, len);
3006 } else {
3007 data->notify_data.data.string = NULL;
3011 /*******************************************************************
3012 * fill a notify_info_data with the print processor options
3013 * jfm:xxxx send an empty string
3014 ********************************************************************/
3016 void spoolss_notify_parameters(int snum,
3017 SPOOL_NOTIFY_INFO_DATA *data,
3018 print_queue_struct *queue,
3019 NT_PRINTER_INFO_LEVEL *printer,
3020 TALLOC_CTX *mem_ctx)
3022 pstring temp;
3023 uint32 len;
3025 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3027 data->notify_data.data.length = len;
3028 if (len) {
3029 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3031 if (!data->notify_data.data.string) {
3032 data->notify_data.data.length = 0;
3033 return;
3036 memcpy(data->notify_data.data.string, temp, len);
3037 } else {
3038 data->notify_data.data.string = NULL;
3042 /*******************************************************************
3043 * fill a notify_info_data with the data type
3044 * jfm:xxxx always send RAW as data type
3045 ********************************************************************/
3047 void spoolss_notify_datatype(int snum,
3048 SPOOL_NOTIFY_INFO_DATA *data,
3049 print_queue_struct *queue,
3050 NT_PRINTER_INFO_LEVEL *printer,
3051 TALLOC_CTX *mem_ctx)
3053 pstring temp;
3054 uint32 len;
3056 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3058 data->notify_data.data.length = len;
3059 if (len) {
3060 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3062 if (!data->notify_data.data.string) {
3063 data->notify_data.data.length = 0;
3064 return;
3067 memcpy(data->notify_data.data.string, temp, len);
3068 } else {
3069 data->notify_data.data.string = NULL;
3073 /*******************************************************************
3074 * fill a notify_info_data with the security descriptor
3075 * jfm:xxxx send an null pointer to say no security desc
3076 * have to implement security before !
3077 ********************************************************************/
3079 static void spoolss_notify_security_desc(int snum,
3080 SPOOL_NOTIFY_INFO_DATA *data,
3081 print_queue_struct *queue,
3082 NT_PRINTER_INFO_LEVEL *printer,
3083 TALLOC_CTX *mem_ctx)
3085 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3086 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3089 /*******************************************************************
3090 * fill a notify_info_data with the attributes
3091 * jfm:xxxx a samba printer is always shared
3092 ********************************************************************/
3094 void spoolss_notify_attributes(int snum,
3095 SPOOL_NOTIFY_INFO_DATA *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 data->notify_data.value[0] = printer->info_2->attributes;
3101 data->notify_data.value[1] = 0;
3104 /*******************************************************************
3105 * fill a notify_info_data with the priority
3106 ********************************************************************/
3108 static void spoolss_notify_priority(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 data->notify_data.value[0] = printer->info_2->priority;
3115 data->notify_data.value[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the default priority
3120 ********************************************************************/
3122 static void spoolss_notify_default_priority(int snum,
3123 SPOOL_NOTIFY_INFO_DATA *data,
3124 print_queue_struct *queue,
3125 NT_PRINTER_INFO_LEVEL *printer,
3126 TALLOC_CTX *mem_ctx)
3128 data->notify_data.value[0] = printer->info_2->default_priority;
3129 data->notify_data.value[1] = 0;
3132 /*******************************************************************
3133 * fill a notify_info_data with the start time
3134 ********************************************************************/
3136 static void spoolss_notify_start_time(int snum,
3137 SPOOL_NOTIFY_INFO_DATA *data,
3138 print_queue_struct *queue,
3139 NT_PRINTER_INFO_LEVEL *printer,
3140 TALLOC_CTX *mem_ctx)
3142 data->notify_data.value[0] = printer->info_2->starttime;
3143 data->notify_data.value[1] = 0;
3146 /*******************************************************************
3147 * fill a notify_info_data with the until time
3148 ********************************************************************/
3150 static void spoolss_notify_until_time(int snum,
3151 SPOOL_NOTIFY_INFO_DATA *data,
3152 print_queue_struct *queue,
3153 NT_PRINTER_INFO_LEVEL *printer,
3154 TALLOC_CTX *mem_ctx)
3156 data->notify_data.value[0] = printer->info_2->untiltime;
3157 data->notify_data.value[1] = 0;
3160 /*******************************************************************
3161 * fill a notify_info_data with the status
3162 ********************************************************************/
3164 static void spoolss_notify_status(int snum,
3165 SPOOL_NOTIFY_INFO_DATA *data,
3166 print_queue_struct *queue,
3167 NT_PRINTER_INFO_LEVEL *printer,
3168 TALLOC_CTX *mem_ctx)
3170 print_status_struct status;
3172 print_queue_length(snum, &status);
3173 data->notify_data.value[0]=(uint32) status.status;
3174 data->notify_data.value[1] = 0;
3177 /*******************************************************************
3178 * fill a notify_info_data with the number of jobs queued
3179 ********************************************************************/
3181 void spoolss_notify_cjobs(int snum,
3182 SPOOL_NOTIFY_INFO_DATA *data,
3183 print_queue_struct *queue,
3184 NT_PRINTER_INFO_LEVEL *printer,
3185 TALLOC_CTX *mem_ctx)
3187 data->notify_data.value[0] = print_queue_length(snum, NULL);
3188 data->notify_data.value[1] = 0;
3191 /*******************************************************************
3192 * fill a notify_info_data with the average ppm
3193 ********************************************************************/
3195 static void spoolss_notify_average_ppm(int snum,
3196 SPOOL_NOTIFY_INFO_DATA *data,
3197 print_queue_struct *queue,
3198 NT_PRINTER_INFO_LEVEL *printer,
3199 TALLOC_CTX *mem_ctx)
3201 /* always respond 8 pages per minutes */
3202 /* a little hard ! */
3203 data->notify_data.value[0] = printer->info_2->averageppm;
3204 data->notify_data.value[1] = 0;
3207 /*******************************************************************
3208 * fill a notify_info_data with username
3209 ********************************************************************/
3211 static void spoolss_notify_username(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 pstring temp;
3218 uint32 len;
3220 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3222 data->notify_data.data.length = len;
3223 if (len) {
3224 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3226 if (!data->notify_data.data.string) {
3227 data->notify_data.data.length = 0;
3228 return;
3231 memcpy(data->notify_data.data.string, temp, len);
3232 } else {
3233 data->notify_data.data.string = NULL;
3237 /*******************************************************************
3238 * fill a notify_info_data with job status
3239 ********************************************************************/
3241 static void spoolss_notify_job_status(int snum,
3242 SPOOL_NOTIFY_INFO_DATA *data,
3243 print_queue_struct *queue,
3244 NT_PRINTER_INFO_LEVEL *printer,
3245 TALLOC_CTX *mem_ctx)
3247 data->notify_data.value[0]=nt_printj_status(queue->status);
3248 data->notify_data.value[1] = 0;
3251 /*******************************************************************
3252 * fill a notify_info_data with job name
3253 ********************************************************************/
3255 static void spoolss_notify_job_name(int snum,
3256 SPOOL_NOTIFY_INFO_DATA *data,
3257 print_queue_struct *queue,
3258 NT_PRINTER_INFO_LEVEL *printer,
3259 TALLOC_CTX *mem_ctx)
3261 pstring temp;
3262 uint32 len;
3264 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3266 data->notify_data.data.length = len;
3267 if (len) {
3268 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3270 if (!data->notify_data.data.string) {
3271 data->notify_data.data.length = 0;
3272 return;
3275 memcpy(data->notify_data.data.string, temp, len);
3276 } else {
3277 data->notify_data.data.string = NULL;
3281 /*******************************************************************
3282 * fill a notify_info_data with job status
3283 ********************************************************************/
3285 static void spoolss_notify_job_status_string(int snum,
3286 SPOOL_NOTIFY_INFO_DATA *data,
3287 print_queue_struct *queue,
3288 NT_PRINTER_INFO_LEVEL *printer,
3289 TALLOC_CTX *mem_ctx)
3292 * Now we're returning job status codes we just return a "" here. JRA.
3295 const char *p = "";
3296 pstring temp;
3297 uint32 len;
3299 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3300 p = "unknown";
3302 switch (queue->status) {
3303 case LPQ_QUEUED:
3304 p = "Queued";
3305 break;
3306 case LPQ_PAUSED:
3307 p = ""; /* NT provides the paused string */
3308 break;
3309 case LPQ_SPOOLING:
3310 p = "Spooling";
3311 break;
3312 case LPQ_PRINTING:
3313 p = "Printing";
3314 break;
3316 #endif /* NO LONGER NEEDED. */
3318 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3320 data->notify_data.data.length = len;
3321 if (len) {
3322 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3324 if (!data->notify_data.data.string) {
3325 data->notify_data.data.length = 0;
3326 return;
3329 memcpy(data->notify_data.data.string, temp, len);
3330 } else {
3331 data->notify_data.data.string = NULL;
3335 /*******************************************************************
3336 * fill a notify_info_data with job time
3337 ********************************************************************/
3339 static void spoolss_notify_job_time(int snum,
3340 SPOOL_NOTIFY_INFO_DATA *data,
3341 print_queue_struct *queue,
3342 NT_PRINTER_INFO_LEVEL *printer,
3343 TALLOC_CTX *mem_ctx)
3345 data->notify_data.value[0]=0x0;
3346 data->notify_data.value[1]=0;
3349 /*******************************************************************
3350 * fill a notify_info_data with job size
3351 ********************************************************************/
3353 static void spoolss_notify_job_size(int snum,
3354 SPOOL_NOTIFY_INFO_DATA *data,
3355 print_queue_struct *queue,
3356 NT_PRINTER_INFO_LEVEL *printer,
3357 TALLOC_CTX *mem_ctx)
3359 data->notify_data.value[0]=queue->size;
3360 data->notify_data.value[1]=0;
3363 /*******************************************************************
3364 * fill a notify_info_data with page info
3365 ********************************************************************/
3366 static void spoolss_notify_total_pages(int snum,
3367 SPOOL_NOTIFY_INFO_DATA *data,
3368 print_queue_struct *queue,
3369 NT_PRINTER_INFO_LEVEL *printer,
3370 TALLOC_CTX *mem_ctx)
3372 data->notify_data.value[0]=queue->page_count;
3373 data->notify_data.value[1]=0;
3376 /*******************************************************************
3377 * fill a notify_info_data with pages printed info.
3378 ********************************************************************/
3379 static void spoolss_notify_pages_printed(int snum,
3380 SPOOL_NOTIFY_INFO_DATA *data,
3381 print_queue_struct *queue,
3382 NT_PRINTER_INFO_LEVEL *printer,
3383 TALLOC_CTX *mem_ctx)
3385 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3386 data->notify_data.value[1]=0;
3389 /*******************************************************************
3390 Fill a notify_info_data with job position.
3391 ********************************************************************/
3393 static void spoolss_notify_job_position(int snum,
3394 SPOOL_NOTIFY_INFO_DATA *data,
3395 print_queue_struct *queue,
3396 NT_PRINTER_INFO_LEVEL *printer,
3397 TALLOC_CTX *mem_ctx)
3399 data->notify_data.value[0]=queue->job;
3400 data->notify_data.value[1]=0;
3403 /*******************************************************************
3404 Fill a notify_info_data with submitted time.
3405 ********************************************************************/
3407 static void spoolss_notify_submitted_time(int snum,
3408 SPOOL_NOTIFY_INFO_DATA *data,
3409 print_queue_struct *queue,
3410 NT_PRINTER_INFO_LEVEL *printer,
3411 TALLOC_CTX *mem_ctx)
3413 struct tm *t;
3414 uint32 len;
3415 SYSTEMTIME st;
3416 char *p;
3418 t=gmtime(&queue->time);
3420 len = sizeof(SYSTEMTIME);
3422 data->notify_data.data.length = len;
3423 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3425 if (!data->notify_data.data.string) {
3426 data->notify_data.data.length = 0;
3427 return;
3430 make_systemtime(&st, t);
3433 * Systemtime must be linearized as a set of UINT16's.
3434 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3437 p = (char *)data->notify_data.data.string;
3438 SSVAL(p, 0, st.year);
3439 SSVAL(p, 2, st.month);
3440 SSVAL(p, 4, st.dayofweek);
3441 SSVAL(p, 6, st.day);
3442 SSVAL(p, 8, st.hour);
3443 SSVAL(p, 10, st.minute);
3444 SSVAL(p, 12, st.second);
3445 SSVAL(p, 14, st.milliseconds);
3448 struct s_notify_info_data_table
3450 uint16 type;
3451 uint16 field;
3452 const char *name;
3453 uint32 size;
3454 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3455 print_queue_struct *queue,
3456 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3459 /* A table describing the various print notification constants and
3460 whether the notification data is a pointer to a variable sized
3461 buffer, a one value uint32 or a two value uint32. */
3463 static const struct s_notify_info_data_table notify_info_data_table[] =
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3489 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3490 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3511 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3512 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3513 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3514 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3517 /*******************************************************************
3518 Return the size of info_data structure.
3519 ********************************************************************/
3521 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3523 int i=0;
3525 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3526 if ( (notify_info_data_table[i].type == type)
3527 && (notify_info_data_table[i].field == field) ) {
3528 switch(notify_info_data_table[i].size) {
3529 case NOTIFY_ONE_VALUE:
3530 case NOTIFY_TWO_VALUE:
3531 return 1;
3532 case NOTIFY_STRING:
3533 return 2;
3535 /* The only pointer notify data I have seen on
3536 the wire is the submitted time and this has
3537 the notify size set to 4. -tpot */
3539 case NOTIFY_POINTER:
3540 return 4;
3542 case NOTIFY_SECDESC:
3543 return 5;
3548 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3550 return 0;
3553 /*******************************************************************
3554 Return the type of notify_info_data.
3555 ********************************************************************/
3557 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3559 uint32 i=0;
3561 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3562 if (notify_info_data_table[i].type == type &&
3563 notify_info_data_table[i].field == field)
3564 return notify_info_data_table[i].size;
3567 return 0;
3570 /****************************************************************************
3571 ****************************************************************************/
3573 static bool search_notify(uint16 type, uint16 field, int *value)
3575 int i;
3577 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3578 if (notify_info_data_table[i].type == type &&
3579 notify_info_data_table[i].field == field &&
3580 notify_info_data_table[i].fn != NULL) {
3581 *value = i;
3582 return True;
3586 return False;
3589 /****************************************************************************
3590 ****************************************************************************/
3592 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3594 info_data->type = type;
3595 info_data->field = field;
3596 info_data->reserved = 0;
3598 info_data->size = size_of_notify_info_data(type, field);
3599 info_data->enc_type = type_of_notify_info_data(type, field);
3601 info_data->id = id;
3604 /*******************************************************************
3606 * fill a notify_info struct with info asked
3608 ********************************************************************/
3610 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3611 snum, SPOOL_NOTIFY_OPTION_TYPE
3612 *option_type, uint32 id,
3613 TALLOC_CTX *mem_ctx)
3615 int field_num,j;
3616 uint16 type;
3617 uint16 field;
3619 SPOOL_NOTIFY_INFO_DATA *current_data;
3620 NT_PRINTER_INFO_LEVEL *printer = NULL;
3621 print_queue_struct *queue=NULL;
3623 type=option_type->type;
3625 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3626 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3627 option_type->count, lp_servicename(snum)));
3629 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3630 return False;
3632 for(field_num=0; field_num<option_type->count; field_num++) {
3633 field = option_type->fields[field_num];
3635 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3637 if (!search_notify(type, field, &j) )
3638 continue;
3640 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3641 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3642 free_a_printer(&printer, 2);
3643 return False;
3646 current_data = &info->data[info->count];
3648 construct_info_data(current_data, type, field, id);
3650 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3651 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3653 notify_info_data_table[j].fn(snum, current_data, queue,
3654 printer, mem_ctx);
3656 info->count++;
3659 free_a_printer(&printer, 2);
3660 return True;
3663 /*******************************************************************
3665 * fill a notify_info struct with info asked
3667 ********************************************************************/
3669 static bool construct_notify_jobs_info(print_queue_struct *queue,
3670 SPOOL_NOTIFY_INFO *info,
3671 NT_PRINTER_INFO_LEVEL *printer,
3672 int snum, SPOOL_NOTIFY_OPTION_TYPE
3673 *option_type, uint32 id,
3674 TALLOC_CTX *mem_ctx)
3676 int field_num,j;
3677 uint16 type;
3678 uint16 field;
3680 SPOOL_NOTIFY_INFO_DATA *current_data;
3682 DEBUG(4,("construct_notify_jobs_info\n"));
3684 type = option_type->type;
3686 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3687 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3688 option_type->count));
3690 for(field_num=0; field_num<option_type->count; field_num++) {
3691 field = option_type->fields[field_num];
3693 if (!search_notify(type, field, &j) )
3694 continue;
3696 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3697 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3698 return False;
3701 current_data=&(info->data[info->count]);
3703 construct_info_data(current_data, type, field, id);
3704 notify_info_data_table[j].fn(snum, current_data, queue,
3705 printer, mem_ctx);
3706 info->count++;
3709 return True;
3713 * JFM: The enumeration is not that simple, it's even non obvious.
3715 * let's take an example: I want to monitor the PRINTER SERVER for
3716 * the printer's name and the number of jobs currently queued.
3717 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3718 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3720 * I have 3 printers on the back of my server.
3722 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3723 * structures.
3724 * Number Data Id
3725 * 1 printer 1 name 1
3726 * 2 printer 1 cjob 1
3727 * 3 printer 2 name 2
3728 * 4 printer 2 cjob 2
3729 * 5 printer 3 name 3
3730 * 6 printer 3 name 3
3732 * that's the print server case, the printer case is even worse.
3735 /*******************************************************************
3737 * enumerate all printers on the printserver
3738 * fill a notify_info struct with info asked
3740 ********************************************************************/
3742 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3743 SPOOL_NOTIFY_INFO *info,
3744 TALLOC_CTX *mem_ctx)
3746 int snum;
3747 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3748 int n_services=lp_numservices();
3749 int i;
3750 SPOOL_NOTIFY_OPTION *option;
3751 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3753 DEBUG(4,("printserver_notify_info\n"));
3755 if (!Printer)
3756 return WERR_BADFID;
3758 option=Printer->notify.option;
3759 info->version=2;
3760 info->data=NULL;
3761 info->count=0;
3763 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3764 sending a ffpcn() request first */
3766 if ( !option )
3767 return WERR_BADFID;
3769 for (i=0; i<option->count; i++) {
3770 option_type=&(option->ctr.type[i]);
3772 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3773 continue;
3775 for (snum=0; snum<n_services; snum++)
3777 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3778 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3782 #if 0
3784 * Debugging information, don't delete.
3787 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3788 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3789 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3791 for (i=0; i<info->count; i++) {
3792 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3793 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3794 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3796 #endif
3798 return WERR_OK;
3801 /*******************************************************************
3803 * fill a notify_info struct with info asked
3805 ********************************************************************/
3807 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3808 TALLOC_CTX *mem_ctx)
3810 int snum;
3811 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3812 int i;
3813 uint32 id;
3814 SPOOL_NOTIFY_OPTION *option;
3815 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3816 int count,j;
3817 print_queue_struct *queue=NULL;
3818 print_status_struct status;
3820 DEBUG(4,("printer_notify_info\n"));
3822 if (!Printer)
3823 return WERR_BADFID;
3825 option=Printer->notify.option;
3826 id = 0x0;
3827 info->version=2;
3828 info->data=NULL;
3829 info->count=0;
3831 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3832 sending a ffpcn() request first */
3834 if ( !option )
3835 return WERR_BADFID;
3837 get_printer_snum(p, hnd, &snum, NULL);
3839 for (i=0; i<option->count; i++) {
3840 option_type=&option->ctr.type[i];
3842 switch ( option_type->type ) {
3843 case PRINTER_NOTIFY_TYPE:
3844 if(construct_notify_printer_info(Printer, info, snum,
3845 option_type, id,
3846 mem_ctx))
3847 id--;
3848 break;
3850 case JOB_NOTIFY_TYPE: {
3851 NT_PRINTER_INFO_LEVEL *printer = NULL;
3853 count = print_queue_status(snum, &queue, &status);
3855 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3856 goto done;
3858 for (j=0; j<count; j++) {
3859 construct_notify_jobs_info(&queue[j], info,
3860 printer, snum,
3861 option_type,
3862 queue[j].job,
3863 mem_ctx);
3866 free_a_printer(&printer, 2);
3868 done:
3869 SAFE_FREE(queue);
3870 break;
3876 * Debugging information, don't delete.
3879 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3880 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3881 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3883 for (i=0; i<info->count; i++) {
3884 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3885 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3886 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3889 return WERR_OK;
3892 /********************************************************************
3893 * spoolss_rfnpcnex
3894 ********************************************************************/
3896 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3898 POLICY_HND *handle = &q_u->handle;
3899 SPOOL_NOTIFY_INFO *info = &r_u->info;
3901 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3902 WERROR result = WERR_BADFID;
3904 /* we always have a NOTIFY_INFO struct */
3905 r_u->info_ptr=0x1;
3907 if (!Printer) {
3908 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3909 OUR_HANDLE(handle)));
3910 goto done;
3913 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3916 * We are now using the change value, and
3917 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3918 * I don't have a global notification system, I'm sending back all the
3919 * informations even when _NOTHING_ has changed.
3922 /* We need to keep track of the change value to send back in
3923 RRPCN replies otherwise our updates are ignored. */
3925 Printer->notify.fnpcn = True;
3927 if (Printer->notify.client_connected) {
3928 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3929 Printer->notify.change = q_u->change;
3932 /* just ignore the SPOOL_NOTIFY_OPTION */
3934 switch (Printer->printer_type) {
3935 case SPLHND_SERVER:
3936 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3937 break;
3939 case SPLHND_PRINTER:
3940 result = printer_notify_info(p, handle, info, p->mem_ctx);
3941 break;
3944 Printer->notify.fnpcn = False;
3946 done:
3947 return result;
3950 /********************************************************************
3951 * construct_printer_info_0
3952 * fill a printer_info_0 struct
3953 ********************************************************************/
3955 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3957 pstring chaine;
3958 int count;
3959 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3960 counter_printer_0 *session_counter;
3961 uint32 global_counter;
3962 struct tm *t;
3963 time_t setuptime;
3964 print_status_struct status;
3966 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3967 return False;
3969 count = print_queue_length(snum, &status);
3971 /* check if we already have a counter for this printer */
3972 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3973 if (session_counter->snum == snum)
3974 break;
3977 /* it's the first time, add it to the list */
3978 if (session_counter==NULL) {
3979 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3980 free_a_printer(&ntprinter, 2);
3981 return False;
3983 ZERO_STRUCTP(session_counter);
3984 session_counter->snum=snum;
3985 session_counter->counter=0;
3986 DLIST_ADD(counter_list, session_counter);
3989 /* increment it */
3990 session_counter->counter++;
3992 /* JFM:
3993 * the global_counter should be stored in a TDB as it's common to all the clients
3994 * and should be zeroed on samba startup
3996 global_counter=session_counter->counter;
3998 pstrcpy(chaine,ntprinter->info_2->printername);
4000 init_unistr(&printer->printername, chaine);
4002 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
4003 init_unistr(&printer->servername, chaine);
4005 printer->cjobs = count;
4006 printer->total_jobs = 0;
4007 printer->total_bytes = 0;
4009 setuptime = (time_t)ntprinter->info_2->setuptime;
4010 t=gmtime(&setuptime);
4012 printer->year = t->tm_year+1900;
4013 printer->month = t->tm_mon+1;
4014 printer->dayofweek = t->tm_wday;
4015 printer->day = t->tm_mday;
4016 printer->hour = t->tm_hour;
4017 printer->minute = t->tm_min;
4018 printer->second = t->tm_sec;
4019 printer->milliseconds = 0;
4021 printer->global_counter = global_counter;
4022 printer->total_pages = 0;
4024 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4025 printer->major_version = 0x0005; /* NT 5 */
4026 printer->build_version = 0x0893; /* build 2195 */
4028 printer->unknown7 = 0x1;
4029 printer->unknown8 = 0x0;
4030 printer->unknown9 = 0x0;
4031 printer->session_counter = session_counter->counter;
4032 printer->unknown11 = 0x0;
4033 printer->printer_errors = 0x0; /* number of print failure */
4034 printer->unknown13 = 0x0;
4035 printer->unknown14 = 0x1;
4036 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4037 printer->unknown16 = 0x0;
4038 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4039 printer->unknown18 = 0x0;
4040 printer->status = nt_printq_status(status.status);
4041 printer->unknown20 = 0x0;
4042 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4043 printer->unknown22 = 0x0;
4044 printer->unknown23 = 0x6; /* 6 ???*/
4045 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4046 printer->unknown25 = 0;
4047 printer->unknown26 = 0;
4048 printer->unknown27 = 0;
4049 printer->unknown28 = 0;
4050 printer->unknown29 = 0;
4052 free_a_printer(&ntprinter,2);
4053 return (True);
4056 /********************************************************************
4057 * construct_printer_info_1
4058 * fill a printer_info_1 struct
4059 ********************************************************************/
4060 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4062 pstring chaine;
4063 pstring chaine2;
4064 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4066 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4067 return False;
4069 printer->flags=flags;
4071 if (*ntprinter->info_2->comment == '\0') {
4072 init_unistr(&printer->comment, lp_comment(snum));
4073 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4074 ntprinter->info_2->drivername, lp_comment(snum));
4076 else {
4077 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4078 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4079 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4082 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4084 init_unistr(&printer->description, chaine);
4085 init_unistr(&printer->name, chaine2);
4087 free_a_printer(&ntprinter,2);
4089 return True;
4092 /****************************************************************************
4093 Free a DEVMODE struct.
4094 ****************************************************************************/
4096 static void free_dev_mode(DEVICEMODE *dev)
4098 if (dev == NULL)
4099 return;
4101 SAFE_FREE(dev->dev_private);
4102 SAFE_FREE(dev);
4106 /****************************************************************************
4107 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4108 should be valid upon entry
4109 ****************************************************************************/
4111 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4113 if ( !devmode || !ntdevmode )
4114 return False;
4116 init_unistr(&devmode->devicename, ntdevmode->devicename);
4118 init_unistr(&devmode->formname, ntdevmode->formname);
4120 devmode->specversion = ntdevmode->specversion;
4121 devmode->driverversion = ntdevmode->driverversion;
4122 devmode->size = ntdevmode->size;
4123 devmode->driverextra = ntdevmode->driverextra;
4124 devmode->fields = ntdevmode->fields;
4126 devmode->orientation = ntdevmode->orientation;
4127 devmode->papersize = ntdevmode->papersize;
4128 devmode->paperlength = ntdevmode->paperlength;
4129 devmode->paperwidth = ntdevmode->paperwidth;
4130 devmode->scale = ntdevmode->scale;
4131 devmode->copies = ntdevmode->copies;
4132 devmode->defaultsource = ntdevmode->defaultsource;
4133 devmode->printquality = ntdevmode->printquality;
4134 devmode->color = ntdevmode->color;
4135 devmode->duplex = ntdevmode->duplex;
4136 devmode->yresolution = ntdevmode->yresolution;
4137 devmode->ttoption = ntdevmode->ttoption;
4138 devmode->collate = ntdevmode->collate;
4139 devmode->icmmethod = ntdevmode->icmmethod;
4140 devmode->icmintent = ntdevmode->icmintent;
4141 devmode->mediatype = ntdevmode->mediatype;
4142 devmode->dithertype = ntdevmode->dithertype;
4144 if (ntdevmode->nt_dev_private != NULL) {
4145 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4146 return False;
4149 return True;
4152 /****************************************************************************
4153 Create a DEVMODE struct. Returns malloced memory.
4154 ****************************************************************************/
4156 DEVICEMODE *construct_dev_mode(const char *servicename)
4158 NT_PRINTER_INFO_LEVEL *printer = NULL;
4159 DEVICEMODE *devmode = NULL;
4161 DEBUG(7,("construct_dev_mode\n"));
4163 DEBUGADD(8,("getting printer characteristics\n"));
4165 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4166 return NULL;
4168 if ( !printer->info_2->devmode ) {
4169 DEBUG(5, ("BONG! There was no device mode!\n"));
4170 goto done;
4173 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4174 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4175 goto done;
4178 ZERO_STRUCTP(devmode);
4180 DEBUGADD(8,("loading DEVICEMODE\n"));
4182 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4183 free_dev_mode( devmode );
4184 devmode = NULL;
4187 done:
4188 free_a_printer(&printer,2);
4190 return devmode;
4193 /********************************************************************
4194 * construct_printer_info_2
4195 * fill a printer_info_2 struct
4196 ********************************************************************/
4198 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4200 int count;
4201 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4203 print_status_struct status;
4205 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4206 return False;
4208 count = print_queue_length(snum, &status);
4210 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4211 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4212 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4213 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4214 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4216 if (*ntprinter->info_2->comment == '\0')
4217 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4218 else
4219 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4221 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4222 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4223 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4224 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4225 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4227 printer->attributes = ntprinter->info_2->attributes;
4229 printer->priority = ntprinter->info_2->priority; /* priority */
4230 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4231 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4232 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4233 printer->status = nt_printq_status(status.status); /* status */
4234 printer->cjobs = count; /* jobs */
4235 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4237 if ( !(printer->devmode = construct_dev_mode(
4238 lp_const_servicename(snum))) )
4239 DEBUG(8, ("Returning NULL Devicemode!\n"));
4241 printer->secdesc = NULL;
4243 if ( ntprinter->info_2->secdesc_buf
4244 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4246 /* don't use talloc_steal() here unless you do a deep steal of all
4247 the SEC_DESC members */
4249 printer->secdesc = dup_sec_desc( talloc_tos(),
4250 ntprinter->info_2->secdesc_buf->sd );
4253 free_a_printer(&ntprinter, 2);
4255 return True;
4258 /********************************************************************
4259 * construct_printer_info_3
4260 * fill a printer_info_3 struct
4261 ********************************************************************/
4263 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4265 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4266 PRINTER_INFO_3 *printer = NULL;
4268 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4269 return False;
4271 *pp_printer = NULL;
4272 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4273 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4274 free_a_printer(&ntprinter, 2);
4275 return False;
4278 ZERO_STRUCTP(printer);
4280 /* These are the components of the SD we are returning. */
4282 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4283 /* don't use talloc_steal() here unless you do a deep steal of all
4284 the SEC_DESC members */
4286 printer->secdesc = dup_sec_desc( talloc_tos(),
4287 ntprinter->info_2->secdesc_buf->sd );
4290 free_a_printer(&ntprinter, 2);
4292 *pp_printer = printer;
4293 return True;
4296 /********************************************************************
4297 * construct_printer_info_4
4298 * fill a printer_info_4 struct
4299 ********************************************************************/
4301 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4303 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4305 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4306 return False;
4308 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4309 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4310 printer->attributes = ntprinter->info_2->attributes;
4312 free_a_printer(&ntprinter, 2);
4313 return True;
4316 /********************************************************************
4317 * construct_printer_info_5
4318 * fill a printer_info_5 struct
4319 ********************************************************************/
4321 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4323 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4325 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4326 return False;
4328 init_unistr(&printer->printername, ntprinter->info_2->printername);
4329 init_unistr(&printer->portname, ntprinter->info_2->portname);
4330 printer->attributes = ntprinter->info_2->attributes;
4332 /* these two are not used by NT+ according to MSDN */
4334 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4335 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4337 free_a_printer(&ntprinter, 2);
4339 return True;
4342 /********************************************************************
4343 * construct_printer_info_6
4344 * fill a printer_info_6 struct
4345 ********************************************************************/
4347 static bool construct_printer_info_6(Printer_entry *print_hnd,
4348 PRINTER_INFO_6 *printer,
4349 int snum)
4351 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4352 int count;
4353 print_status_struct status;
4355 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4356 lp_const_servicename(snum))))
4357 return False;
4359 count = print_queue_length(snum, &status);
4361 printer->status = nt_printq_status(status.status);
4363 free_a_printer(&ntprinter, 2);
4365 return True;
4368 /********************************************************************
4369 * construct_printer_info_7
4370 * fill a printer_info_7 struct
4371 ********************************************************************/
4373 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4375 char *guid_str = NULL;
4376 struct GUID guid;
4378 if (is_printer_published(print_hnd, snum, &guid)) {
4379 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4380 strupper_m(guid_str);
4381 init_unistr(&printer->guid, guid_str);
4382 printer->action = SPOOL_DS_PUBLISH;
4383 } else {
4384 init_unistr(&printer->guid, "");
4385 printer->action = SPOOL_DS_UNPUBLISH;
4388 return True;
4391 /********************************************************************
4392 Spoolss_enumprinters.
4393 ********************************************************************/
4395 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4397 int snum;
4398 int i;
4399 int n_services=lp_numservices();
4400 PRINTER_INFO_1 *printers=NULL;
4401 PRINTER_INFO_1 current_prt;
4402 WERROR result = WERR_OK;
4404 DEBUG(4,("enum_all_printers_info_1\n"));
4406 for (snum=0; snum<n_services; snum++) {
4407 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4408 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4410 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4411 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4412 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4413 *returned=0;
4414 return WERR_NOMEM;
4416 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4418 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4419 (*returned)++;
4424 /* check the required size. */
4425 for (i=0; i<*returned; i++)
4426 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4428 if (*needed > offered) {
4429 result = WERR_INSUFFICIENT_BUFFER;
4430 goto out;
4433 if (!rpcbuf_alloc_size(buffer, *needed)) {
4434 result = WERR_NOMEM;
4435 goto out;
4438 /* fill the buffer with the structures */
4439 for (i=0; i<*returned; i++)
4440 smb_io_printer_info_1("", buffer, &printers[i], 0);
4442 out:
4443 /* clear memory */
4445 SAFE_FREE(printers);
4447 if ( !W_ERROR_IS_OK(result) )
4448 *returned = 0;
4450 return result;
4453 /********************************************************************
4454 enum_all_printers_info_1_local.
4455 *********************************************************************/
4457 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4459 DEBUG(4,("enum_all_printers_info_1_local\n"));
4461 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4464 /********************************************************************
4465 enum_all_printers_info_1_name.
4466 *********************************************************************/
4468 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4470 char *s = name;
4472 DEBUG(4,("enum_all_printers_info_1_name\n"));
4474 if ((name[0] == '\\') && (name[1] == '\\'))
4475 s = name + 2;
4477 if (is_myname_or_ipaddr(s)) {
4478 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4480 else
4481 return WERR_INVALID_NAME;
4484 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4485 /********************************************************************
4486 enum_all_printers_info_1_remote.
4487 *********************************************************************/
4489 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4491 PRINTER_INFO_1 *printer;
4492 fstring printername;
4493 fstring desc;
4494 fstring comment;
4495 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4496 WERROR result = WERR_OK;
4498 /* JFM: currently it's more a place holder than anything else.
4499 * In the spooler world there is a notion of server registration.
4500 * the print servers are registered on the PDC (in the same domain)
4502 * We should have a TDB here. The registration is done thru an
4503 * undocumented RPC call.
4506 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4507 return WERR_NOMEM;
4509 *returned=1;
4511 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4512 slprintf(desc, sizeof(desc)-1,"%s", name);
4513 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4515 init_unistr(&printer->description, desc);
4516 init_unistr(&printer->name, printername);
4517 init_unistr(&printer->comment, comment);
4518 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4520 /* check the required size. */
4521 *needed += spoolss_size_printer_info_1(printer);
4523 if (*needed > offered) {
4524 result = WERR_INSUFFICIENT_BUFFER;
4525 goto out;
4528 if (!rpcbuf_alloc_size(buffer, *needed)) {
4529 result = WERR_NOMEM;
4530 goto out;
4533 /* fill the buffer with the structures */
4534 smb_io_printer_info_1("", buffer, printer, 0);
4536 out:
4537 /* clear memory */
4538 SAFE_FREE(printer);
4540 if ( !W_ERROR_IS_OK(result) )
4541 *returned = 0;
4543 return result;
4546 #endif
4548 /********************************************************************
4549 enum_all_printers_info_1_network.
4550 *********************************************************************/
4552 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4554 char *s = name;
4556 DEBUG(4,("enum_all_printers_info_1_network\n"));
4558 /* If we respond to a enum_printers level 1 on our name with flags
4559 set to PRINTER_ENUM_REMOTE with a list of printers then these
4560 printers incorrectly appear in the APW browse list.
4561 Specifically the printers for the server appear at the workgroup
4562 level where all the other servers in the domain are
4563 listed. Windows responds to this call with a
4564 WERR_CAN_NOT_COMPLETE so we should do the same. */
4566 if (name[0] == '\\' && name[1] == '\\')
4567 s = name + 2;
4569 if (is_myname_or_ipaddr(s))
4570 return WERR_CAN_NOT_COMPLETE;
4572 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4575 /********************************************************************
4576 * api_spoolss_enumprinters
4578 * called from api_spoolss_enumprinters (see this to understand)
4579 ********************************************************************/
4581 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4583 int snum;
4584 int i;
4585 int n_services=lp_numservices();
4586 PRINTER_INFO_2 *printers=NULL;
4587 PRINTER_INFO_2 current_prt;
4588 WERROR result = WERR_OK;
4590 *returned = 0;
4592 for (snum=0; snum<n_services; snum++) {
4593 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4594 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4596 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4597 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4598 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4599 *returned = 0;
4600 return WERR_NOMEM;
4603 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4605 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4607 (*returned)++;
4612 /* check the required size. */
4613 for (i=0; i<*returned; i++)
4614 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4616 if (*needed > offered) {
4617 result = WERR_INSUFFICIENT_BUFFER;
4618 goto out;
4621 if (!rpcbuf_alloc_size(buffer, *needed)) {
4622 result = WERR_NOMEM;
4623 goto out;
4626 /* fill the buffer with the structures */
4627 for (i=0; i<*returned; i++)
4628 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4630 out:
4631 /* clear memory */
4633 for (i=0; i<*returned; i++)
4634 free_devmode(printers[i].devmode);
4636 SAFE_FREE(printers);
4638 if ( !W_ERROR_IS_OK(result) )
4639 *returned = 0;
4641 return result;
4644 /********************************************************************
4645 * handle enumeration of printers at level 1
4646 ********************************************************************/
4648 static WERROR enumprinters_level1( uint32 flags, fstring name,
4649 RPC_BUFFER *buffer, uint32 offered,
4650 uint32 *needed, uint32 *returned)
4652 /* Not all the flags are equals */
4654 if (flags & PRINTER_ENUM_LOCAL)
4655 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4657 if (flags & PRINTER_ENUM_NAME)
4658 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4660 #if 0 /* JERRY - disabled for now */
4661 if (flags & PRINTER_ENUM_REMOTE)
4662 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4663 #endif
4665 if (flags & PRINTER_ENUM_NETWORK)
4666 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4668 return WERR_OK; /* NT4sp5 does that */
4671 /********************************************************************
4672 * handle enumeration of printers at level 2
4673 ********************************************************************/
4675 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4676 RPC_BUFFER *buffer, uint32 offered,
4677 uint32 *needed, uint32 *returned)
4679 char *s = servername;
4681 if (flags & PRINTER_ENUM_LOCAL) {
4682 return enum_all_printers_info_2(buffer, offered, needed, returned);
4685 if (flags & PRINTER_ENUM_NAME) {
4686 if ((servername[0] == '\\') && (servername[1] == '\\'))
4687 s = servername + 2;
4688 if (is_myname_or_ipaddr(s))
4689 return enum_all_printers_info_2(buffer, offered, needed, returned);
4690 else
4691 return WERR_INVALID_NAME;
4694 if (flags & PRINTER_ENUM_REMOTE)
4695 return WERR_UNKNOWN_LEVEL;
4697 return WERR_OK;
4700 /********************************************************************
4701 * handle enumeration of printers at level 5
4702 ********************************************************************/
4704 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4705 RPC_BUFFER *buffer, uint32 offered,
4706 uint32 *needed, uint32 *returned)
4708 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4709 return WERR_OK;
4712 /********************************************************************
4713 * api_spoolss_enumprinters
4715 * called from api_spoolss_enumprinters (see this to understand)
4716 ********************************************************************/
4718 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4720 uint32 flags = q_u->flags;
4721 UNISTR2 *servername = &q_u->servername;
4722 uint32 level = q_u->level;
4723 RPC_BUFFER *buffer = NULL;
4724 uint32 offered = q_u->offered;
4725 uint32 *needed = &r_u->needed;
4726 uint32 *returned = &r_u->returned;
4728 fstring name;
4730 /* that's an [in out] buffer */
4732 if (!q_u->buffer && (offered!=0)) {
4733 return WERR_INVALID_PARAM;
4736 rpcbuf_move(q_u->buffer, &r_u->buffer);
4737 buffer = r_u->buffer;
4739 DEBUG(4,("_spoolss_enumprinters\n"));
4741 *needed=0;
4742 *returned=0;
4745 * Level 1:
4746 * flags==PRINTER_ENUM_NAME
4747 * if name=="" then enumerates all printers
4748 * if name!="" then enumerate the printer
4749 * flags==PRINTER_ENUM_REMOTE
4750 * name is NULL, enumerate printers
4751 * Level 2: name!="" enumerates printers, name can't be NULL
4752 * Level 3: doesn't exist
4753 * Level 4: does a local registry lookup
4754 * Level 5: same as Level 2
4757 unistr2_to_ascii(name, servername, sizeof(name));
4758 strupper_m(name);
4760 switch (level) {
4761 case 1:
4762 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4763 case 2:
4764 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4765 case 5:
4766 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4767 case 3:
4768 case 4:
4769 break;
4771 return WERR_UNKNOWN_LEVEL;
4774 /****************************************************************************
4775 ****************************************************************************/
4777 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4779 PRINTER_INFO_0 *printer=NULL;
4780 WERROR result = WERR_OK;
4782 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4783 return WERR_NOMEM;
4785 construct_printer_info_0(print_hnd, printer, snum);
4787 /* check the required size. */
4788 *needed += spoolss_size_printer_info_0(printer);
4790 if (*needed > offered) {
4791 result = WERR_INSUFFICIENT_BUFFER;
4792 goto out;
4795 if (!rpcbuf_alloc_size(buffer, *needed)) {
4796 result = WERR_NOMEM;
4797 goto out;
4800 /* fill the buffer with the structures */
4801 smb_io_printer_info_0("", buffer, printer, 0);
4803 out:
4804 /* clear memory */
4806 SAFE_FREE(printer);
4808 return result;
4811 /****************************************************************************
4812 ****************************************************************************/
4814 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4816 PRINTER_INFO_1 *printer=NULL;
4817 WERROR result = WERR_OK;
4819 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4820 return WERR_NOMEM;
4822 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4824 /* check the required size. */
4825 *needed += spoolss_size_printer_info_1(printer);
4827 if (*needed > offered) {
4828 result = WERR_INSUFFICIENT_BUFFER;
4829 goto out;
4832 if (!rpcbuf_alloc_size(buffer, *needed)) {
4833 result = WERR_NOMEM;
4834 goto out;
4837 /* fill the buffer with the structures */
4838 smb_io_printer_info_1("", buffer, printer, 0);
4840 out:
4841 /* clear memory */
4842 SAFE_FREE(printer);
4844 return result;
4847 /****************************************************************************
4848 ****************************************************************************/
4850 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4852 PRINTER_INFO_2 *printer=NULL;
4853 WERROR result = WERR_OK;
4855 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4856 return WERR_NOMEM;
4858 construct_printer_info_2(print_hnd, printer, snum);
4860 /* check the required size. */
4861 *needed += spoolss_size_printer_info_2(printer);
4863 if (*needed > offered) {
4864 result = WERR_INSUFFICIENT_BUFFER;
4865 goto out;
4868 if (!rpcbuf_alloc_size(buffer, *needed)) {
4869 result = WERR_NOMEM;
4870 goto out;
4873 /* fill the buffer with the structures */
4874 if (!smb_io_printer_info_2("", buffer, printer, 0))
4875 result = WERR_NOMEM;
4877 out:
4878 /* clear memory */
4879 free_printer_info_2(printer);
4881 return result;
4884 /****************************************************************************
4885 ****************************************************************************/
4887 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4889 PRINTER_INFO_3 *printer=NULL;
4890 WERROR result = WERR_OK;
4892 if (!construct_printer_info_3(print_hnd, &printer, snum))
4893 return WERR_NOMEM;
4895 /* check the required size. */
4896 *needed += spoolss_size_printer_info_3(printer);
4898 if (*needed > offered) {
4899 result = WERR_INSUFFICIENT_BUFFER;
4900 goto out;
4903 if (!rpcbuf_alloc_size(buffer, *needed)) {
4904 result = WERR_NOMEM;
4905 goto out;
4908 /* fill the buffer with the structures */
4909 smb_io_printer_info_3("", buffer, printer, 0);
4911 out:
4912 /* clear memory */
4913 free_printer_info_3(printer);
4915 return result;
4918 /****************************************************************************
4919 ****************************************************************************/
4921 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4923 PRINTER_INFO_4 *printer=NULL;
4924 WERROR result = WERR_OK;
4926 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4927 return WERR_NOMEM;
4929 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4930 SAFE_FREE(printer);
4931 return WERR_NOMEM;
4934 /* check the required size. */
4935 *needed += spoolss_size_printer_info_4(printer);
4937 if (*needed > offered) {
4938 result = WERR_INSUFFICIENT_BUFFER;
4939 goto out;
4942 if (!rpcbuf_alloc_size(buffer, *needed)) {
4943 result = WERR_NOMEM;
4944 goto out;
4947 /* fill the buffer with the structures */
4948 smb_io_printer_info_4("", buffer, printer, 0);
4950 out:
4951 /* clear memory */
4952 free_printer_info_4(printer);
4954 return result;
4957 /****************************************************************************
4958 ****************************************************************************/
4960 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4962 PRINTER_INFO_5 *printer=NULL;
4963 WERROR result = WERR_OK;
4965 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4966 return WERR_NOMEM;
4968 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4969 free_printer_info_5(printer);
4970 return WERR_NOMEM;
4973 /* check the required size. */
4974 *needed += spoolss_size_printer_info_5(printer);
4976 if (*needed > offered) {
4977 result = WERR_INSUFFICIENT_BUFFER;
4978 goto out;
4981 if (!rpcbuf_alloc_size(buffer, *needed)) {
4982 result = WERR_NOMEM;
4983 goto out;
4986 /* fill the buffer with the structures */
4987 smb_io_printer_info_5("", buffer, printer, 0);
4989 out:
4990 /* clear memory */
4991 free_printer_info_5(printer);
4993 return result;
4996 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4997 int snum,
4998 RPC_BUFFER *buffer, uint32 offered,
4999 uint32 *needed)
5001 PRINTER_INFO_6 *printer;
5002 WERROR result = WERR_OK;
5004 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5005 return WERR_NOMEM;
5008 if (!construct_printer_info_6(print_hnd, printer, snum)) {
5009 free_printer_info_6(printer);
5010 return WERR_NOMEM;
5013 /* check the required size. */
5014 *needed += spoolss_size_printer_info_6(printer);
5016 if (*needed > offered) {
5017 result = WERR_INSUFFICIENT_BUFFER;
5018 goto out;
5021 if (!rpcbuf_alloc_size(buffer, *needed)) {
5022 result = WERR_NOMEM;
5023 goto out;
5026 /* fill the buffer with the structures */
5027 smb_io_printer_info_6("", buffer, printer, 0);
5029 out:
5030 /* clear memory */
5031 free_printer_info_6(printer);
5033 return result;
5036 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5038 PRINTER_INFO_7 *printer=NULL;
5039 WERROR result = WERR_OK;
5041 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5042 return WERR_NOMEM;
5044 if (!construct_printer_info_7(print_hnd, printer, snum))
5045 return WERR_NOMEM;
5047 /* check the required size. */
5048 *needed += spoolss_size_printer_info_7(printer);
5050 if (*needed > offered) {
5051 result = WERR_INSUFFICIENT_BUFFER;
5052 goto out;
5055 if (!rpcbuf_alloc_size(buffer, *needed)) {
5056 result = WERR_NOMEM;
5057 goto out;
5061 /* fill the buffer with the structures */
5062 smb_io_printer_info_7("", buffer, printer, 0);
5064 out:
5065 /* clear memory */
5066 free_printer_info_7(printer);
5068 return result;
5071 /****************************************************************************
5072 ****************************************************************************/
5074 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5076 POLICY_HND *handle = &q_u->handle;
5077 uint32 level = q_u->level;
5078 RPC_BUFFER *buffer = NULL;
5079 uint32 offered = q_u->offered;
5080 uint32 *needed = &r_u->needed;
5081 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5083 int snum;
5085 /* that's an [in out] buffer */
5087 if (!q_u->buffer && (offered!=0)) {
5088 return WERR_INVALID_PARAM;
5091 rpcbuf_move(q_u->buffer, &r_u->buffer);
5092 buffer = r_u->buffer;
5094 *needed=0;
5096 if (!get_printer_snum(p, handle, &snum, NULL))
5097 return WERR_BADFID;
5099 switch (level) {
5100 case 0:
5101 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5102 case 1:
5103 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5104 case 2:
5105 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5106 case 3:
5107 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5108 case 4:
5109 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5110 case 5:
5111 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5112 case 6:
5113 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5114 case 7:
5115 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5117 return WERR_UNKNOWN_LEVEL;
5120 /********************************************************************
5121 * fill a DRIVER_INFO_1 struct
5122 ********************************************************************/
5124 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5126 init_unistr( &info->name, driver.info_3->name);
5129 /********************************************************************
5130 * construct_printer_driver_info_1
5131 ********************************************************************/
5133 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5135 NT_PRINTER_INFO_LEVEL *printer = NULL;
5136 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5138 ZERO_STRUCT(driver);
5140 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5141 return WERR_INVALID_PRINTER_NAME;
5143 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5144 free_a_printer(&printer, 2);
5145 return WERR_UNKNOWN_PRINTER_DRIVER;
5148 fill_printer_driver_info_1(info, driver, servername, architecture);
5150 free_a_printer(&printer,2);
5152 return WERR_OK;
5155 /********************************************************************
5156 * construct_printer_driver_info_2
5157 * fill a printer_info_2 struct
5158 ********************************************************************/
5160 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5162 pstring temp;
5164 info->version=driver.info_3->cversion;
5166 init_unistr( &info->name, driver.info_3->name );
5167 init_unistr( &info->architecture, driver.info_3->environment );
5170 if (strlen(driver.info_3->driverpath)) {
5171 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5172 init_unistr( &info->driverpath, temp );
5173 } else
5174 init_unistr( &info->driverpath, "" );
5176 if (strlen(driver.info_3->datafile)) {
5177 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5178 init_unistr( &info->datafile, temp );
5179 } else
5180 init_unistr( &info->datafile, "" );
5182 if (strlen(driver.info_3->configfile)) {
5183 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5184 init_unistr( &info->configfile, temp );
5185 } else
5186 init_unistr( &info->configfile, "" );
5189 /********************************************************************
5190 * construct_printer_driver_info_2
5191 * fill a printer_info_2 struct
5192 ********************************************************************/
5194 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5196 NT_PRINTER_INFO_LEVEL *printer = NULL;
5197 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5199 ZERO_STRUCT(printer);
5200 ZERO_STRUCT(driver);
5202 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5203 return WERR_INVALID_PRINTER_NAME;
5205 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5206 free_a_printer(&printer, 2);
5207 return WERR_UNKNOWN_PRINTER_DRIVER;
5210 fill_printer_driver_info_2(info, driver, servername);
5212 free_a_printer(&printer,2);
5214 return WERR_OK;
5217 /********************************************************************
5218 * copy a strings array and convert to UNICODE
5220 * convert an array of ascii string to a UNICODE string
5221 ********************************************************************/
5223 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5225 int i=0;
5226 int j=0;
5227 const char *v;
5228 pstring line;
5230 DEBUG(6,("init_unistr_array\n"));
5231 *uni_array=NULL;
5233 while (True)
5235 if ( !char_array )
5236 v = "";
5237 else
5239 v = char_array[i];
5240 if (!v)
5241 v = ""; /* hack to handle null lists */
5244 /* hack to allow this to be used in places other than when generating
5245 the list of dependent files */
5247 if ( servername )
5248 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5249 else
5250 pstrcpy( line, v );
5252 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5254 /* add one extra unit16 for the second terminating NULL */
5256 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5257 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5258 return 0;
5261 if ( !strlen(v) )
5262 break;
5264 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5265 i++;
5268 if (*uni_array) {
5269 /* special case for ""; we need to add both NULL's here */
5270 if (!j)
5271 (*uni_array)[j++]=0x0000;
5272 (*uni_array)[j]=0x0000;
5275 DEBUGADD(6,("last one:done\n"));
5277 /* return size of array in uint16's */
5279 return j+1;
5282 /********************************************************************
5283 * construct_printer_info_3
5284 * fill a printer_info_3 struct
5285 ********************************************************************/
5287 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5289 pstring temp;
5291 ZERO_STRUCTP(info);
5293 info->version=driver.info_3->cversion;
5295 init_unistr( &info->name, driver.info_3->name );
5296 init_unistr( &info->architecture, driver.info_3->environment );
5298 if (strlen(driver.info_3->driverpath)) {
5299 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5300 init_unistr( &info->driverpath, temp );
5301 } else
5302 init_unistr( &info->driverpath, "" );
5304 if (strlen(driver.info_3->datafile)) {
5305 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5306 init_unistr( &info->datafile, temp );
5307 } else
5308 init_unistr( &info->datafile, "" );
5310 if (strlen(driver.info_3->configfile)) {
5311 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5312 init_unistr( &info->configfile, temp );
5313 } else
5314 init_unistr( &info->configfile, "" );
5316 if (strlen(driver.info_3->helpfile)) {
5317 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5318 init_unistr( &info->helpfile, temp );
5319 } else
5320 init_unistr( &info->helpfile, "" );
5322 init_unistr( &info->monitorname, driver.info_3->monitorname );
5323 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5325 info->dependentfiles=NULL;
5326 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5329 /********************************************************************
5330 * construct_printer_info_3
5331 * fill a printer_info_3 struct
5332 ********************************************************************/
5334 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5336 NT_PRINTER_INFO_LEVEL *printer = NULL;
5337 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5338 WERROR status;
5339 ZERO_STRUCT(driver);
5341 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5342 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5343 if (!W_ERROR_IS_OK(status))
5344 return WERR_INVALID_PRINTER_NAME;
5346 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5347 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5349 #if 0 /* JERRY */
5352 * I put this code in during testing. Helpful when commenting out the
5353 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5354 * as win2k always queries the driver using an infor level of 6.
5355 * I've left it in (but ifdef'd out) because I'll probably
5356 * use it in experimentation again in the future. --jerry 22/01/2002
5359 if (!W_ERROR_IS_OK(status)) {
5361 * Is this a W2k client ?
5363 if (version == 3) {
5364 /* Yes - try again with a WinNT driver. */
5365 version = 2;
5366 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5367 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5369 #endif
5371 if (!W_ERROR_IS_OK(status)) {
5372 free_a_printer(&printer,2);
5373 return WERR_UNKNOWN_PRINTER_DRIVER;
5376 #if 0 /* JERRY */
5378 #endif
5381 fill_printer_driver_info_3(info, driver, servername);
5383 free_a_printer(&printer,2);
5385 return WERR_OK;
5388 /********************************************************************
5389 * construct_printer_info_6
5390 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5391 ********************************************************************/
5393 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5395 pstring temp;
5396 fstring nullstr;
5398 ZERO_STRUCTP(info);
5399 memset(&nullstr, '\0', sizeof(fstring));
5401 info->version=driver.info_3->cversion;
5403 init_unistr( &info->name, driver.info_3->name );
5404 init_unistr( &info->architecture, driver.info_3->environment );
5406 if (strlen(driver.info_3->driverpath)) {
5407 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5408 init_unistr( &info->driverpath, temp );
5409 } else
5410 init_unistr( &info->driverpath, "" );
5412 if (strlen(driver.info_3->datafile)) {
5413 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5414 init_unistr( &info->datafile, temp );
5415 } else
5416 init_unistr( &info->datafile, "" );
5418 if (strlen(driver.info_3->configfile)) {
5419 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5420 init_unistr( &info->configfile, temp );
5421 } else
5422 init_unistr( &info->configfile, "" );
5424 if (strlen(driver.info_3->helpfile)) {
5425 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5426 init_unistr( &info->helpfile, temp );
5427 } else
5428 init_unistr( &info->helpfile, "" );
5430 init_unistr( &info->monitorname, driver.info_3->monitorname );
5431 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5433 info->dependentfiles = NULL;
5434 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5436 info->previousdrivernames=NULL;
5437 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5439 info->driver_date=0;
5441 info->padding=0;
5442 info->driver_version_low=0;
5443 info->driver_version_high=0;
5445 init_unistr( &info->mfgname, "");
5446 init_unistr( &info->oem_url, "");
5447 init_unistr( &info->hardware_id, "");
5448 init_unistr( &info->provider, "");
5451 /********************************************************************
5452 * construct_printer_info_6
5453 * fill a printer_info_6 struct
5454 ********************************************************************/
5456 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5457 fstring servername, fstring architecture, uint32 version)
5459 NT_PRINTER_INFO_LEVEL *printer = NULL;
5460 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5461 WERROR status;
5463 ZERO_STRUCT(driver);
5465 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5467 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5469 if (!W_ERROR_IS_OK(status))
5470 return WERR_INVALID_PRINTER_NAME;
5472 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5474 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5476 if (!W_ERROR_IS_OK(status))
5479 * Is this a W2k client ?
5482 if (version < 3) {
5483 free_a_printer(&printer,2);
5484 return WERR_UNKNOWN_PRINTER_DRIVER;
5487 /* Yes - try again with a WinNT driver. */
5488 version = 2;
5489 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5490 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5491 if (!W_ERROR_IS_OK(status)) {
5492 free_a_printer(&printer,2);
5493 return WERR_UNKNOWN_PRINTER_DRIVER;
5497 fill_printer_driver_info_6(info, driver, servername);
5499 free_a_printer(&printer,2);
5500 free_a_printer_driver(driver, 3);
5502 return WERR_OK;
5505 /****************************************************************************
5506 ****************************************************************************/
5508 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5510 SAFE_FREE(info->dependentfiles);
5513 /****************************************************************************
5514 ****************************************************************************/
5516 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5518 SAFE_FREE(info->dependentfiles);
5521 /****************************************************************************
5522 ****************************************************************************/
5524 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5526 DRIVER_INFO_1 *info=NULL;
5527 WERROR result;
5529 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5530 return WERR_NOMEM;
5532 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5533 if (!W_ERROR_IS_OK(result))
5534 goto out;
5536 /* check the required size. */
5537 *needed += spoolss_size_printer_driver_info_1(info);
5539 if (*needed > offered) {
5540 result = WERR_INSUFFICIENT_BUFFER;
5541 goto out;
5544 if (!rpcbuf_alloc_size(buffer, *needed)) {
5545 result = WERR_NOMEM;
5546 goto out;
5549 /* fill the buffer with the structures */
5550 smb_io_printer_driver_info_1("", buffer, info, 0);
5552 out:
5553 /* clear memory */
5554 SAFE_FREE(info);
5556 return result;
5559 /****************************************************************************
5560 ****************************************************************************/
5562 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5564 DRIVER_INFO_2 *info=NULL;
5565 WERROR result;
5567 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5568 return WERR_NOMEM;
5570 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5571 if (!W_ERROR_IS_OK(result))
5572 goto out;
5574 /* check the required size. */
5575 *needed += spoolss_size_printer_driver_info_2(info);
5577 if (*needed > offered) {
5578 result = WERR_INSUFFICIENT_BUFFER;
5579 goto out;
5582 if (!rpcbuf_alloc_size(buffer, *needed)) {
5583 result = WERR_NOMEM;
5584 goto out;
5587 /* fill the buffer with the structures */
5588 smb_io_printer_driver_info_2("", buffer, info, 0);
5590 out:
5591 /* clear memory */
5592 SAFE_FREE(info);
5594 return result;
5597 /****************************************************************************
5598 ****************************************************************************/
5600 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5602 DRIVER_INFO_3 info;
5603 WERROR result;
5605 ZERO_STRUCT(info);
5607 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5608 if (!W_ERROR_IS_OK(result))
5609 goto out;
5611 /* check the required size. */
5612 *needed += spoolss_size_printer_driver_info_3(&info);
5614 if (*needed > offered) {
5615 result = WERR_INSUFFICIENT_BUFFER;
5616 goto out;
5619 if (!rpcbuf_alloc_size(buffer, *needed)) {
5620 result = WERR_NOMEM;
5621 goto out;
5624 /* fill the buffer with the structures */
5625 smb_io_printer_driver_info_3("", buffer, &info, 0);
5627 out:
5628 free_printer_driver_info_3(&info);
5630 return result;
5633 /****************************************************************************
5634 ****************************************************************************/
5636 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5638 DRIVER_INFO_6 info;
5639 WERROR result;
5641 ZERO_STRUCT(info);
5643 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5644 if (!W_ERROR_IS_OK(result))
5645 goto out;
5647 /* check the required size. */
5648 *needed += spoolss_size_printer_driver_info_6(&info);
5650 if (*needed > offered) {
5651 result = WERR_INSUFFICIENT_BUFFER;
5652 goto out;
5655 if (!rpcbuf_alloc_size(buffer, *needed)) {
5656 result = WERR_NOMEM;
5657 goto out;
5660 /* fill the buffer with the structures */
5661 smb_io_printer_driver_info_6("", buffer, &info, 0);
5663 out:
5664 free_printer_driver_info_6(&info);
5666 return result;
5669 /****************************************************************************
5670 ****************************************************************************/
5672 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5674 POLICY_HND *handle = &q_u->handle;
5675 UNISTR2 *uni_arch = &q_u->architecture;
5676 uint32 level = q_u->level;
5677 uint32 clientmajorversion = q_u->clientmajorversion;
5678 RPC_BUFFER *buffer = NULL;
5679 uint32 offered = q_u->offered;
5680 uint32 *needed = &r_u->needed;
5681 uint32 *servermajorversion = &r_u->servermajorversion;
5682 uint32 *serverminorversion = &r_u->serverminorversion;
5683 Printer_entry *printer;
5685 fstring servername;
5686 fstring architecture;
5687 int snum;
5689 /* that's an [in out] buffer */
5691 if (!q_u->buffer && (offered!=0)) {
5692 return WERR_INVALID_PARAM;
5695 rpcbuf_move(q_u->buffer, &r_u->buffer);
5696 buffer = r_u->buffer;
5698 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5700 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5701 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5702 return WERR_INVALID_PRINTER_NAME;
5705 *needed = 0;
5706 *servermajorversion = 0;
5707 *serverminorversion = 0;
5709 fstrcpy(servername, get_server_name( printer ));
5710 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5712 if (!get_printer_snum(p, handle, &snum, NULL))
5713 return WERR_BADFID;
5715 switch (level) {
5716 case 1:
5717 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5718 case 2:
5719 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5720 case 3:
5721 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5722 case 6:
5723 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5724 #if 0 /* JERRY */
5725 case 101:
5726 /* apparently this call is the equivalent of
5727 EnumPrinterDataEx() for the DsDriver key */
5728 break;
5729 #endif
5732 return WERR_UNKNOWN_LEVEL;
5735 /****************************************************************************
5736 ****************************************************************************/
5738 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5740 POLICY_HND *handle = &q_u->handle;
5742 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5744 if (!Printer) {
5745 DEBUG(3,("Error in startpageprinter printer handle\n"));
5746 return WERR_BADFID;
5749 Printer->page_started=True;
5750 return WERR_OK;
5753 /****************************************************************************
5754 ****************************************************************************/
5756 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5758 POLICY_HND *handle = &q_u->handle;
5759 int snum;
5761 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5763 if (!Printer) {
5764 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5765 return WERR_BADFID;
5768 if (!get_printer_snum(p, handle, &snum, NULL))
5769 return WERR_BADFID;
5771 Printer->page_started=False;
5772 print_job_endpage(snum, Printer->jobid);
5774 return WERR_OK;
5777 /********************************************************************
5778 * api_spoolss_getprinter
5779 * called from the spoolss dispatcher
5781 ********************************************************************/
5783 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5785 POLICY_HND *handle = &q_u->handle;
5786 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5787 uint32 *jobid = &r_u->jobid;
5789 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5790 int snum;
5791 pstring jobname;
5792 fstring datatype;
5793 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5795 if (!Printer) {
5796 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5797 return WERR_BADFID;
5801 * a nice thing with NT is it doesn't listen to what you tell it.
5802 * when asked to send _only_ RAW datas, it tries to send datas
5803 * in EMF format.
5805 * So I add checks like in NT Server ...
5808 if (info_1->p_datatype != 0) {
5809 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5810 if (strcmp(datatype, "RAW") != 0) {
5811 (*jobid)=0;
5812 return WERR_INVALID_DATATYPE;
5816 /* get the share number of the printer */
5817 if (!get_printer_snum(p, handle, &snum, NULL)) {
5818 return WERR_BADFID;
5821 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5823 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5825 /* An error occured in print_job_start() so return an appropriate
5826 NT error code. */
5828 if (Printer->jobid == -1) {
5829 return map_werror_from_unix(errno);
5832 Printer->document_started=True;
5833 (*jobid) = Printer->jobid;
5835 return WERR_OK;
5838 /********************************************************************
5839 * api_spoolss_getprinter
5840 * called from the spoolss dispatcher
5842 ********************************************************************/
5844 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5846 POLICY_HND *handle = &q_u->handle;
5848 return _spoolss_enddocprinter_internal(p, handle);
5851 /****************************************************************************
5852 ****************************************************************************/
5854 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5856 POLICY_HND *handle = &q_u->handle;
5857 uint32 buffer_size = q_u->buffer_size;
5858 uint8 *buffer = q_u->buffer;
5859 uint32 *buffer_written = &q_u->buffer_size2;
5860 int snum;
5861 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5863 if (!Printer) {
5864 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5865 r_u->buffer_written = q_u->buffer_size2;
5866 return WERR_BADFID;
5869 if (!get_printer_snum(p, handle, &snum, NULL))
5870 return WERR_BADFID;
5872 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5873 (SMB_OFF_T)-1, (size_t)buffer_size);
5874 if (*buffer_written == (uint32)-1) {
5875 r_u->buffer_written = 0;
5876 if (errno == ENOSPC)
5877 return WERR_NO_SPOOL_SPACE;
5878 else
5879 return WERR_ACCESS_DENIED;
5882 r_u->buffer_written = q_u->buffer_size2;
5884 return WERR_OK;
5887 /********************************************************************
5888 * api_spoolss_getprinter
5889 * called from the spoolss dispatcher
5891 ********************************************************************/
5893 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5894 pipes_struct *p)
5896 int snum;
5897 WERROR errcode = WERR_BADFUNC;
5898 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5900 if (!Printer) {
5901 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5902 return WERR_BADFID;
5905 if (!get_printer_snum(p, handle, &snum, NULL))
5906 return WERR_BADFID;
5908 switch (command) {
5909 case PRINTER_CONTROL_PAUSE:
5910 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5911 errcode = WERR_OK;
5913 break;
5914 case PRINTER_CONTROL_RESUME:
5915 case PRINTER_CONTROL_UNPAUSE:
5916 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5917 errcode = WERR_OK;
5919 break;
5920 case PRINTER_CONTROL_PURGE:
5921 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5922 errcode = WERR_OK;
5924 break;
5925 default:
5926 return WERR_UNKNOWN_LEVEL;
5929 return errcode;
5932 /********************************************************************
5933 * api_spoolss_abortprinter
5934 * From MSDN: "Deletes printer's spool file if printer is configured
5935 * for spooling"
5936 ********************************************************************/
5938 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5940 POLICY_HND *handle = &q_u->handle;
5941 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5942 int snum;
5943 WERROR errcode = WERR_OK;
5945 if (!Printer) {
5946 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5947 return WERR_BADFID;
5950 if (!get_printer_snum(p, handle, &snum, NULL))
5951 return WERR_BADFID;
5953 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5955 return errcode;
5958 /********************************************************************
5959 * called by spoolss_api_setprinter
5960 * when updating a printer description
5961 ********************************************************************/
5963 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5964 const SPOOL_PRINTER_INFO_LEVEL *info,
5965 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5967 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5968 WERROR result;
5969 int snum;
5971 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5973 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5974 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5975 OUR_HANDLE(handle)));
5977 result = WERR_BADFID;
5978 goto done;
5981 if (!secdesc_ctr) {
5982 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5983 result = WERR_INVALID_PARAM;
5984 goto done;
5987 /* Check the user has permissions to change the security
5988 descriptor. By experimentation with two NT machines, the user
5989 requires Full Access to the printer to change security
5990 information. */
5992 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5993 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5994 result = WERR_ACCESS_DENIED;
5995 goto done;
5998 /* NT seems to like setting the security descriptor even though
5999 nothing may have actually changed. */
6001 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6003 if (DEBUGLEVEL >= 10) {
6004 SEC_ACL *the_acl;
6005 int i;
6007 the_acl = old_secdesc_ctr->sd->dacl;
6008 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6009 PRINTERNAME(snum), the_acl->num_aces));
6011 for (i = 0; i < the_acl->num_aces; i++) {
6012 fstring sid_str;
6014 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6016 DEBUG(10, ("%s 0x%08x\n", sid_str,
6017 the_acl->aces[i].access_mask));
6020 the_acl = secdesc_ctr->sd->dacl;
6022 if (the_acl) {
6023 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6024 PRINTERNAME(snum), the_acl->num_aces));
6026 for (i = 0; i < the_acl->num_aces; i++) {
6027 fstring sid_str;
6029 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6031 DEBUG(10, ("%s 0x%08x\n", sid_str,
6032 the_acl->aces[i].access_mask));
6034 } else {
6035 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6039 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6040 if (!new_secdesc_ctr) {
6041 result = WERR_NOMEM;
6042 goto done;
6045 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6046 result = WERR_OK;
6047 goto done;
6050 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6052 done:
6054 return result;
6057 /********************************************************************
6058 Canonicalize printer info from a client
6060 ATTN: It does not matter what we set the servername to hear
6061 since we do the necessary work in get_a_printer() to set it to
6062 the correct value based on what the client sent in the
6063 _spoolss_open_printer_ex().
6064 ********************************************************************/
6066 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6068 fstring printername;
6069 const char *p;
6071 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6072 "portname=%s drivername=%s comment=%s location=%s\n",
6073 info->servername, info->printername, info->sharename,
6074 info->portname, info->drivername, info->comment, info->location));
6076 /* we force some elements to "correct" values */
6077 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6078 fstrcpy(info->sharename, lp_servicename(snum));
6080 /* check to see if we allow printername != sharename */
6082 if ( lp_force_printername(snum) ) {
6083 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6084 global_myname(), info->sharename );
6085 } else {
6087 /* make sure printername is in \\server\printername format */
6089 fstrcpy( printername, info->printername );
6090 p = printername;
6091 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6092 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6093 p++;
6096 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6097 global_myname(), p );
6100 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6101 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6105 return True;
6108 /****************************************************************************
6109 ****************************************************************************/
6111 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6113 char *cmd = lp_addport_cmd();
6114 pstring command;
6115 int ret;
6116 int fd;
6117 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6118 bool is_print_op = False;
6120 if ( !*cmd ) {
6121 return WERR_ACCESS_DENIED;
6124 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6126 if ( token )
6127 is_print_op = user_has_privileges( token, &se_printop );
6129 DEBUG(10,("Running [%s]\n", command));
6131 /********* BEGIN SePrintOperatorPrivilege **********/
6133 if ( is_print_op )
6134 become_root();
6136 ret = smbrun(command, &fd);
6138 if ( is_print_op )
6139 unbecome_root();
6141 /********* END SePrintOperatorPrivilege **********/
6143 DEBUGADD(10,("returned [%d]\n", ret));
6145 if ( ret != 0 ) {
6146 if (fd != -1)
6147 close(fd);
6148 return WERR_ACCESS_DENIED;
6151 return WERR_OK;
6154 /****************************************************************************
6155 ****************************************************************************/
6157 bool add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6159 char *cmd = lp_addprinter_cmd();
6160 char **qlines;
6161 pstring command;
6162 int numlines;
6163 int ret;
6164 int fd;
6165 fstring remote_machine = "%m";
6166 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6167 bool is_print_op = False;
6169 standard_sub_basic(current_user_info.smb_name,
6170 current_user_info.domain,
6171 remote_machine,sizeof(remote_machine));
6173 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6174 cmd, printer->info_2->printername, printer->info_2->sharename,
6175 printer->info_2->portname, printer->info_2->drivername,
6176 printer->info_2->location, printer->info_2->comment, remote_machine);
6178 if ( token )
6179 is_print_op = user_has_privileges( token, &se_printop );
6181 DEBUG(10,("Running [%s]\n", command));
6183 /********* BEGIN SePrintOperatorPrivilege **********/
6185 if ( is_print_op )
6186 become_root();
6188 if ( (ret = smbrun(command, &fd)) == 0 ) {
6189 /* Tell everyone we updated smb.conf. */
6190 message_send_all(smbd_messaging_context(),
6191 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6194 if ( is_print_op )
6195 unbecome_root();
6197 /********* END SePrintOperatorPrivilege **********/
6199 DEBUGADD(10,("returned [%d]\n", ret));
6201 if ( ret != 0 ) {
6202 if (fd != -1)
6203 close(fd);
6204 return False;
6207 /* reload our services immediately */
6208 reload_services( False );
6210 numlines = 0;
6211 /* Get lines and convert them back to dos-codepage */
6212 qlines = fd_lines_load(fd, &numlines, 0);
6213 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6214 close(fd);
6216 /* Set the portname to what the script says the portname should be. */
6217 /* but don't require anything to be return from the script exit a good error code */
6219 if (numlines) {
6220 /* Set the portname to what the script says the portname should be. */
6221 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6222 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6225 file_lines_free(qlines);
6226 return True;
6230 /********************************************************************
6231 * Called by spoolss_api_setprinter
6232 * when updating a printer description.
6233 ********************************************************************/
6235 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6236 const SPOOL_PRINTER_INFO_LEVEL *info,
6237 DEVICEMODE *devmode)
6239 int snum;
6240 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6241 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6242 WERROR result;
6243 UNISTR2 buffer;
6244 fstring asc_buffer;
6246 DEBUG(8,("update_printer\n"));
6248 result = WERR_OK;
6250 if (!Printer) {
6251 result = WERR_BADFID;
6252 goto done;
6255 if (!get_printer_snum(p, handle, &snum, NULL)) {
6256 result = WERR_BADFID;
6257 goto done;
6260 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6261 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6262 result = WERR_BADFID;
6263 goto done;
6266 DEBUGADD(8,("Converting info_2 struct\n"));
6269 * convert_printer_info converts the incoming
6270 * info from the client and overwrites the info
6271 * just read from the tdb in the pointer 'printer'.
6274 if (!convert_printer_info(info, printer, level)) {
6275 result = WERR_NOMEM;
6276 goto done;
6279 if (devmode) {
6280 /* we have a valid devmode
6281 convert it and link it*/
6283 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6284 if (!convert_devicemode(printer->info_2->printername, devmode,
6285 &printer->info_2->devmode)) {
6286 result = WERR_NOMEM;
6287 goto done;
6291 /* Do sanity check on the requested changes for Samba */
6293 if (!check_printer_ok(printer->info_2, snum)) {
6294 result = WERR_INVALID_PARAM;
6295 goto done;
6298 /* FIXME!!! If the driver has changed we really should verify that
6299 it is installed before doing much else --jerry */
6301 /* Check calling user has permission to update printer description */
6303 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6304 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6305 result = WERR_ACCESS_DENIED;
6306 goto done;
6309 /* Call addprinter hook */
6310 /* Check changes to see if this is really needed */
6312 if ( *lp_addprinter_cmd()
6313 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6314 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6315 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6316 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6318 /* add_printer_hook() will call reload_services() */
6320 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6321 result = WERR_ACCESS_DENIED;
6322 goto done;
6327 * When a *new* driver is bound to a printer, the drivername is used to
6328 * lookup previously saved driver initialization info, which is then
6329 * bound to the printer, simulating what happens in the Windows arch.
6331 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6333 if (!set_driver_init(printer, 2))
6335 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6336 printer->info_2->drivername));
6339 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6340 printer->info_2->drivername));
6342 notify_printer_driver(snum, printer->info_2->drivername);
6346 * flag which changes actually occured. This is a small subset of
6347 * all the possible changes. We also have to update things in the
6348 * DsSpooler key.
6351 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6352 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6353 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6354 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6356 notify_printer_comment(snum, printer->info_2->comment);
6359 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6360 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6361 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6362 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6364 notify_printer_sharename(snum, printer->info_2->sharename);
6367 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6368 char *pname;
6370 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6371 pname++;
6372 else
6373 pname = printer->info_2->printername;
6376 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6377 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6378 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6380 notify_printer_printername( snum, pname );
6383 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6384 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6385 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6386 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6388 notify_printer_port(snum, printer->info_2->portname);
6391 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6392 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6393 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6394 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6396 notify_printer_location(snum, printer->info_2->location);
6399 /* here we need to update some more DsSpooler keys */
6400 /* uNCName, serverName, shortServerName */
6402 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6403 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6404 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6405 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6406 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6408 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6409 global_myname(), printer->info_2->sharename );
6410 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6411 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6412 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6414 /* Update printer info */
6415 result = mod_a_printer(printer, 2);
6417 done:
6418 free_a_printer(&printer, 2);
6419 free_a_printer(&old_printer, 2);
6422 return result;
6425 /****************************************************************************
6426 ****************************************************************************/
6427 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6428 const SPOOL_PRINTER_INFO_LEVEL *info)
6430 #ifdef HAVE_ADS
6431 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6432 int snum;
6433 Printer_entry *Printer;
6435 if ( lp_security() != SEC_ADS ) {
6436 return WERR_UNKNOWN_LEVEL;
6439 Printer = find_printer_index_by_hnd(p, handle);
6441 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6443 if (!Printer)
6444 return WERR_BADFID;
6446 if (!get_printer_snum(p, handle, &snum, NULL))
6447 return WERR_BADFID;
6449 nt_printer_publish(Printer, snum, info7->action);
6451 return WERR_OK;
6452 #else
6453 return WERR_UNKNOWN_LEVEL;
6454 #endif
6456 /****************************************************************************
6457 ****************************************************************************/
6459 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6461 POLICY_HND *handle = &q_u->handle;
6462 uint32 level = q_u->level;
6463 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6464 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6465 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6466 uint32 command = q_u->command;
6467 WERROR result;
6469 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6471 if (!Printer) {
6472 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6473 return WERR_BADFID;
6476 /* check the level */
6477 switch (level) {
6478 case 0:
6479 return control_printer(handle, command, p);
6480 case 2:
6481 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6482 if (!W_ERROR_IS_OK(result))
6483 return result;
6484 if (secdesc_ctr)
6485 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6486 return result;
6487 case 3:
6488 return update_printer_sec(handle, level, info, p,
6489 secdesc_ctr);
6490 case 7:
6491 return publish_or_unpublish_printer(p, handle, info);
6492 default:
6493 return WERR_UNKNOWN_LEVEL;
6497 /****************************************************************************
6498 ****************************************************************************/
6500 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6502 POLICY_HND *handle = &q_u->handle;
6503 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6505 if (!Printer) {
6506 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6507 return WERR_BADFID;
6510 if (Printer->notify.client_connected==True) {
6511 int snum = -1;
6513 if ( Printer->printer_type == SPLHND_SERVER)
6514 snum = -1;
6515 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6516 !get_printer_snum(p, handle, &snum, NULL) )
6517 return WERR_BADFID;
6519 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6522 Printer->notify.flags=0;
6523 Printer->notify.options=0;
6524 Printer->notify.localmachine[0]='\0';
6525 Printer->notify.printerlocal=0;
6526 if (Printer->notify.option)
6527 free_spool_notify_option(&Printer->notify.option);
6528 Printer->notify.client_connected=False;
6530 return WERR_OK;
6533 /****************************************************************************
6534 ****************************************************************************/
6536 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6538 /* that's an [in out] buffer */
6540 if (!q_u->buffer && (q_u->offered!=0)) {
6541 return WERR_INVALID_PARAM;
6544 rpcbuf_move(q_u->buffer, &r_u->buffer);
6546 r_u->needed = 0;
6547 return WERR_INVALID_PARAM; /* this is what a NT server
6548 returns for AddJob. AddJob
6549 must fail on non-local
6550 printers */
6553 /****************************************************************************
6554 ****************************************************************************/
6556 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6557 int position, int snum,
6558 const NT_PRINTER_INFO_LEVEL *ntprinter)
6560 struct tm *t;
6562 t=gmtime(&queue->time);
6564 job_info->jobid=queue->job;
6565 init_unistr(&job_info->printername, lp_servicename(snum));
6566 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6567 init_unistr(&job_info->username, queue->fs_user);
6568 init_unistr(&job_info->document, queue->fs_file);
6569 init_unistr(&job_info->datatype, "RAW");
6570 init_unistr(&job_info->text_status, "");
6571 job_info->status=nt_printj_status(queue->status);
6572 job_info->priority=queue->priority;
6573 job_info->position=position;
6574 job_info->totalpages=queue->page_count;
6575 job_info->pagesprinted=0;
6577 make_systemtime(&job_info->submitted, t);
6580 /****************************************************************************
6581 ****************************************************************************/
6583 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6584 int position, int snum,
6585 const NT_PRINTER_INFO_LEVEL *ntprinter,
6586 DEVICEMODE *devmode)
6588 struct tm *t;
6590 t=gmtime(&queue->time);
6592 job_info->jobid=queue->job;
6594 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6596 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6597 init_unistr(&job_info->username, queue->fs_user);
6598 init_unistr(&job_info->document, queue->fs_file);
6599 init_unistr(&job_info->notifyname, queue->fs_user);
6600 init_unistr(&job_info->datatype, "RAW");
6601 init_unistr(&job_info->printprocessor, "winprint");
6602 init_unistr(&job_info->parameters, "");
6603 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6604 init_unistr(&job_info->text_status, "");
6606 /* and here the security descriptor */
6608 job_info->status=nt_printj_status(queue->status);
6609 job_info->priority=queue->priority;
6610 job_info->position=position;
6611 job_info->starttime=0;
6612 job_info->untiltime=0;
6613 job_info->totalpages=queue->page_count;
6614 job_info->size=queue->size;
6615 make_systemtime(&(job_info->submitted), t);
6616 job_info->timeelapsed=0;
6617 job_info->pagesprinted=0;
6619 job_info->devmode = devmode;
6621 return (True);
6624 /****************************************************************************
6625 Enumjobs at level 1.
6626 ****************************************************************************/
6628 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6629 const NT_PRINTER_INFO_LEVEL *ntprinter,
6630 RPC_BUFFER *buffer, uint32 offered,
6631 uint32 *needed, uint32 *returned)
6633 JOB_INFO_1 *info;
6634 int i;
6635 WERROR result = WERR_OK;
6637 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6638 if (info==NULL) {
6639 *returned=0;
6640 return WERR_NOMEM;
6643 for (i=0; i<*returned; i++)
6644 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6646 /* check the required size. */
6647 for (i=0; i<*returned; i++)
6648 (*needed) += spoolss_size_job_info_1(&info[i]);
6650 if (*needed > offered) {
6651 result = WERR_INSUFFICIENT_BUFFER;
6652 goto out;
6655 if (!rpcbuf_alloc_size(buffer, *needed)) {
6656 result = WERR_NOMEM;
6657 goto out;
6660 /* fill the buffer with the structures */
6661 for (i=0; i<*returned; i++)
6662 smb_io_job_info_1("", buffer, &info[i], 0);
6664 out:
6665 /* clear memory */
6666 SAFE_FREE(info);
6668 if ( !W_ERROR_IS_OK(result) )
6669 *returned = 0;
6671 return result;
6674 /****************************************************************************
6675 Enumjobs at level 2.
6676 ****************************************************************************/
6678 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6679 const NT_PRINTER_INFO_LEVEL *ntprinter,
6680 RPC_BUFFER *buffer, uint32 offered,
6681 uint32 *needed, uint32 *returned)
6683 JOB_INFO_2 *info = NULL;
6684 int i;
6685 WERROR result = WERR_OK;
6686 DEVICEMODE *devmode = NULL;
6688 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6689 *returned=0;
6690 return WERR_NOMEM;
6693 /* this should not be a failure condition if the devmode is NULL */
6695 devmode = construct_dev_mode(lp_const_servicename(snum));
6697 for (i=0; i<*returned; i++)
6698 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6700 /* check the required size. */
6701 for (i=0; i<*returned; i++)
6702 (*needed) += spoolss_size_job_info_2(&info[i]);
6704 if (*needed > offered) {
6705 result = WERR_INSUFFICIENT_BUFFER;
6706 goto out;
6709 if (!rpcbuf_alloc_size(buffer, *needed)) {
6710 result = WERR_NOMEM;
6711 goto out;
6714 /* fill the buffer with the structures */
6715 for (i=0; i<*returned; i++)
6716 smb_io_job_info_2("", buffer, &info[i], 0);
6718 out:
6719 free_devmode(devmode);
6720 SAFE_FREE(info);
6722 if ( !W_ERROR_IS_OK(result) )
6723 *returned = 0;
6725 return result;
6729 /****************************************************************************
6730 Enumjobs.
6731 ****************************************************************************/
6733 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6735 POLICY_HND *handle = &q_u->handle;
6736 uint32 level = q_u->level;
6737 RPC_BUFFER *buffer = NULL;
6738 uint32 offered = q_u->offered;
6739 uint32 *needed = &r_u->needed;
6740 uint32 *returned = &r_u->returned;
6741 WERROR wret;
6742 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6743 int snum;
6744 print_status_struct prt_status;
6745 print_queue_struct *queue=NULL;
6747 /* that's an [in out] buffer */
6749 if (!q_u->buffer && (offered!=0)) {
6750 return WERR_INVALID_PARAM;
6753 rpcbuf_move(q_u->buffer, &r_u->buffer);
6754 buffer = r_u->buffer;
6756 DEBUG(4,("_spoolss_enumjobs\n"));
6758 *needed=0;
6759 *returned=0;
6761 /* lookup the printer snum and tdb entry */
6763 if (!get_printer_snum(p, handle, &snum, NULL))
6764 return WERR_BADFID;
6766 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6767 if ( !W_ERROR_IS_OK(wret) )
6768 return wret;
6770 *returned = print_queue_status(snum, &queue, &prt_status);
6771 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6773 if (*returned == 0) {
6774 SAFE_FREE(queue);
6775 free_a_printer(&ntprinter, 2);
6776 return WERR_OK;
6779 switch (level) {
6780 case 1:
6781 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6782 break;
6783 case 2:
6784 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6785 break;
6786 default:
6787 *returned=0;
6788 wret = WERR_UNKNOWN_LEVEL;
6789 break;
6792 SAFE_FREE(queue);
6793 free_a_printer( &ntprinter, 2 );
6794 return wret;
6797 /****************************************************************************
6798 ****************************************************************************/
6800 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6802 return WERR_OK;
6805 /****************************************************************************
6806 ****************************************************************************/
6808 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6810 POLICY_HND *handle = &q_u->handle;
6811 uint32 jobid = q_u->jobid;
6812 uint32 command = q_u->command;
6814 int snum;
6815 WERROR errcode = WERR_BADFUNC;
6817 if (!get_printer_snum(p, handle, &snum, NULL)) {
6818 return WERR_BADFID;
6821 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6822 return WERR_INVALID_PRINTER_NAME;
6825 switch (command) {
6826 case JOB_CONTROL_CANCEL:
6827 case JOB_CONTROL_DELETE:
6828 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6829 errcode = WERR_OK;
6831 break;
6832 case JOB_CONTROL_PAUSE:
6833 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6834 errcode = WERR_OK;
6836 break;
6837 case JOB_CONTROL_RESTART:
6838 case JOB_CONTROL_RESUME:
6839 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6840 errcode = WERR_OK;
6842 break;
6843 default:
6844 return WERR_UNKNOWN_LEVEL;
6847 return errcode;
6850 /****************************************************************************
6851 Enumerates all printer drivers at level 1.
6852 ****************************************************************************/
6854 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6856 int i;
6857 int ndrivers;
6858 uint32 version;
6859 fstring *list = NULL;
6860 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6861 DRIVER_INFO_1 *driver_info_1=NULL;
6862 WERROR result = WERR_OK;
6864 *returned=0;
6866 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6867 list=NULL;
6868 ndrivers=get_ntdrivers(&list, architecture, version);
6869 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6871 if(ndrivers == -1) {
6872 SAFE_FREE(driver_info_1);
6873 return WERR_NOMEM;
6876 if(ndrivers != 0) {
6877 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6878 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6879 SAFE_FREE(list);
6880 return WERR_NOMEM;
6884 for (i=0; i<ndrivers; i++) {
6885 WERROR status;
6886 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6887 ZERO_STRUCT(driver);
6888 status = get_a_printer_driver(&driver, 3, list[i],
6889 architecture, version);
6890 if (!W_ERROR_IS_OK(status)) {
6891 SAFE_FREE(list);
6892 SAFE_FREE(driver_info_1);
6893 return status;
6895 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6896 free_a_printer_driver(driver, 3);
6899 *returned+=ndrivers;
6900 SAFE_FREE(list);
6903 /* check the required size. */
6904 for (i=0; i<*returned; i++) {
6905 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6906 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6909 if (*needed > offered) {
6910 result = WERR_INSUFFICIENT_BUFFER;
6911 goto out;
6914 if (!rpcbuf_alloc_size(buffer, *needed)) {
6915 result = WERR_NOMEM;
6916 goto out;
6919 /* fill the buffer with the driver structures */
6920 for (i=0; i<*returned; i++) {
6921 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6922 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6925 out:
6926 SAFE_FREE(driver_info_1);
6928 if ( !W_ERROR_IS_OK(result) )
6929 *returned = 0;
6931 return result;
6934 /****************************************************************************
6935 Enumerates all printer drivers at level 2.
6936 ****************************************************************************/
6938 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6940 int i;
6941 int ndrivers;
6942 uint32 version;
6943 fstring *list = NULL;
6944 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6945 DRIVER_INFO_2 *driver_info_2=NULL;
6946 WERROR result = WERR_OK;
6948 *returned=0;
6950 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6951 list=NULL;
6952 ndrivers=get_ntdrivers(&list, architecture, version);
6953 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6955 if(ndrivers == -1) {
6956 SAFE_FREE(driver_info_2);
6957 return WERR_NOMEM;
6960 if(ndrivers != 0) {
6961 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6962 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6963 SAFE_FREE(list);
6964 return WERR_NOMEM;
6968 for (i=0; i<ndrivers; i++) {
6969 WERROR status;
6971 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6972 ZERO_STRUCT(driver);
6973 status = get_a_printer_driver(&driver, 3, list[i],
6974 architecture, version);
6975 if (!W_ERROR_IS_OK(status)) {
6976 SAFE_FREE(list);
6977 SAFE_FREE(driver_info_2);
6978 return status;
6980 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6981 free_a_printer_driver(driver, 3);
6984 *returned+=ndrivers;
6985 SAFE_FREE(list);
6988 /* check the required size. */
6989 for (i=0; i<*returned; i++) {
6990 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6991 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6994 if (*needed > offered) {
6995 result = WERR_INSUFFICIENT_BUFFER;
6996 goto out;
6999 if (!rpcbuf_alloc_size(buffer, *needed)) {
7000 result = WERR_NOMEM;
7001 goto out;
7004 /* fill the buffer with the form structures */
7005 for (i=0; i<*returned; i++) {
7006 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7007 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7010 out:
7011 SAFE_FREE(driver_info_2);
7013 if ( !W_ERROR_IS_OK(result) )
7014 *returned = 0;
7016 return result;
7019 /****************************************************************************
7020 Enumerates all printer drivers at level 3.
7021 ****************************************************************************/
7023 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7025 int i;
7026 int ndrivers;
7027 uint32 version;
7028 fstring *list = NULL;
7029 DRIVER_INFO_3 *driver_info_3=NULL;
7030 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7031 WERROR result = WERR_OK;
7033 *returned=0;
7035 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7036 list=NULL;
7037 ndrivers=get_ntdrivers(&list, architecture, version);
7038 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7040 if(ndrivers == -1) {
7041 SAFE_FREE(driver_info_3);
7042 return WERR_NOMEM;
7045 if(ndrivers != 0) {
7046 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7047 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7048 SAFE_FREE(list);
7049 return WERR_NOMEM;
7053 for (i=0; i<ndrivers; i++) {
7054 WERROR status;
7056 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7057 ZERO_STRUCT(driver);
7058 status = get_a_printer_driver(&driver, 3, list[i],
7059 architecture, version);
7060 if (!W_ERROR_IS_OK(status)) {
7061 SAFE_FREE(list);
7062 SAFE_FREE(driver_info_3);
7063 return status;
7065 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7066 free_a_printer_driver(driver, 3);
7069 *returned+=ndrivers;
7070 SAFE_FREE(list);
7073 /* check the required size. */
7074 for (i=0; i<*returned; i++) {
7075 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7076 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7079 if (*needed > offered) {
7080 result = WERR_INSUFFICIENT_BUFFER;
7081 goto out;
7084 if (!rpcbuf_alloc_size(buffer, *needed)) {
7085 result = WERR_NOMEM;
7086 goto out;
7089 /* fill the buffer with the driver structures */
7090 for (i=0; i<*returned; i++) {
7091 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7092 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7095 out:
7096 for (i=0; i<*returned; i++) {
7097 SAFE_FREE(driver_info_3[i].dependentfiles);
7100 SAFE_FREE(driver_info_3);
7102 if ( !W_ERROR_IS_OK(result) )
7103 *returned = 0;
7105 return result;
7108 /****************************************************************************
7109 Enumerates all printer drivers.
7110 ****************************************************************************/
7112 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7114 uint32 level = q_u->level;
7115 RPC_BUFFER *buffer = NULL;
7116 uint32 offered = q_u->offered;
7117 uint32 *needed = &r_u->needed;
7118 uint32 *returned = &r_u->returned;
7120 fstring servername;
7121 fstring architecture;
7123 /* that's an [in out] buffer */
7125 if (!q_u->buffer && (offered!=0)) {
7126 return WERR_INVALID_PARAM;
7129 rpcbuf_move(q_u->buffer, &r_u->buffer);
7130 buffer = r_u->buffer;
7132 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7134 *needed = 0;
7135 *returned = 0;
7137 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7138 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7140 if ( !is_myname_or_ipaddr( servername ) )
7141 return WERR_UNKNOWN_PRINTER_DRIVER;
7143 switch (level) {
7144 case 1:
7145 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7146 case 2:
7147 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7148 case 3:
7149 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7150 default:
7151 return WERR_UNKNOWN_LEVEL;
7155 /****************************************************************************
7156 ****************************************************************************/
7158 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7160 form->flag=list->flag;
7161 init_unistr(&form->name, list->name);
7162 form->width=list->width;
7163 form->length=list->length;
7164 form->left=list->left;
7165 form->top=list->top;
7166 form->right=list->right;
7167 form->bottom=list->bottom;
7170 /****************************************************************************
7171 ****************************************************************************/
7173 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7175 uint32 level = q_u->level;
7176 RPC_BUFFER *buffer = NULL;
7177 uint32 offered = q_u->offered;
7178 uint32 *needed = &r_u->needed;
7179 uint32 *numofforms = &r_u->numofforms;
7180 uint32 numbuiltinforms;
7182 nt_forms_struct *list=NULL;
7183 nt_forms_struct *builtinlist=NULL;
7184 FORM_1 *forms_1;
7185 int buffer_size=0;
7186 int i;
7188 /* that's an [in out] buffer */
7190 if (!q_u->buffer && (offered!=0) ) {
7191 return WERR_INVALID_PARAM;
7194 rpcbuf_move(q_u->buffer, &r_u->buffer);
7195 buffer = r_u->buffer;
7197 DEBUG(4,("_spoolss_enumforms\n"));
7198 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7199 DEBUGADD(5,("Info level [%d]\n", level));
7201 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7202 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7203 *numofforms = get_ntforms(&list);
7204 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7205 *numofforms += numbuiltinforms;
7207 if (*numofforms == 0) {
7208 SAFE_FREE(builtinlist);
7209 SAFE_FREE(list);
7210 return WERR_NO_MORE_ITEMS;
7213 switch (level) {
7214 case 1:
7215 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7216 SAFE_FREE(builtinlist);
7217 SAFE_FREE(list);
7218 *numofforms=0;
7219 return WERR_NOMEM;
7222 /* construct the list of form structures */
7223 for (i=0; i<numbuiltinforms; i++) {
7224 DEBUGADD(6,("Filling form number [%d]\n",i));
7225 fill_form_1(&forms_1[i], &builtinlist[i]);
7228 SAFE_FREE(builtinlist);
7230 for (; i<*numofforms; i++) {
7231 DEBUGADD(6,("Filling form number [%d]\n",i));
7232 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7235 SAFE_FREE(list);
7237 /* check the required size. */
7238 for (i=0; i<numbuiltinforms; i++) {
7239 DEBUGADD(6,("adding form [%d]'s size\n",i));
7240 buffer_size += spoolss_size_form_1(&forms_1[i]);
7242 for (; i<*numofforms; i++) {
7243 DEBUGADD(6,("adding form [%d]'s size\n",i));
7244 buffer_size += spoolss_size_form_1(&forms_1[i]);
7247 *needed=buffer_size;
7249 if (*needed > offered) {
7250 SAFE_FREE(forms_1);
7251 *numofforms=0;
7252 return WERR_INSUFFICIENT_BUFFER;
7255 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7256 SAFE_FREE(forms_1);
7257 *numofforms=0;
7258 return WERR_NOMEM;
7261 /* fill the buffer with the form structures */
7262 for (i=0; i<numbuiltinforms; i++) {
7263 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7264 smb_io_form_1("", buffer, &forms_1[i], 0);
7266 for (; i<*numofforms; i++) {
7267 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7268 smb_io_form_1("", buffer, &forms_1[i], 0);
7271 SAFE_FREE(forms_1);
7273 return WERR_OK;
7275 default:
7276 SAFE_FREE(list);
7277 SAFE_FREE(builtinlist);
7278 return WERR_UNKNOWN_LEVEL;
7282 /****************************************************************************
7283 ****************************************************************************/
7285 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7287 uint32 level = q_u->level;
7288 UNISTR2 *uni_formname = &q_u->formname;
7289 RPC_BUFFER *buffer = NULL;
7290 uint32 offered = q_u->offered;
7291 uint32 *needed = &r_u->needed;
7293 nt_forms_struct *list=NULL;
7294 nt_forms_struct builtin_form;
7295 bool foundBuiltin;
7296 FORM_1 form_1;
7297 fstring form_name;
7298 int buffer_size=0;
7299 int numofforms=0, i=0;
7301 /* that's an [in out] buffer */
7303 if (!q_u->buffer && (offered!=0)) {
7304 return WERR_INVALID_PARAM;
7307 rpcbuf_move(q_u->buffer, &r_u->buffer);
7308 buffer = r_u->buffer;
7310 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7312 DEBUG(4,("_spoolss_getform\n"));
7313 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7314 DEBUGADD(5,("Info level [%d]\n", level));
7316 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7317 if (!foundBuiltin) {
7318 numofforms = get_ntforms(&list);
7319 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7321 if (numofforms == 0)
7322 return WERR_BADFID;
7325 switch (level) {
7326 case 1:
7327 if (foundBuiltin) {
7328 fill_form_1(&form_1, &builtin_form);
7329 } else {
7331 /* Check if the requested name is in the list of form structures */
7332 for (i=0; i<numofforms; i++) {
7334 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7336 if (strequal(form_name, list[i].name)) {
7337 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7338 fill_form_1(&form_1, &list[i]);
7339 break;
7343 SAFE_FREE(list);
7344 if (i == numofforms) {
7345 return WERR_BADFID;
7348 /* check the required size. */
7350 *needed=spoolss_size_form_1(&form_1);
7352 if (*needed > offered)
7353 return WERR_INSUFFICIENT_BUFFER;
7355 if (!rpcbuf_alloc_size(buffer, buffer_size))
7356 return WERR_NOMEM;
7358 /* fill the buffer with the form structures */
7359 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7360 smb_io_form_1("", buffer, &form_1, 0);
7362 return WERR_OK;
7364 default:
7365 SAFE_FREE(list);
7366 return WERR_UNKNOWN_LEVEL;
7370 /****************************************************************************
7371 ****************************************************************************/
7373 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7375 init_unistr(&port->port_name, name);
7378 /****************************************************************************
7379 TODO: This probably needs distinguish between TCP/IP and Local ports
7380 somehow.
7381 ****************************************************************************/
7383 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7385 init_unistr(&port->port_name, name);
7386 init_unistr(&port->monitor_name, "Local Monitor");
7387 init_unistr(&port->description, SPL_LOCAL_PORT );
7388 port->port_type=PORT_TYPE_WRITE;
7389 port->reserved=0x0;
7393 /****************************************************************************
7394 wrapper around the enumer ports command
7395 ****************************************************************************/
7397 WERROR enumports_hook( int *count, char ***lines )
7399 char *cmd = lp_enumports_cmd();
7400 char **qlines;
7401 pstring command;
7402 int numlines;
7403 int ret;
7404 int fd;
7406 *count = 0;
7407 *lines = NULL;
7409 /* if no hook then just fill in the default port */
7411 if ( !*cmd ) {
7412 if (!(qlines = SMB_MALLOC_ARRAY( char*, 2 ))) {
7413 return WERR_NOMEM;
7415 if (!(qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME ))) {
7416 SAFE_FREE(qlines);
7417 return WERR_NOMEM;
7419 qlines[1] = NULL;
7420 numlines = 1;
7422 else {
7423 /* we have a valid enumport command */
7425 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7427 DEBUG(10,("Running [%s]\n", command));
7428 ret = smbrun(command, &fd);
7429 DEBUG(10,("Returned [%d]\n", ret));
7430 if (ret != 0) {
7431 if (fd != -1) {
7432 close(fd);
7434 return WERR_ACCESS_DENIED;
7437 numlines = 0;
7438 qlines = fd_lines_load(fd, &numlines, 0);
7439 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7440 close(fd);
7443 *count = numlines;
7444 *lines = qlines;
7446 return WERR_OK;
7449 /****************************************************************************
7450 enumports level 1.
7451 ****************************************************************************/
7453 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7455 PORT_INFO_1 *ports=NULL;
7456 int i=0;
7457 WERROR result = WERR_OK;
7458 char **qlines = NULL;
7459 int numlines = 0;
7461 result = enumports_hook( &numlines, &qlines );
7462 if (!W_ERROR_IS_OK(result)) {
7463 file_lines_free(qlines);
7464 return result;
7467 if(numlines) {
7468 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7469 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7470 dos_errstr(WERR_NOMEM)));
7471 file_lines_free(qlines);
7472 return WERR_NOMEM;
7475 for (i=0; i<numlines; i++) {
7476 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7477 fill_port_1(&ports[i], qlines[i]);
7480 file_lines_free(qlines);
7482 *returned = numlines;
7484 /* check the required size. */
7485 for (i=0; i<*returned; i++) {
7486 DEBUGADD(6,("adding port [%d]'s size\n", i));
7487 *needed += spoolss_size_port_info_1(&ports[i]);
7490 if (*needed > offered) {
7491 result = WERR_INSUFFICIENT_BUFFER;
7492 goto out;
7495 if (!rpcbuf_alloc_size(buffer, *needed)) {
7496 result = WERR_NOMEM;
7497 goto out;
7500 /* fill the buffer with the ports structures */
7501 for (i=0; i<*returned; i++) {
7502 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7503 smb_io_port_1("", buffer, &ports[i], 0);
7506 out:
7507 SAFE_FREE(ports);
7509 if ( !W_ERROR_IS_OK(result) )
7510 *returned = 0;
7512 return result;
7515 /****************************************************************************
7516 enumports level 2.
7517 ****************************************************************************/
7519 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7521 PORT_INFO_2 *ports=NULL;
7522 int i=0;
7523 WERROR result = WERR_OK;
7524 char **qlines = NULL;
7525 int numlines = 0;
7527 result = enumports_hook( &numlines, &qlines );
7528 if ( !W_ERROR_IS_OK(result)) {
7529 file_lines_free(qlines);
7530 return result;
7533 if(numlines) {
7534 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7535 file_lines_free(qlines);
7536 return WERR_NOMEM;
7539 for (i=0; i<numlines; i++) {
7540 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7541 fill_port_2(&(ports[i]), qlines[i]);
7545 file_lines_free(qlines);
7547 *returned = numlines;
7549 /* check the required size. */
7550 for (i=0; i<*returned; i++) {
7551 DEBUGADD(6,("adding port [%d]'s size\n", i));
7552 *needed += spoolss_size_port_info_2(&ports[i]);
7555 if (*needed > offered) {
7556 result = WERR_INSUFFICIENT_BUFFER;
7557 goto out;
7560 if (!rpcbuf_alloc_size(buffer, *needed)) {
7561 result = WERR_NOMEM;
7562 goto out;
7565 /* fill the buffer with the ports structures */
7566 for (i=0; i<*returned; i++) {
7567 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7568 smb_io_port_2("", buffer, &ports[i], 0);
7571 out:
7572 SAFE_FREE(ports);
7574 if ( !W_ERROR_IS_OK(result) )
7575 *returned = 0;
7577 return result;
7580 /****************************************************************************
7581 enumports.
7582 ****************************************************************************/
7584 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7586 uint32 level = q_u->level;
7587 RPC_BUFFER *buffer = NULL;
7588 uint32 offered = q_u->offered;
7589 uint32 *needed = &r_u->needed;
7590 uint32 *returned = &r_u->returned;
7592 /* that's an [in out] buffer */
7594 if (!q_u->buffer && (offered!=0)) {
7595 return WERR_INVALID_PARAM;
7598 rpcbuf_move(q_u->buffer, &r_u->buffer);
7599 buffer = r_u->buffer;
7601 DEBUG(4,("_spoolss_enumports\n"));
7603 *returned=0;
7604 *needed=0;
7606 switch (level) {
7607 case 1:
7608 return enumports_level_1(buffer, offered, needed, returned);
7609 case 2:
7610 return enumports_level_2(buffer, offered, needed, returned);
7611 default:
7612 return WERR_UNKNOWN_LEVEL;
7616 /****************************************************************************
7617 ****************************************************************************/
7619 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7620 const SPOOL_PRINTER_INFO_LEVEL *info,
7621 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7622 uint32 user_switch, const SPOOL_USER_CTR *user,
7623 POLICY_HND *handle)
7625 NT_PRINTER_INFO_LEVEL *printer = NULL;
7626 fstring name;
7627 int snum;
7628 WERROR err = WERR_OK;
7630 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7631 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7632 return WERR_NOMEM;
7635 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7636 if (!convert_printer_info(info, printer, 2)) {
7637 free_a_printer(&printer, 2);
7638 return WERR_NOMEM;
7641 /* check to see if the printer already exists */
7643 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7644 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7645 printer->info_2->sharename));
7646 free_a_printer(&printer, 2);
7647 return WERR_PRINTER_ALREADY_EXISTS;
7650 /* FIXME!!! smbd should check to see if the driver is installed before
7651 trying to add a printer like this --jerry */
7653 if (*lp_addprinter_cmd() ) {
7654 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7655 free_a_printer(&printer,2);
7656 return WERR_ACCESS_DENIED;
7658 } else {
7659 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7660 "smb.conf parameter \"addprinter command\" is defined. This"
7661 "parameter must exist for this call to succeed\n",
7662 printer->info_2->sharename ));
7665 /* use our primary netbios name since get_a_printer() will convert
7666 it to what the client expects on a case by case basis */
7668 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7669 printer->info_2->sharename);
7672 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7673 free_a_printer(&printer,2);
7674 return WERR_ACCESS_DENIED;
7677 /* you must be a printer admin to add a new printer */
7678 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7679 free_a_printer(&printer,2);
7680 return WERR_ACCESS_DENIED;
7684 * Do sanity check on the requested changes for Samba.
7687 if (!check_printer_ok(printer->info_2, snum)) {
7688 free_a_printer(&printer,2);
7689 return WERR_INVALID_PARAM;
7693 * When a printer is created, the drivername bound to the printer is used
7694 * to lookup previously saved driver initialization info, which is then
7695 * bound to the new printer, simulating what happens in the Windows arch.
7698 if (!devmode)
7700 set_driver_init(printer, 2);
7702 else
7704 /* A valid devmode was included, convert and link it
7706 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7708 if (!convert_devicemode(printer->info_2->printername, devmode,
7709 &printer->info_2->devmode))
7710 return WERR_NOMEM;
7713 /* write the ASCII on disk */
7714 err = mod_a_printer(printer, 2);
7715 if (!W_ERROR_IS_OK(err)) {
7716 free_a_printer(&printer,2);
7717 return err;
7720 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7721 /* Handle open failed - remove addition. */
7722 del_a_printer(printer->info_2->sharename);
7723 free_a_printer(&printer,2);
7724 return WERR_ACCESS_DENIED;
7727 update_c_setprinter(False);
7728 free_a_printer(&printer,2);
7730 return WERR_OK;
7733 /****************************************************************************
7734 ****************************************************************************/
7736 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7738 UNISTR2 *uni_srv_name = q_u->server_name;
7739 uint32 level = q_u->level;
7740 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7741 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7742 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7743 uint32 user_switch = q_u->user_switch;
7744 SPOOL_USER_CTR *user = &q_u->user_ctr;
7745 POLICY_HND *handle = &r_u->handle;
7747 switch (level) {
7748 case 1:
7749 /* we don't handle yet */
7750 /* but I know what to do ... */
7751 return WERR_UNKNOWN_LEVEL;
7752 case 2:
7753 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7754 devmode, sdb,
7755 user_switch, user, handle);
7756 default:
7757 return WERR_UNKNOWN_LEVEL;
7761 /****************************************************************************
7762 ****************************************************************************/
7764 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7766 uint32 level = q_u->level;
7767 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7768 WERROR err = WERR_OK;
7769 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7770 fstring driver_name;
7771 uint32 version;
7773 ZERO_STRUCT(driver);
7775 if (!convert_printer_driver_info(info, &driver, level)) {
7776 err = WERR_NOMEM;
7777 goto done;
7780 DEBUG(5,("Cleaning driver's information\n"));
7781 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7782 if (!W_ERROR_IS_OK(err))
7783 goto done;
7785 DEBUG(5,("Moving driver to final destination\n"));
7786 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7787 goto done;
7790 if (add_a_printer_driver(driver, level)!=0) {
7791 err = WERR_ACCESS_DENIED;
7792 goto done;
7796 * I think this is where he DrvUpgradePrinter() hook would be
7797 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7798 * server. Right now, we just need to send ourselves a message
7799 * to update each printer bound to this driver. --jerry
7802 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7803 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7804 driver_name));
7808 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7809 * decide if the driver init data should be deleted. The rules are:
7810 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7811 * 2) delete init data only if there is no 2k/Xp driver
7812 * 3) always delete init data
7813 * The generalized rule is always use init data from the highest order driver.
7814 * It is necessary to follow the driver install by an initialization step to
7815 * finish off this process.
7817 if (level == 3)
7818 version = driver.info_3->cversion;
7819 else if (level == 6)
7820 version = driver.info_6->version;
7821 else
7822 version = -1;
7823 switch (version) {
7825 * 9x printer driver - never delete init data
7827 case 0:
7828 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7829 driver_name));
7830 break;
7833 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7834 * there is no 2k/Xp driver init data for this driver name.
7836 case 2:
7838 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7840 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7842 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7844 if (!del_driver_init(driver_name))
7845 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7846 } else {
7848 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7850 free_a_printer_driver(driver1,3);
7851 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7852 driver_name));
7855 break;
7858 * 2k or Xp printer driver - always delete init data
7860 case 3:
7861 if (!del_driver_init(driver_name))
7862 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7863 break;
7865 default:
7866 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7867 break;
7871 done:
7872 free_a_printer_driver(driver, level);
7873 return err;
7876 /********************************************************************
7877 * spoolss_addprinterdriverex
7878 ********************************************************************/
7880 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7882 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7883 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7886 * we only support the semantics of AddPrinterDriver()
7887 * i.e. only copy files that are newer than existing ones
7890 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7891 return WERR_ACCESS_DENIED;
7893 ZERO_STRUCT(q_u_local);
7894 ZERO_STRUCT(r_u_local);
7896 /* just pass the information off to _spoolss_addprinterdriver() */
7897 q_u_local.server_name_ptr = q_u->server_name_ptr;
7898 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7899 q_u_local.level = q_u->level;
7900 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7902 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7905 /****************************************************************************
7906 ****************************************************************************/
7908 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7910 init_unistr(&info->name, name);
7913 /****************************************************************************
7914 ****************************************************************************/
7916 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7918 pstring path;
7919 pstring long_archi;
7920 fstring servername;
7921 char *pservername;
7922 const char *short_archi;
7923 DRIVER_DIRECTORY_1 *info=NULL;
7924 WERROR result = WERR_OK;
7926 unistr2_to_ascii(servername, name, sizeof(servername));
7927 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi));
7929 /* check for beginning double '\'s and that the server
7930 long enough */
7932 pservername = servername;
7933 if ( *pservername == '\\' && strlen(servername)>2 ) {
7934 pservername += 2;
7937 if ( !is_myname_or_ipaddr( pservername ) )
7938 return WERR_INVALID_PARAM;
7940 if (!(short_archi = get_short_archi(long_archi)))
7941 return WERR_INVALID_ENVIRONMENT;
7943 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7944 return WERR_NOMEM;
7946 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7948 DEBUG(4,("printer driver directory: [%s]\n", path));
7950 fill_driverdir_1(info, path);
7952 *needed += spoolss_size_driverdir_info_1(info);
7954 if (*needed > offered) {
7955 result = WERR_INSUFFICIENT_BUFFER;
7956 goto out;
7959 if (!rpcbuf_alloc_size(buffer, *needed)) {
7960 result = WERR_NOMEM;
7961 goto out;
7964 smb_io_driverdir_1("", buffer, info, 0);
7966 out:
7967 SAFE_FREE(info);
7969 return result;
7972 /****************************************************************************
7973 ****************************************************************************/
7975 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7977 UNISTR2 *name = &q_u->name;
7978 UNISTR2 *uni_environment = &q_u->environment;
7979 uint32 level = q_u->level;
7980 RPC_BUFFER *buffer = NULL;
7981 uint32 offered = q_u->offered;
7982 uint32 *needed = &r_u->needed;
7984 /* that's an [in out] buffer */
7986 if (!q_u->buffer && (offered!=0)) {
7987 return WERR_INVALID_PARAM;
7990 rpcbuf_move(q_u->buffer, &r_u->buffer);
7991 buffer = r_u->buffer;
7993 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7995 *needed=0;
7997 switch(level) {
7998 case 1:
7999 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8000 default:
8001 return WERR_UNKNOWN_LEVEL;
8005 /****************************************************************************
8006 ****************************************************************************/
8008 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8010 POLICY_HND *handle = &q_u->handle;
8011 uint32 idx = q_u->index;
8012 uint32 in_value_len = q_u->valuesize;
8013 uint32 in_data_len = q_u->datasize;
8014 uint32 *out_max_value_len = &r_u->valuesize;
8015 uint16 **out_value = &r_u->value;
8016 uint32 *out_value_len = &r_u->realvaluesize;
8017 uint32 *out_type = &r_u->type;
8018 uint32 *out_max_data_len = &r_u->datasize;
8019 uint8 **data_out = &r_u->data;
8020 uint32 *out_data_len = &r_u->realdatasize;
8022 NT_PRINTER_INFO_LEVEL *printer = NULL;
8024 uint32 biggest_valuesize;
8025 uint32 biggest_datasize;
8026 uint32 data_len;
8027 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8028 int snum;
8029 WERROR result;
8030 REGISTRY_VALUE *val = NULL;
8031 NT_PRINTER_DATA *p_data;
8032 int i, key_index, num_values;
8033 int name_length;
8035 *out_type = 0;
8037 *out_max_data_len = 0;
8038 *data_out = NULL;
8039 *out_data_len = 0;
8041 DEBUG(5,("spoolss_enumprinterdata\n"));
8043 if (!Printer) {
8044 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8045 return WERR_BADFID;
8048 if (!get_printer_snum(p,handle, &snum, NULL))
8049 return WERR_BADFID;
8051 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8052 if (!W_ERROR_IS_OK(result))
8053 return result;
8055 p_data = printer->info_2->data;
8056 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8058 result = WERR_OK;
8061 * The NT machine wants to know the biggest size of value and data
8063 * cf: MSDN EnumPrinterData remark section
8066 if ( !in_value_len && !in_data_len && (key_index != -1) )
8068 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8070 biggest_valuesize = 0;
8071 biggest_datasize = 0;
8073 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8075 for ( i=0; i<num_values; i++ )
8077 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8079 name_length = strlen(val->valuename);
8080 if ( strlen(val->valuename) > biggest_valuesize )
8081 biggest_valuesize = name_length;
8083 if ( val->size > biggest_datasize )
8084 biggest_datasize = val->size;
8086 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8087 biggest_datasize));
8090 /* the value is an UNICODE string but real_value_size is the length
8091 in bytes including the trailing 0 */
8093 *out_value_len = 2 * (1+biggest_valuesize);
8094 *out_data_len = biggest_datasize;
8096 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8098 goto done;
8102 * the value len is wrong in NT sp3
8103 * that's the number of bytes not the number of unicode chars
8106 if ( key_index != -1 )
8107 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8109 if ( !val )
8112 /* out_value should default to "" or else NT4 has
8113 problems unmarshalling the response */
8115 *out_max_value_len=(in_value_len/sizeof(uint16));
8117 if (in_value_len) {
8118 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8120 result = WERR_NOMEM;
8121 goto done;
8123 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8124 } else {
8125 *out_value=NULL;
8126 *out_value_len = 0;
8129 /* the data is counted in bytes */
8131 *out_max_data_len = in_data_len;
8132 *out_data_len = in_data_len;
8134 /* only allocate when given a non-zero data_len */
8136 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8138 result = WERR_NOMEM;
8139 goto done;
8142 result = WERR_NO_MORE_ITEMS;
8144 else
8147 * the value is:
8148 * - counted in bytes in the request
8149 * - counted in UNICODE chars in the max reply
8150 * - counted in bytes in the real size
8152 * take a pause *before* coding not *during* coding
8155 /* name */
8156 *out_max_value_len=(in_value_len/sizeof(uint16));
8157 if (in_value_len) {
8158 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8160 result = WERR_NOMEM;
8161 goto done;
8164 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8165 } else {
8166 *out_value = NULL;
8167 *out_value_len = 0;
8170 /* type */
8172 *out_type = regval_type( val );
8174 /* data - counted in bytes */
8176 *out_max_data_len = in_data_len;
8177 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8179 result = WERR_NOMEM;
8180 goto done;
8182 data_len = regval_size(val);
8183 if ( *data_out && data_len )
8184 memcpy( *data_out, regval_data_p(val), data_len );
8185 *out_data_len = data_len;
8188 done:
8189 free_a_printer(&printer, 2);
8190 return result;
8193 /****************************************************************************
8194 ****************************************************************************/
8196 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8198 POLICY_HND *handle = &q_u->handle;
8199 UNISTR2 *value = &q_u->value;
8200 uint32 type = q_u->type;
8201 uint8 *data = q_u->data;
8202 uint32 real_len = q_u->real_len;
8204 NT_PRINTER_INFO_LEVEL *printer = NULL;
8205 int snum=0;
8206 WERROR status = WERR_OK;
8207 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8208 fstring valuename;
8210 DEBUG(5,("spoolss_setprinterdata\n"));
8212 if (!Printer) {
8213 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8214 return WERR_BADFID;
8217 if ( Printer->printer_type == SPLHND_SERVER ) {
8218 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8219 return WERR_INVALID_PARAM;
8222 if (!get_printer_snum(p,handle, &snum, NULL))
8223 return WERR_BADFID;
8226 * Access check : NT returns "access denied" if you make a
8227 * SetPrinterData call without the necessary privildge.
8228 * we were originally returning OK if nothing changed
8229 * which made Win2k issue **a lot** of SetPrinterData
8230 * when connecting to a printer --jerry
8233 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8235 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8236 status = WERR_ACCESS_DENIED;
8237 goto done;
8240 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8241 if (!W_ERROR_IS_OK(status))
8242 return status;
8244 unistr2_to_ascii(valuename, value, sizeof(valuename));
8247 * When client side code sets a magic printer data key, detect it and save
8248 * the current printer data and the magic key's data (its the DEVMODE) for
8249 * future printer/driver initializations.
8251 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8253 /* Set devmode and printer initialization info */
8254 status = save_driver_init( printer, 2, data, real_len );
8256 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8258 else
8260 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8261 type, data, real_len );
8262 if ( W_ERROR_IS_OK(status) )
8263 status = mod_a_printer(printer, 2);
8266 done:
8267 free_a_printer(&printer, 2);
8269 return status;
8272 /****************************************************************************
8273 ****************************************************************************/
8275 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8277 POLICY_HND *handle = &q_u->handle;
8278 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8279 int snum;
8281 DEBUG(5,("_spoolss_resetprinter\n"));
8284 * All we do is to check to see if the handle and queue is valid.
8285 * This call really doesn't mean anything to us because we only
8286 * support RAW printing. --jerry
8289 if (!Printer) {
8290 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8291 return WERR_BADFID;
8294 if (!get_printer_snum(p,handle, &snum, NULL))
8295 return WERR_BADFID;
8298 /* blindly return success */
8299 return WERR_OK;
8303 /****************************************************************************
8304 ****************************************************************************/
8306 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8308 POLICY_HND *handle = &q_u->handle;
8309 UNISTR2 *value = &q_u->valuename;
8311 NT_PRINTER_INFO_LEVEL *printer = NULL;
8312 int snum=0;
8313 WERROR status = WERR_OK;
8314 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8315 pstring valuename;
8317 DEBUG(5,("spoolss_deleteprinterdata\n"));
8319 if (!Printer) {
8320 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8321 return WERR_BADFID;
8324 if (!get_printer_snum(p, handle, &snum, NULL))
8325 return WERR_BADFID;
8327 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8328 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8329 return WERR_ACCESS_DENIED;
8332 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8333 if (!W_ERROR_IS_OK(status))
8334 return status;
8336 unistr2_to_ascii(valuename, value, sizeof(valuename));
8338 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8340 if ( W_ERROR_IS_OK(status) )
8341 mod_a_printer( printer, 2 );
8343 free_a_printer(&printer, 2);
8345 return status;
8348 /****************************************************************************
8349 ****************************************************************************/
8351 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8353 POLICY_HND *handle = &q_u->handle;
8354 FORM *form = &q_u->form;
8355 nt_forms_struct tmpForm;
8356 int snum;
8357 WERROR status = WERR_OK;
8358 NT_PRINTER_INFO_LEVEL *printer = NULL;
8360 int count=0;
8361 nt_forms_struct *list=NULL;
8362 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8364 DEBUG(5,("spoolss_addform\n"));
8366 if (!Printer) {
8367 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8368 return WERR_BADFID;
8372 /* forms can be added on printer of on the print server handle */
8374 if ( Printer->printer_type == SPLHND_PRINTER )
8376 if (!get_printer_snum(p,handle, &snum, NULL))
8377 return WERR_BADFID;
8379 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8380 if (!W_ERROR_IS_OK(status))
8381 goto done;
8384 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8385 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8386 status = WERR_ACCESS_DENIED;
8387 goto done;
8390 /* can't add if builtin */
8392 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8393 status = WERR_ALREADY_EXISTS;
8394 goto done;
8397 count = get_ntforms(&list);
8399 if(!add_a_form(&list, form, &count)) {
8400 status = WERR_NOMEM;
8401 goto done;
8404 write_ntforms(&list, count);
8407 * ChangeID must always be set if this is a printer
8410 if ( Printer->printer_type == SPLHND_PRINTER )
8411 status = mod_a_printer(printer, 2);
8413 done:
8414 if ( printer )
8415 free_a_printer(&printer, 2);
8416 SAFE_FREE(list);
8418 return status;
8421 /****************************************************************************
8422 ****************************************************************************/
8424 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8426 POLICY_HND *handle = &q_u->handle;
8427 UNISTR2 *form_name = &q_u->name;
8428 nt_forms_struct tmpForm;
8429 int count=0;
8430 nt_forms_struct *list=NULL;
8431 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8432 int snum;
8433 WERROR status = WERR_OK;
8434 NT_PRINTER_INFO_LEVEL *printer = NULL;
8436 DEBUG(5,("spoolss_deleteform\n"));
8438 if (!Printer) {
8439 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8440 return WERR_BADFID;
8443 /* forms can be deleted on printer of on the print server handle */
8445 if ( Printer->printer_type == SPLHND_PRINTER )
8447 if (!get_printer_snum(p,handle, &snum, NULL))
8448 return WERR_BADFID;
8450 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8451 if (!W_ERROR_IS_OK(status))
8452 goto done;
8455 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8456 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8457 status = WERR_ACCESS_DENIED;
8458 goto done;
8461 /* can't delete if builtin */
8463 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8464 status = WERR_INVALID_PARAM;
8465 goto done;
8468 count = get_ntforms(&list);
8470 if ( !delete_a_form(&list, form_name, &count, &status ))
8471 goto done;
8474 * ChangeID must always be set if this is a printer
8477 if ( Printer->printer_type == SPLHND_PRINTER )
8478 status = mod_a_printer(printer, 2);
8480 done:
8481 if ( printer )
8482 free_a_printer(&printer, 2);
8483 SAFE_FREE(list);
8485 return status;
8488 /****************************************************************************
8489 ****************************************************************************/
8491 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8493 POLICY_HND *handle = &q_u->handle;
8494 FORM *form = &q_u->form;
8495 nt_forms_struct tmpForm;
8496 int snum;
8497 WERROR status = WERR_OK;
8498 NT_PRINTER_INFO_LEVEL *printer = NULL;
8500 int count=0;
8501 nt_forms_struct *list=NULL;
8502 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8504 DEBUG(5,("spoolss_setform\n"));
8506 if (!Printer) {
8507 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8508 return WERR_BADFID;
8511 /* forms can be modified on printer of on the print server handle */
8513 if ( Printer->printer_type == SPLHND_PRINTER )
8515 if (!get_printer_snum(p,handle, &snum, NULL))
8516 return WERR_BADFID;
8518 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8519 if (!W_ERROR_IS_OK(status))
8520 goto done;
8523 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8524 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8525 status = WERR_ACCESS_DENIED;
8526 goto done;
8529 /* can't set if builtin */
8530 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8531 status = WERR_INVALID_PARAM;
8532 goto done;
8535 count = get_ntforms(&list);
8536 update_a_form(&list, form, count);
8537 write_ntforms(&list, count);
8540 * ChangeID must always be set if this is a printer
8543 if ( Printer->printer_type == SPLHND_PRINTER )
8544 status = mod_a_printer(printer, 2);
8547 done:
8548 if ( printer )
8549 free_a_printer(&printer, 2);
8550 SAFE_FREE(list);
8552 return status;
8555 /****************************************************************************
8556 enumprintprocessors level 1.
8557 ****************************************************************************/
8559 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8561 PRINTPROCESSOR_1 *info_1=NULL;
8562 WERROR result = WERR_OK;
8564 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8565 return WERR_NOMEM;
8567 (*returned) = 0x1;
8569 init_unistr(&info_1->name, "winprint");
8571 *needed += spoolss_size_printprocessor_info_1(info_1);
8573 if (*needed > offered) {
8574 result = WERR_INSUFFICIENT_BUFFER;
8575 goto out;
8578 if (!rpcbuf_alloc_size(buffer, *needed)) {
8579 result = WERR_NOMEM;
8580 goto out;
8583 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8585 out:
8586 SAFE_FREE(info_1);
8588 if ( !W_ERROR_IS_OK(result) )
8589 *returned = 0;
8591 return result;
8594 /****************************************************************************
8595 ****************************************************************************/
8597 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8599 uint32 level = q_u->level;
8600 RPC_BUFFER *buffer = NULL;
8601 uint32 offered = q_u->offered;
8602 uint32 *needed = &r_u->needed;
8603 uint32 *returned = &r_u->returned;
8605 /* that's an [in out] buffer */
8607 if (!q_u->buffer && (offered!=0)) {
8608 return WERR_INVALID_PARAM;
8611 rpcbuf_move(q_u->buffer, &r_u->buffer);
8612 buffer = r_u->buffer;
8614 DEBUG(5,("spoolss_enumprintprocessors\n"));
8617 * Enumerate the print processors ...
8619 * Just reply with "winprint", to keep NT happy
8620 * and I can use my nice printer checker.
8623 *returned=0;
8624 *needed=0;
8626 switch (level) {
8627 case 1:
8628 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8629 default:
8630 return WERR_UNKNOWN_LEVEL;
8634 /****************************************************************************
8635 enumprintprocdatatypes level 1.
8636 ****************************************************************************/
8638 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8640 PRINTPROCDATATYPE_1 *info_1=NULL;
8641 WERROR result = WERR_OK;
8643 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8644 return WERR_NOMEM;
8646 (*returned) = 0x1;
8648 init_unistr(&info_1->name, "RAW");
8650 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8652 if (*needed > offered) {
8653 result = WERR_INSUFFICIENT_BUFFER;
8654 goto out;
8657 if (!rpcbuf_alloc_size(buffer, *needed)) {
8658 result = WERR_NOMEM;
8659 goto out;
8662 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8664 out:
8665 SAFE_FREE(info_1);
8667 if ( !W_ERROR_IS_OK(result) )
8668 *returned = 0;
8670 return result;
8673 /****************************************************************************
8674 ****************************************************************************/
8676 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8678 uint32 level = q_u->level;
8679 RPC_BUFFER *buffer = NULL;
8680 uint32 offered = q_u->offered;
8681 uint32 *needed = &r_u->needed;
8682 uint32 *returned = &r_u->returned;
8684 /* that's an [in out] buffer */
8686 if (!q_u->buffer && (offered!=0)) {
8687 return WERR_INVALID_PARAM;
8690 rpcbuf_move(q_u->buffer, &r_u->buffer);
8691 buffer = r_u->buffer;
8693 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8695 *returned=0;
8696 *needed=0;
8698 switch (level) {
8699 case 1:
8700 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8701 default:
8702 return WERR_UNKNOWN_LEVEL;
8706 /****************************************************************************
8707 enumprintmonitors level 1.
8708 ****************************************************************************/
8710 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8712 PRINTMONITOR_1 *info_1;
8713 WERROR result = WERR_OK;
8714 int i;
8716 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8717 return WERR_NOMEM;
8719 *returned = 2;
8721 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8722 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8724 for ( i=0; i<*returned; i++ ) {
8725 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8728 if (*needed > offered) {
8729 result = WERR_INSUFFICIENT_BUFFER;
8730 goto out;
8733 if (!rpcbuf_alloc_size(buffer, *needed)) {
8734 result = WERR_NOMEM;
8735 goto out;
8738 for ( i=0; i<*returned; i++ ) {
8739 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8742 out:
8743 SAFE_FREE(info_1);
8745 if ( !W_ERROR_IS_OK(result) )
8746 *returned = 0;
8748 return result;
8751 /****************************************************************************
8752 enumprintmonitors level 2.
8753 ****************************************************************************/
8755 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8757 PRINTMONITOR_2 *info_2;
8758 WERROR result = WERR_OK;
8759 int i;
8761 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8762 return WERR_NOMEM;
8764 *returned = 2;
8766 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8767 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8768 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8770 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8771 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8772 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8774 for ( i=0; i<*returned; i++ ) {
8775 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8778 if (*needed > offered) {
8779 result = WERR_INSUFFICIENT_BUFFER;
8780 goto out;
8783 if (!rpcbuf_alloc_size(buffer, *needed)) {
8784 result = WERR_NOMEM;
8785 goto out;
8788 for ( i=0; i<*returned; i++ ) {
8789 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8792 out:
8793 SAFE_FREE(info_2);
8795 if ( !W_ERROR_IS_OK(result) )
8796 *returned = 0;
8798 return result;
8801 /****************************************************************************
8802 ****************************************************************************/
8804 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8806 uint32 level = q_u->level;
8807 RPC_BUFFER *buffer = NULL;
8808 uint32 offered = q_u->offered;
8809 uint32 *needed = &r_u->needed;
8810 uint32 *returned = &r_u->returned;
8812 /* that's an [in out] buffer */
8814 if (!q_u->buffer && (offered!=0)) {
8815 return WERR_INVALID_PARAM;
8818 rpcbuf_move(q_u->buffer, &r_u->buffer);
8819 buffer = r_u->buffer;
8821 DEBUG(5,("spoolss_enumprintmonitors\n"));
8824 * Enumerate the print monitors ...
8826 * Just reply with "Local Port", to keep NT happy
8827 * and I can use my nice printer checker.
8830 *returned=0;
8831 *needed=0;
8833 switch (level) {
8834 case 1:
8835 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8836 case 2:
8837 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8838 default:
8839 return WERR_UNKNOWN_LEVEL;
8843 /****************************************************************************
8844 ****************************************************************************/
8846 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8847 NT_PRINTER_INFO_LEVEL *ntprinter,
8848 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8849 uint32 *needed)
8851 int i=0;
8852 bool found=False;
8853 JOB_INFO_1 *info_1=NULL;
8854 WERROR result = WERR_OK;
8856 info_1=SMB_MALLOC_P(JOB_INFO_1);
8858 if (info_1 == NULL) {
8859 return WERR_NOMEM;
8862 for (i=0; i<count && found==False; i++) {
8863 if ((*queue)[i].job==(int)jobid)
8864 found=True;
8867 if (found==False) {
8868 SAFE_FREE(info_1);
8869 /* NT treats not found as bad param... yet another bad choice */
8870 return WERR_INVALID_PARAM;
8873 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8875 *needed += spoolss_size_job_info_1(info_1);
8877 if (*needed > offered) {
8878 result = WERR_INSUFFICIENT_BUFFER;
8879 goto out;
8882 if (!rpcbuf_alloc_size(buffer, *needed)) {
8883 result = WERR_NOMEM;
8884 goto out;
8887 smb_io_job_info_1("", buffer, info_1, 0);
8889 out:
8890 SAFE_FREE(info_1);
8892 return result;
8895 /****************************************************************************
8896 ****************************************************************************/
8898 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8899 NT_PRINTER_INFO_LEVEL *ntprinter,
8900 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8901 uint32 *needed)
8903 int i = 0;
8904 bool found = False;
8905 JOB_INFO_2 *info_2;
8906 WERROR result;
8907 DEVICEMODE *devmode = NULL;
8908 NT_DEVICEMODE *nt_devmode = NULL;
8910 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8911 return WERR_NOMEM;
8913 ZERO_STRUCTP(info_2);
8915 for ( i=0; i<count && found==False; i++ )
8917 if ((*queue)[i].job == (int)jobid)
8918 found = True;
8921 if ( !found ) {
8922 /* NT treats not found as bad param... yet another bad
8923 choice */
8924 result = WERR_INVALID_PARAM;
8925 goto done;
8929 * if the print job does not have a DEVMODE associated with it,
8930 * just use the one for the printer. A NULL devicemode is not
8931 * a failure condition
8934 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8935 devmode = construct_dev_mode(lp_const_servicename(snum));
8936 else {
8937 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8938 ZERO_STRUCTP( devmode );
8939 convert_nt_devicemode( devmode, nt_devmode );
8943 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8945 *needed += spoolss_size_job_info_2(info_2);
8947 if (*needed > offered) {
8948 result = WERR_INSUFFICIENT_BUFFER;
8949 goto done;
8952 if (!rpcbuf_alloc_size(buffer, *needed)) {
8953 result = WERR_NOMEM;
8954 goto done;
8957 smb_io_job_info_2("", buffer, info_2, 0);
8959 result = WERR_OK;
8961 done:
8962 /* Cleanup allocated memory */
8964 free_job_info_2(info_2); /* Also frees devmode */
8965 SAFE_FREE(info_2);
8967 return result;
8970 /****************************************************************************
8971 ****************************************************************************/
8973 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8975 POLICY_HND *handle = &q_u->handle;
8976 uint32 jobid = q_u->jobid;
8977 uint32 level = q_u->level;
8978 RPC_BUFFER *buffer = NULL;
8979 uint32 offered = q_u->offered;
8980 uint32 *needed = &r_u->needed;
8981 WERROR wstatus = WERR_OK;
8982 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8983 int snum;
8984 int count;
8985 print_queue_struct *queue = NULL;
8986 print_status_struct prt_status;
8988 /* that's an [in out] buffer */
8990 if (!q_u->buffer && (offered!=0)) {
8991 return WERR_INVALID_PARAM;
8994 rpcbuf_move(q_u->buffer, &r_u->buffer);
8995 buffer = r_u->buffer;
8997 DEBUG(5,("spoolss_getjob\n"));
8999 *needed = 0;
9001 if (!get_printer_snum(p, handle, &snum, NULL))
9002 return WERR_BADFID;
9004 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9005 if ( !W_ERROR_IS_OK(wstatus) )
9006 return wstatus;
9008 count = print_queue_status(snum, &queue, &prt_status);
9010 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9011 count, prt_status.status, prt_status.message));
9013 switch ( level ) {
9014 case 1:
9015 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9016 buffer, offered, needed);
9017 break;
9018 case 2:
9019 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9020 buffer, offered, needed);
9021 break;
9022 default:
9023 wstatus = WERR_UNKNOWN_LEVEL;
9024 break;
9027 SAFE_FREE(queue);
9028 free_a_printer( &ntprinter, 2 );
9030 return wstatus;
9033 /********************************************************************
9034 spoolss_getprinterdataex
9036 From MSDN documentation of GetPrinterDataEx: pass request
9037 to GetPrinterData if key is "PrinterDriverData".
9038 ********************************************************************/
9040 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9042 POLICY_HND *handle = &q_u->handle;
9043 uint32 in_size = q_u->size;
9044 uint32 *type = &r_u->type;
9045 uint32 *out_size = &r_u->size;
9046 uint8 **data = &r_u->data;
9047 uint32 *needed = &r_u->needed;
9048 fstring keyname, valuename;
9050 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9052 NT_PRINTER_INFO_LEVEL *printer = NULL;
9053 int snum = 0;
9054 WERROR status = WERR_OK;
9056 DEBUG(4,("_spoolss_getprinterdataex\n"));
9058 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9059 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9061 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9062 keyname, valuename));
9064 /* in case of problem, return some default values */
9066 *needed = 0;
9067 *type = 0;
9068 *out_size = in_size;
9070 if (!Printer) {
9071 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9072 status = WERR_BADFID;
9073 goto done;
9076 /* Is the handle to a printer or to the server? */
9078 if (Printer->printer_type == SPLHND_SERVER) {
9079 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9080 status = WERR_INVALID_PARAM;
9081 goto done;
9084 if ( !get_printer_snum(p,handle, &snum, NULL) )
9085 return WERR_BADFID;
9087 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9088 if ( !W_ERROR_IS_OK(status) )
9089 goto done;
9091 /* check to see if the keyname is valid */
9092 if ( !strlen(keyname) ) {
9093 status = WERR_INVALID_PARAM;
9094 goto done;
9097 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9098 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9099 free_a_printer( &printer, 2 );
9100 status = WERR_BADFILE;
9101 goto done;
9104 /* When given a new keyname, we should just create it */
9106 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9108 if (*needed > *out_size)
9109 status = WERR_MORE_DATA;
9111 done:
9112 if ( !W_ERROR_IS_OK(status) )
9114 DEBUG(5, ("error: allocating %d\n", *out_size));
9116 /* reply this param doesn't exist */
9118 if ( *out_size )
9120 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9121 status = WERR_NOMEM;
9122 goto done;
9124 } else {
9125 *data = NULL;
9129 if ( printer )
9130 free_a_printer( &printer, 2 );
9132 return status;
9135 /********************************************************************
9136 * spoolss_setprinterdataex
9137 ********************************************************************/
9139 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9141 POLICY_HND *handle = &q_u->handle;
9142 uint32 type = q_u->type;
9143 uint8 *data = q_u->data;
9144 uint32 real_len = q_u->real_len;
9146 NT_PRINTER_INFO_LEVEL *printer = NULL;
9147 int snum = 0;
9148 WERROR status = WERR_OK;
9149 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9150 fstring valuename;
9151 fstring keyname;
9152 char *oid_string;
9154 DEBUG(4,("_spoolss_setprinterdataex\n"));
9156 /* From MSDN documentation of SetPrinterDataEx: pass request to
9157 SetPrinterData if key is "PrinterDriverData" */
9159 if (!Printer) {
9160 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9161 return WERR_BADFID;
9164 if ( Printer->printer_type == SPLHND_SERVER ) {
9165 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9166 return WERR_INVALID_PARAM;
9169 if ( !get_printer_snum(p,handle, &snum, NULL) )
9170 return WERR_BADFID;
9173 * Access check : NT returns "access denied" if you make a
9174 * SetPrinterData call without the necessary privildge.
9175 * we were originally returning OK if nothing changed
9176 * which made Win2k issue **a lot** of SetPrinterData
9177 * when connecting to a printer --jerry
9180 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9182 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9183 return WERR_ACCESS_DENIED;
9186 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9187 if (!W_ERROR_IS_OK(status))
9188 return status;
9190 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9191 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9193 /* check for OID in valuename */
9195 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9197 *oid_string = '\0';
9198 oid_string++;
9201 /* save the registry data */
9203 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9205 if ( W_ERROR_IS_OK(status) )
9207 /* save the OID if one was specified */
9208 if ( oid_string ) {
9209 fstrcat( keyname, "\\" );
9210 fstrcat( keyname, SPOOL_OID_KEY );
9213 * I'm not checking the status here on purpose. Don't know
9214 * if this is right, but I'm returning the status from the
9215 * previous set_printer_dataex() call. I have no idea if
9216 * this is right. --jerry
9219 set_printer_dataex( printer, keyname, valuename,
9220 REG_SZ, (uint8 *)oid_string,
9221 strlen(oid_string)+1 );
9224 status = mod_a_printer(printer, 2);
9227 free_a_printer(&printer, 2);
9229 return status;
9233 /********************************************************************
9234 * spoolss_deleteprinterdataex
9235 ********************************************************************/
9237 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9239 POLICY_HND *handle = &q_u->handle;
9240 UNISTR2 *value = &q_u->valuename;
9241 UNISTR2 *key = &q_u->keyname;
9243 NT_PRINTER_INFO_LEVEL *printer = NULL;
9244 int snum=0;
9245 WERROR status = WERR_OK;
9246 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9247 pstring valuename, keyname;
9249 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9251 if (!Printer) {
9252 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9253 return WERR_BADFID;
9256 if (!get_printer_snum(p, handle, &snum, NULL))
9257 return WERR_BADFID;
9259 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9260 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9261 return WERR_ACCESS_DENIED;
9264 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9265 if (!W_ERROR_IS_OK(status))
9266 return status;
9268 unistr2_to_ascii(valuename, value, sizeof(valuename));
9269 unistr2_to_ascii(keyname, key, sizeof(keyname));
9271 status = delete_printer_dataex( printer, keyname, valuename );
9273 if ( W_ERROR_IS_OK(status) )
9274 mod_a_printer( printer, 2 );
9276 free_a_printer(&printer, 2);
9278 return status;
9281 /********************************************************************
9282 * spoolss_enumprinterkey
9283 ********************************************************************/
9286 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9288 fstring key;
9289 fstring *keynames = NULL;
9290 uint16 *enumkeys = NULL;
9291 int num_keys;
9292 int printerkey_len;
9293 POLICY_HND *handle = &q_u->handle;
9294 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9295 NT_PRINTER_DATA *data;
9296 NT_PRINTER_INFO_LEVEL *printer = NULL;
9297 int snum = 0;
9298 WERROR status = WERR_BADFILE;
9301 DEBUG(4,("_spoolss_enumprinterkey\n"));
9303 if (!Printer) {
9304 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9305 return WERR_BADFID;
9308 if ( !get_printer_snum(p,handle, &snum, NULL) )
9309 return WERR_BADFID;
9311 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9312 if (!W_ERROR_IS_OK(status))
9313 return status;
9315 /* get the list of subkey names */
9317 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9318 data = printer->info_2->data;
9320 num_keys = get_printer_subkeys( data, key, &keynames );
9322 if ( num_keys == -1 ) {
9323 status = WERR_BADFILE;
9324 goto done;
9327 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9329 r_u->needed = printerkey_len*2;
9331 if ( q_u->size < r_u->needed ) {
9332 status = WERR_MORE_DATA;
9333 goto done;
9336 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9337 status = WERR_NOMEM;
9338 goto done;
9341 status = WERR_OK;
9343 if ( q_u->size < r_u->needed )
9344 status = WERR_MORE_DATA;
9346 done:
9347 free_a_printer( &printer, 2 );
9348 SAFE_FREE( keynames );
9350 return status;
9353 /********************************************************************
9354 * spoolss_deleteprinterkey
9355 ********************************************************************/
9357 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9359 POLICY_HND *handle = &q_u->handle;
9360 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9361 fstring key;
9362 NT_PRINTER_INFO_LEVEL *printer = NULL;
9363 int snum=0;
9364 WERROR status;
9366 DEBUG(5,("spoolss_deleteprinterkey\n"));
9368 if (!Printer) {
9369 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9370 return WERR_BADFID;
9373 /* if keyname == NULL, return error */
9375 if ( !q_u->keyname.buffer )
9376 return WERR_INVALID_PARAM;
9378 if (!get_printer_snum(p, handle, &snum, NULL))
9379 return WERR_BADFID;
9381 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9382 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9383 return WERR_ACCESS_DENIED;
9386 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9387 if (!W_ERROR_IS_OK(status))
9388 return status;
9390 /* delete the key and all subneys */
9392 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9394 status = delete_all_printer_data( printer->info_2, key );
9396 if ( W_ERROR_IS_OK(status) )
9397 status = mod_a_printer(printer, 2);
9399 free_a_printer( &printer, 2 );
9401 return status;
9405 /********************************************************************
9406 * spoolss_enumprinterdataex
9407 ********************************************************************/
9409 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9411 POLICY_HND *handle = &q_u->handle;
9412 uint32 in_size = q_u->size;
9413 uint32 num_entries,
9414 needed;
9415 NT_PRINTER_INFO_LEVEL *printer = NULL;
9416 PRINTER_ENUM_VALUES *enum_values = NULL;
9417 NT_PRINTER_DATA *p_data;
9418 fstring key;
9419 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9420 int snum;
9421 WERROR result;
9422 int key_index;
9423 int i;
9424 REGISTRY_VALUE *val;
9425 char *value_name;
9426 uint32 data_len;
9429 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9431 if (!Printer) {
9432 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9433 return WERR_BADFID;
9437 * first check for a keyname of NULL or "". Win2k seems to send
9438 * this a lot and we should send back WERR_INVALID_PARAM
9439 * no need to spend time looking up the printer in this case.
9440 * --jerry
9443 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9444 if ( !strlen(key) ) {
9445 result = WERR_INVALID_PARAM;
9446 goto done;
9449 /* get the printer off of disk */
9451 if (!get_printer_snum(p,handle, &snum, NULL))
9452 return WERR_BADFID;
9454 ZERO_STRUCT(printer);
9455 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9456 if (!W_ERROR_IS_OK(result))
9457 return result;
9459 /* now look for a match on the key name */
9461 p_data = printer->info_2->data;
9463 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9464 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9466 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9467 result = WERR_INVALID_PARAM;
9468 goto done;
9471 result = WERR_OK;
9472 needed = 0;
9474 /* allocate the memory for the array of pointers -- if necessary */
9476 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9477 if ( num_entries )
9479 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9481 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9482 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9483 result = WERR_NOMEM;
9484 goto done;
9487 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9491 * loop through all params and build the array to pass
9492 * back to the client
9495 for ( i=0; i<num_entries; i++ )
9497 /* lookup the registry value */
9499 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9500 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9502 /* copy the data */
9504 value_name = regval_name( val );
9505 init_unistr( &enum_values[i].valuename, value_name );
9506 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9507 enum_values[i].type = regval_type( val );
9509 data_len = regval_size( val );
9510 if ( data_len ) {
9511 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9513 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9514 data_len ));
9515 result = WERR_NOMEM;
9516 goto done;
9519 enum_values[i].data_len = data_len;
9521 /* keep track of the size of the array in bytes */
9523 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9526 /* housekeeping information in the reply */
9528 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9529 * the hand marshalled container size is a multiple
9530 * of 4 bytes for RPC alignment.
9533 if (needed % 4) {
9534 needed += 4-(needed % 4);
9537 r_u->needed = needed;
9538 r_u->returned = num_entries;
9540 if (needed > in_size) {
9541 result = WERR_MORE_DATA;
9542 goto done;
9545 /* copy data into the reply */
9547 r_u->ctr.size = r_u->needed;
9549 r_u->ctr.size_of_array = r_u->returned;
9550 r_u->ctr.values = enum_values;
9554 done:
9555 if ( printer )
9556 free_a_printer(&printer, 2);
9558 return result;
9561 /****************************************************************************
9562 ****************************************************************************/
9564 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9566 init_unistr(&info->name, name);
9569 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9570 UNISTR2 *environment,
9571 RPC_BUFFER *buffer,
9572 uint32 offered,
9573 uint32 *needed)
9575 pstring path;
9576 pstring long_archi;
9577 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9578 WERROR result = WERR_OK;
9580 unistr2_to_ascii(long_archi, environment, sizeof(long_archi));
9582 if (!get_short_archi(long_archi))
9583 return WERR_INVALID_ENVIRONMENT;
9585 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9586 return WERR_NOMEM;
9588 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9590 fill_printprocessordirectory_1(info, path);
9592 *needed += spoolss_size_printprocessordirectory_info_1(info);
9594 if (*needed > offered) {
9595 result = WERR_INSUFFICIENT_BUFFER;
9596 goto out;
9599 if (!rpcbuf_alloc_size(buffer, *needed)) {
9600 result = WERR_INSUFFICIENT_BUFFER;
9601 goto out;
9604 smb_io_printprocessordirectory_1("", buffer, info, 0);
9606 out:
9607 SAFE_FREE(info);
9609 return result;
9612 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9614 uint32 level = q_u->level;
9615 RPC_BUFFER *buffer = NULL;
9616 uint32 offered = q_u->offered;
9617 uint32 *needed = &r_u->needed;
9618 WERROR result;
9620 /* that's an [in out] buffer */
9622 if (!q_u->buffer && (offered!=0)) {
9623 return WERR_INVALID_PARAM;
9626 rpcbuf_move(q_u->buffer, &r_u->buffer);
9627 buffer = r_u->buffer;
9629 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9631 *needed=0;
9633 switch(level) {
9634 case 1:
9635 result = getprintprocessordirectory_level_1
9636 (&q_u->name, &q_u->environment, buffer, offered, needed);
9637 break;
9638 default:
9639 result = WERR_UNKNOWN_LEVEL;
9642 return result;
9645 /*******************************************************************
9646 Streams the monitor UI DLL name in UNICODE
9647 *******************************************************************/
9649 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9650 RPC_BUFFER *out, uint32 *needed )
9652 const char *dllname = "tcpmonui.dll";
9654 *needed = (strlen(dllname)+1) * 2;
9656 if ( rpcbuf_get_size(out) < *needed ) {
9657 return WERR_INSUFFICIENT_BUFFER;
9660 if ( !make_monitorui_buf( out, dllname ) ) {
9661 return WERR_NOMEM;
9664 return WERR_OK;
9667 /*******************************************************************
9668 Create a new TCP/IP port
9669 *******************************************************************/
9671 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9672 RPC_BUFFER *out, uint32 *needed )
9674 NT_PORT_DATA_1 port1;
9675 pstring device_uri;
9677 ZERO_STRUCT( port1 );
9679 /* convert to our internal port data structure */
9681 if ( !convert_port_data_1( &port1, in ) ) {
9682 return WERR_NOMEM;
9685 /* create the device URI and call the add_port_hook() */
9687 switch ( port1.protocol ) {
9688 case PORT_PROTOCOL_DIRECT:
9689 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9690 break;
9692 case PORT_PROTOCOL_LPR:
9693 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9694 break;
9696 default:
9697 return WERR_UNKNOWN_PORT;
9700 return add_port_hook( token, port1.name, device_uri );
9703 /*******************************************************************
9704 *******************************************************************/
9706 struct xcv_api_table xcvtcp_cmds[] = {
9707 { "MonitorUI", xcvtcp_monitorui },
9708 { "AddPort", xcvtcp_addport},
9709 { NULL, NULL }
9712 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9713 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9714 uint32 *needed )
9716 int i;
9718 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9720 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9721 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9722 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9725 return WERR_BADFUNC;
9728 /*******************************************************************
9729 *******************************************************************/
9730 #if 0 /* don't support management using the "Local Port" monitor */
9732 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9733 RPC_BUFFER *out, uint32 *needed )
9735 const char *dllname = "localui.dll";
9737 *needed = (strlen(dllname)+1) * 2;
9739 if ( rpcbuf_get_size(out) < *needed ) {
9740 return WERR_INSUFFICIENT_BUFFER;
9743 if ( !make_monitorui_buf( out, dllname )) {
9744 return WERR_NOMEM;
9747 return WERR_OK;
9750 /*******************************************************************
9751 *******************************************************************/
9753 struct xcv_api_table xcvlocal_cmds[] = {
9754 { "MonitorUI", xcvlocal_monitorui },
9755 { NULL, NULL }
9757 #else
9758 struct xcv_api_table xcvlocal_cmds[] = {
9759 { NULL, NULL }
9761 #endif
9765 /*******************************************************************
9766 *******************************************************************/
9768 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9769 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9770 uint32 *needed )
9772 int i;
9774 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9776 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9777 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9778 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9780 return WERR_BADFUNC;
9783 /*******************************************************************
9784 *******************************************************************/
9786 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9788 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9789 fstring command;
9791 if (!Printer) {
9792 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9793 return WERR_BADFID;
9796 /* Has to be a handle to the TCP/IP port monitor */
9798 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9799 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9800 return WERR_BADFID;
9803 /* requires administrative access to the server */
9805 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9806 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9807 return WERR_ACCESS_DENIED;
9810 /* Get the command name. There's numerous commands supported by the
9811 TCPMON interface. */
9813 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9814 q_u->dataname.uni_str_len*2, 0);
9816 /* Allocate the outgoing buffer */
9818 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9820 switch ( Printer->printer_type ) {
9821 case SPLHND_PORTMON_TCP:
9822 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9823 &q_u->indata, &r_u->outdata, &r_u->needed );
9824 case SPLHND_PORTMON_LOCAL:
9825 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9826 &q_u->indata, &r_u->outdata, &r_u->needed );
9829 return WERR_INVALID_PRINT_MONITOR;