r21585: Start syncing the monster that will become 3.0.25pre1
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob33bfaa6cc84bb7c65e1a1cb242608e89ab3c47c1
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 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
31 extern userdom_struct current_user_info;
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
38 #endif
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
43 struct table_node {
44 const char *long_archi;
45 const char *short_archi;
46 int version;
49 static Printer_entry *printers_list;
51 typedef struct _counter_printer_0 {
52 struct _counter_printer_0 *next;
53 struct _counter_printer_0 *prev;
55 int snum;
56 uint32 counter;
57 } counter_printer_0;
59 static counter_printer_0 *counter_list;
61 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
62 static uint32 smb_connections=0;
65 /* in printing/nt_printing.c */
67 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
69 /* API table for Xcv Monitor functions */
71 struct xcv_api_table {
72 const char *name;
73 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
77 /* translate between internal status numbers and NT status numbers */
78 static int nt_printj_status(int v)
80 switch (v) {
81 case LPQ_QUEUED:
82 return 0;
83 case LPQ_PAUSED:
84 return JOB_STATUS_PAUSED;
85 case LPQ_SPOOLING:
86 return JOB_STATUS_SPOOLING;
87 case LPQ_PRINTING:
88 return JOB_STATUS_PRINTING;
89 case LPQ_ERROR:
90 return JOB_STATUS_ERROR;
91 case LPQ_DELETING:
92 return JOB_STATUS_DELETING;
93 case LPQ_OFFLINE:
94 return JOB_STATUS_OFFLINE;
95 case LPQ_PAPEROUT:
96 return JOB_STATUS_PAPEROUT;
97 case LPQ_PRINTED:
98 return JOB_STATUS_PRINTED;
99 case LPQ_DELETED:
100 return JOB_STATUS_DELETED;
101 case LPQ_BLOCKED:
102 return JOB_STATUS_BLOCKED;
103 case LPQ_USER_INTERVENTION:
104 return JOB_STATUS_USER_INTERVENTION;
106 return 0;
109 static int nt_printq_status(int v)
111 switch (v) {
112 case LPQ_PAUSED:
113 return PRINTER_STATUS_PAUSED;
114 case LPQ_QUEUED:
115 case LPQ_SPOOLING:
116 case LPQ_PRINTING:
117 return 0;
119 return 0;
122 /****************************************************************************
123 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
124 ****************************************************************************/
126 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
128 if (*pp == NULL)
129 return;
131 SAFE_FREE((*pp)->ctr.type);
132 SAFE_FREE(*pp);
135 /***************************************************************************
136 Disconnect from the client
137 ****************************************************************************/
139 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
141 WERROR result;
144 * Tell the specific printing tdb we no longer want messages for this printer
145 * by deregistering our PID.
148 if (!print_notify_deregister_pid(snum))
149 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
151 /* weird if the test succeds !!! */
152 if (smb_connections==0) {
153 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
154 return;
157 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
159 if (!W_ERROR_IS_OK(result))
160 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161 dos_errstr(result)));
163 /* if it's the last connection, deconnect the IPC$ share */
164 if (smb_connections==1) {
166 cli_shutdown( notify_cli_pipe->cli );
167 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
169 message_deregister(MSG_PRINTER_NOTIFY2);
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(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
317 if ( is_print_op )
318 unbecome_root();
320 /********** END SePrintOperatorPrivlege BLOCK **********/
322 DEBUGADD(10,("returned [%d]\n", ret));
324 if (ret != 0)
325 return WERR_BADFID; /* What to return here? */
327 /* go ahead and re-read the services immediately */
328 reload_services( False );
330 if ( lp_servicenumber( sharename ) < 0 )
331 return WERR_ACCESS_DENIED;
333 return WERR_OK;
336 /****************************************************************************
337 Delete a printer given a handle.
338 ****************************************************************************/
340 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
342 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
344 if (!Printer) {
345 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
346 return WERR_BADFID;
350 * It turns out that Windows allows delete printer on a handle
351 * opened by an admin user, then used on a pipe handle created
352 * by an anonymous user..... but they're working on security.... riiight !
353 * JRA.
356 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
357 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
358 return WERR_ACCESS_DENIED;
361 /* this does not need a become root since the access check has been
362 done on the handle already */
364 if (del_a_printer( Printer->sharename ) != 0) {
365 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
366 return WERR_BADFID;
369 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
372 /****************************************************************************
373 Return the snum of a printer corresponding to an handle.
374 ****************************************************************************/
376 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
378 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
380 if (!Printer) {
381 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
382 return False;
385 switch (Printer->printer_type) {
386 case SPLHND_PRINTER:
387 DEBUG(4,("short name:%s\n", Printer->sharename));
388 *number = print_queue_snum(Printer->sharename);
389 return (*number != -1);
390 case SPLHND_SERVER:
391 return False;
392 default:
393 return False;
397 /****************************************************************************
398 Set printer handle type.
399 Check if it's \\server or \\server\printer
400 ****************************************************************************/
402 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
404 DEBUG(3,("Setting printer type=%s\n", handlename));
406 if ( strlen(handlename) < 3 ) {
407 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
408 return False;
411 /* it's a print server */
412 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
413 DEBUGADD(4,("Printer is a print server\n"));
414 Printer->printer_type = SPLHND_SERVER;
416 /* it's a printer (set_printer_hnd_name() will handle port monitors */
417 else {
418 DEBUGADD(4,("Printer is a printer\n"));
419 Printer->printer_type = SPLHND_PRINTER;
422 return True;
425 /****************************************************************************
426 Set printer handle name.. Accept names like \\server, \\server\printer,
427 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
428 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
429 XcvDataPort() interface.
430 ****************************************************************************/
432 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
434 int snum;
435 int n_services=lp_numservices();
436 char *aprinter, *printername;
437 const char *servername;
438 fstring sname;
439 BOOL found=False;
440 NT_PRINTER_INFO_LEVEL *printer = NULL;
441 WERROR result;
443 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
445 aprinter = handlename;
446 if ( *handlename == '\\' ) {
447 servername = handlename + 2;
448 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
449 *aprinter = '\0';
450 aprinter++;
453 else {
454 servername = "";
457 /* save the servername to fill in replies on this handle */
459 if ( !is_myname_or_ipaddr( servername ) )
460 return False;
462 fstrcpy( Printer->servername, servername );
464 if ( Printer->printer_type == SPLHND_SERVER )
465 return True;
467 if ( Printer->printer_type != SPLHND_PRINTER )
468 return False;
470 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
472 /* check for the Port Monitor Interface */
474 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
475 Printer->printer_type = SPLHND_PORTMON_TCP;
476 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
477 found = True;
479 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
480 Printer->printer_type = SPLHND_PORTMON_LOCAL;
481 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
482 found = True;
485 /* Search all sharenames first as this is easier than pulling
486 the printer_info_2 off of disk. Don't use find_service() since
487 that calls out to map_username() */
489 /* do another loop to look for printernames */
491 for (snum=0; !found && snum<n_services; snum++) {
493 /* no point going on if this is not a printer */
495 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
496 continue;
498 fstrcpy(sname, lp_servicename(snum));
499 if ( strequal( aprinter, sname ) ) {
500 found = True;
501 break;
504 /* no point looking up the printer object if
505 we aren't allowing printername != sharename */
507 if ( lp_force_printername(snum) )
508 continue;
510 fstrcpy(sname, lp_servicename(snum));
512 printer = NULL;
513 result = get_a_printer( NULL, &printer, 2, sname );
514 if ( !W_ERROR_IS_OK(result) ) {
515 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
516 sname, dos_errstr(result)));
517 continue;
520 /* printername is always returned as \\server\printername */
521 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
522 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
523 printer->info_2->printername));
524 free_a_printer( &printer, 2);
525 continue;
528 printername++;
530 if ( strequal(printername, aprinter) ) {
531 free_a_printer( &printer, 2);
532 found = True;
533 break;
536 DEBUGADD(10, ("printername: %s\n", printername));
538 free_a_printer( &printer, 2);
541 free_a_printer( &printer, 2);
543 if ( !found ) {
544 DEBUGADD(4,("Printer not found\n"));
545 return False;
548 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
550 fstrcpy(Printer->sharename, sname);
552 return True;
555 /****************************************************************************
556 Find first available printer slot. creates a printer handle for you.
557 ****************************************************************************/
559 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
561 Printer_entry *new_printer;
563 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
565 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
566 return False;
568 ZERO_STRUCTP(new_printer);
570 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
571 SAFE_FREE(new_printer);
572 return False;
575 /* Add to the internal list. */
576 DLIST_ADD(printers_list, new_printer);
578 new_printer->notify.option=NULL;
580 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
581 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
582 close_printer_handle(p, hnd);
583 return False;
586 if (!set_printer_hnd_printertype(new_printer, name)) {
587 close_printer_handle(p, hnd);
588 return False;
591 if (!set_printer_hnd_name(new_printer, name)) {
592 close_printer_handle(p, hnd);
593 return False;
596 new_printer->access_granted = access_granted;
598 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
600 return True;
603 /***************************************************************************
604 check to see if the client motify handle is monitoring the notification
605 given by (notify_type, notify_field).
606 **************************************************************************/
608 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
609 uint16 notify_field)
611 return True;
614 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
615 uint16 notify_field)
617 SPOOL_NOTIFY_OPTION *option = p->notify.option;
618 uint32 i, j;
621 * Flags should always be zero when the change notify
622 * is registered by the client's spooler. A user Win32 app
623 * might use the flags though instead of the NOTIFY_OPTION_INFO
624 * --jerry
627 if (!option) {
628 return False;
631 if (p->notify.flags)
632 return is_monitoring_event_flags(
633 p->notify.flags, notify_type, notify_field);
635 for (i = 0; i < option->count; i++) {
637 /* Check match for notify_type */
639 if (option->ctr.type[i].type != notify_type)
640 continue;
642 /* Check match for field */
644 for (j = 0; j < option->ctr.type[i].count; j++) {
645 if (option->ctr.type[i].fields[j] == notify_field) {
646 return True;
651 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
652 p->servername, p->sharename, notify_type, notify_field));
654 return False;
657 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
659 static void notify_one_value(struct spoolss_notify_msg *msg,
660 SPOOL_NOTIFY_INFO_DATA *data,
661 TALLOC_CTX *mem_ctx)
663 data->notify_data.value[0] = msg->notify.value[0];
664 data->notify_data.value[1] = 0;
667 static void notify_string(struct spoolss_notify_msg *msg,
668 SPOOL_NOTIFY_INFO_DATA *data,
669 TALLOC_CTX *mem_ctx)
671 UNISTR2 unistr;
673 /* The length of the message includes the trailing \0 */
675 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
677 data->notify_data.data.length = msg->len * 2;
678 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
680 if (!data->notify_data.data.string) {
681 data->notify_data.data.length = 0;
682 return;
685 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
688 static void notify_system_time(struct spoolss_notify_msg *msg,
689 SPOOL_NOTIFY_INFO_DATA *data,
690 TALLOC_CTX *mem_ctx)
692 SYSTEMTIME systime;
693 prs_struct ps;
695 if (msg->len != sizeof(time_t)) {
696 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
697 msg->len));
698 return;
701 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
702 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
703 return;
706 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
707 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
708 prs_mem_free(&ps);
709 return;
712 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
713 prs_mem_free(&ps);
714 return;
717 data->notify_data.data.length = prs_offset(&ps);
718 data->notify_data.data.string = (uint16 *)
719 TALLOC(mem_ctx, prs_offset(&ps));
720 if (!data->notify_data.data.string) {
721 prs_mem_free(&ps);
722 return;
725 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
727 prs_mem_free(&ps);
730 struct notify2_message_table {
731 const char *name;
732 void (*fn)(struct spoolss_notify_msg *msg,
733 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
736 static struct notify2_message_table printer_notify_table[] = {
737 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
738 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
739 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
740 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
741 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
742 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
743 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
744 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
745 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
746 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
747 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
748 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
749 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
750 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
751 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
752 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
753 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
754 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
755 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
758 static struct notify2_message_table job_notify_table[] = {
759 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
760 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
761 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
762 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
763 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
764 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
765 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
766 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
767 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
768 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
769 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
770 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
771 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
772 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
773 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
774 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
775 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
776 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
777 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
778 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
779 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
780 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
781 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
782 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
786 /***********************************************************************
787 Allocate talloc context for container object
788 **********************************************************************/
790 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
792 if ( !ctr )
793 return;
795 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
797 return;
800 /***********************************************************************
801 release all allocated memory and zero out structure
802 **********************************************************************/
804 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
806 if ( !ctr )
807 return;
809 if ( ctr->ctx )
810 talloc_destroy(ctr->ctx);
812 ZERO_STRUCTP(ctr);
814 return;
817 /***********************************************************************
818 **********************************************************************/
820 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
822 if ( !ctr )
823 return NULL;
825 return ctr->ctx;
828 /***********************************************************************
829 **********************************************************************/
831 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
833 if ( !ctr || !ctr->msg_groups )
834 return NULL;
836 if ( idx >= ctr->num_groups )
837 return NULL;
839 return &ctr->msg_groups[idx];
843 /***********************************************************************
844 How many groups of change messages do we have ?
845 **********************************************************************/
847 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
849 if ( !ctr )
850 return 0;
852 return ctr->num_groups;
855 /***********************************************************************
856 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
857 **********************************************************************/
859 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
861 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
862 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
863 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
864 int i, new_slot;
866 if ( !ctr || !msg )
867 return 0;
869 /* loop over all groups looking for a matching printer name */
871 for ( i=0; i<ctr->num_groups; i++ ) {
872 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
873 break;
876 /* add a new group? */
878 if ( i == ctr->num_groups ) {
879 ctr->num_groups++;
881 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
882 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
883 return 0;
885 ctr->msg_groups = groups;
887 /* clear the new entry and set the printer name */
889 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
890 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
893 /* add the change messages; 'i' is the correct index now regardless */
895 msg_grp = &ctr->msg_groups[i];
897 msg_grp->num_msgs++;
899 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
900 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
901 return 0;
903 msg_grp->msgs = msg_list;
905 new_slot = msg_grp->num_msgs-1;
906 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
908 /* need to allocate own copy of data */
910 if ( msg->len != 0 )
911 msg_grp->msgs[new_slot].notify.data = (char *)
912 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
914 return ctr->num_groups;
917 /***********************************************************************
918 Send a change notication message on all handles which have a call
919 back registered
920 **********************************************************************/
922 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
924 Printer_entry *p;
925 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
926 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
927 SPOOLSS_NOTIFY_MSG *messages;
928 int sending_msg_count;
930 if ( !msg_group ) {
931 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
932 return;
935 messages = msg_group->msgs;
937 if ( !messages ) {
938 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
939 return;
942 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
944 /* loop over all printers */
946 for (p = printers_list; p; p = p->next) {
947 SPOOL_NOTIFY_INFO_DATA *data;
948 uint32 data_len = 0;
949 uint32 id;
950 int i;
952 /* Is there notification on this handle? */
954 if ( !p->notify.client_connected )
955 continue;
957 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
959 /* For this printer? Print servers always receive
960 notifications. */
962 if ( ( p->printer_type == SPLHND_PRINTER ) &&
963 ( !strequal(msg_group->printername, p->sharename) ) )
964 continue;
966 DEBUG(10,("Our printer\n"));
968 /* allocate the max entries possible */
970 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
971 if (!data) {
972 return;
975 ZERO_STRUCTP(data);
977 /* build the array of change notifications */
979 sending_msg_count = 0;
981 for ( i=0; i<msg_group->num_msgs; i++ ) {
982 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
984 /* Are we monitoring this event? */
986 if (!is_monitoring_event(p, msg->type, msg->field))
987 continue;
989 sending_msg_count++;
992 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
993 msg->type, msg->field, p->sharename));
996 * if the is a printer notification handle and not a job notification
997 * type, then set the id to 0. Other wise just use what was specified
998 * in the message.
1000 * When registering change notification on a print server handle
1001 * we always need to send back the id (snum) matching the printer
1002 * for which the change took place. For change notify registered
1003 * on a printer handle, this does not matter and the id should be 0.
1005 * --jerry
1008 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1009 id = 0;
1010 else
1011 id = msg->id;
1014 /* Convert unix jobid to smb jobid */
1016 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1017 id = sysjob_to_jobid(msg->id);
1019 if (id == -1) {
1020 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1021 goto done;
1025 construct_info_data( &data[data_len], msg->type, msg->field, id );
1027 switch(msg->type) {
1028 case PRINTER_NOTIFY_TYPE:
1029 if ( printer_notify_table[msg->field].fn )
1030 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1031 break;
1033 case JOB_NOTIFY_TYPE:
1034 if ( job_notify_table[msg->field].fn )
1035 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1036 break;
1038 default:
1039 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1040 goto done;
1043 data_len++;
1046 if ( sending_msg_count ) {
1047 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1048 data_len, data, p->notify.change, 0 );
1052 done:
1053 DEBUG(8,("send_notify2_changes: Exit...\n"));
1054 return;
1057 /***********************************************************************
1058 **********************************************************************/
1060 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1063 uint32 tv_sec, tv_usec;
1064 size_t offset = 0;
1066 /* Unpack message */
1068 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1069 msg->printer);
1071 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1072 &tv_sec, &tv_usec,
1073 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1075 if (msg->len == 0)
1076 tdb_unpack((char *)buf + offset, len - offset, "dd",
1077 &msg->notify.value[0], &msg->notify.value[1]);
1078 else
1079 tdb_unpack((char *)buf + offset, len - offset, "B",
1080 &msg->len, &msg->notify.data);
1082 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1083 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1085 tv->tv_sec = tv_sec;
1086 tv->tv_usec = tv_usec;
1088 if (msg->len == 0)
1089 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1090 msg->notify.value[1]));
1091 else
1092 dump_data(3, msg->notify.data, msg->len);
1094 return True;
1097 /********************************************************************
1098 Receive a notify2 message list
1099 ********************************************************************/
1101 static void receive_notify2_message_list(int msg_type, struct process_id src,
1102 void *msg, size_t len,
1103 void *private_data)
1105 size_t msg_count, i;
1106 char *buf = (char *)msg;
1107 char *msg_ptr;
1108 size_t msg_len;
1109 SPOOLSS_NOTIFY_MSG notify;
1110 SPOOLSS_NOTIFY_MSG_CTR messages;
1111 int num_groups;
1113 if (len < 4) {
1114 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1115 return;
1118 msg_count = IVAL(buf, 0);
1119 msg_ptr = buf + 4;
1121 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1123 if (msg_count == 0) {
1124 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1125 return;
1128 /* initialize the container */
1130 ZERO_STRUCT( messages );
1131 notify_msg_ctr_init( &messages );
1134 * build message groups for each printer identified
1135 * in a change_notify msg. Remember that a PCN message
1136 * includes the handle returned for the srv_spoolss_replyopenprinter()
1137 * call. Therefore messages are grouped according to printer handle.
1140 for ( i=0; i<msg_count; i++ ) {
1141 struct timeval msg_tv;
1143 if (msg_ptr + 4 - buf > len) {
1144 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1145 return;
1148 msg_len = IVAL(msg_ptr,0);
1149 msg_ptr += 4;
1151 if (msg_ptr + msg_len - buf > len) {
1152 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1153 return;
1156 /* unpack messages */
1158 ZERO_STRUCT( notify );
1159 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1160 msg_ptr += msg_len;
1162 /* add to correct list in container */
1164 notify_msg_ctr_addmsg( &messages, &notify );
1166 /* free memory that might have been allocated by notify2_unpack_msg() */
1168 if ( notify.len != 0 )
1169 SAFE_FREE( notify.notify.data );
1172 /* process each group of messages */
1174 num_groups = notify_msg_ctr_numgroups( &messages );
1175 for ( i=0; i<num_groups; i++ )
1176 send_notify2_changes( &messages, i );
1179 /* cleanup */
1181 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1183 notify_msg_ctr_destroy( &messages );
1185 return;
1188 /********************************************************************
1189 Send a message to ourself about new driver being installed
1190 so we can upgrade the information for each printer bound to this
1191 driver
1192 ********************************************************************/
1194 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1196 int len = strlen(drivername);
1198 if (!len)
1199 return False;
1201 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1202 drivername));
1204 message_send_pid(pid_to_procid(sys_getpid()),
1205 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1207 return True;
1210 /**********************************************************************
1211 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1212 over all printers, upgrading ones as necessary
1213 **********************************************************************/
1215 void do_drv_upgrade_printer(int msg_type, struct process_id src,
1216 void *buf, size_t len, void *private_data)
1218 fstring drivername;
1219 int snum;
1220 int n_services = lp_numservices();
1222 len = MIN(len,sizeof(drivername)-1);
1223 strncpy(drivername, (const char *)buf, len);
1225 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1227 /* Iterate the printer list */
1229 for (snum=0; snum<n_services; snum++)
1231 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1233 WERROR result;
1234 NT_PRINTER_INFO_LEVEL *printer = NULL;
1236 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1237 if (!W_ERROR_IS_OK(result))
1238 continue;
1240 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1242 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1244 /* all we care about currently is the change_id */
1246 result = mod_a_printer(printer, 2);
1247 if (!W_ERROR_IS_OK(result)) {
1248 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1249 dos_errstr(result)));
1253 free_a_printer(&printer, 2);
1257 /* all done */
1260 /********************************************************************
1261 Update the cache for all printq's with a registered client
1262 connection
1263 ********************************************************************/
1265 void update_monitored_printq_cache( void )
1267 Printer_entry *printer = printers_list;
1268 int snum;
1270 /* loop through all printers and update the cache where
1271 client_connected == True */
1272 while ( printer )
1274 if ( (printer->printer_type == SPLHND_PRINTER)
1275 && printer->notify.client_connected )
1277 snum = print_queue_snum(printer->sharename);
1278 print_queue_status( snum, NULL, NULL );
1281 printer = printer->next;
1284 return;
1286 /********************************************************************
1287 Send a message to ourself about new driver being installed
1288 so we can upgrade the information for each printer bound to this
1289 driver
1290 ********************************************************************/
1292 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1294 int len = strlen(drivername);
1296 if (!len)
1297 return False;
1299 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1300 drivername));
1302 message_send_pid(pid_to_procid(sys_getpid()),
1303 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1305 return True;
1308 /**********************************************************************
1309 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1310 over all printers, resetting printer data as neessary
1311 **********************************************************************/
1313 void reset_all_printerdata(int msg_type, struct process_id src,
1314 void *buf, size_t len, void *private_data)
1316 fstring drivername;
1317 int snum;
1318 int n_services = lp_numservices();
1320 len = MIN( len, sizeof(drivername)-1 );
1321 strncpy( drivername, (const char *)buf, len );
1323 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1325 /* Iterate the printer list */
1327 for ( snum=0; snum<n_services; snum++ )
1329 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1331 WERROR result;
1332 NT_PRINTER_INFO_LEVEL *printer = NULL;
1334 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1335 if ( !W_ERROR_IS_OK(result) )
1336 continue;
1339 * if the printer is bound to the driver,
1340 * then reset to the new driver initdata
1343 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1345 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1347 if ( !set_driver_init(printer, 2) ) {
1348 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1349 printer->info_2->printername, printer->info_2->drivername));
1352 result = mod_a_printer( printer, 2 );
1353 if ( !W_ERROR_IS_OK(result) ) {
1354 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1355 get_dos_error_msg(result)));
1359 free_a_printer( &printer, 2 );
1363 /* all done */
1365 return;
1368 /********************************************************************
1369 Copy routines used by convert_to_openprinterex()
1370 *******************************************************************/
1372 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1374 DEVICEMODE *d;
1375 int len;
1377 if (!devmode)
1378 return NULL;
1380 DEBUG (8,("dup_devmode\n"));
1382 /* bulk copy first */
1384 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1385 if (!d)
1386 return NULL;
1388 /* dup the pointer members separately */
1390 len = unistrlen(devmode->devicename.buffer);
1391 if (len != -1) {
1392 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1393 if (!d->devicename.buffer) {
1394 return NULL;
1396 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1397 return NULL;
1401 len = unistrlen(devmode->formname.buffer);
1402 if (len != -1) {
1403 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1404 if (!d->devicename.buffer) {
1405 return NULL;
1407 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1408 return NULL;
1411 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1412 devmode->driverextra);
1413 if (!d->dev_private) {
1414 return NULL;
1416 return d;
1419 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1421 if (!new_ctr || !ctr)
1422 return;
1424 DEBUG(8,("copy_devmode_ctr\n"));
1426 new_ctr->size = ctr->size;
1427 new_ctr->devmode_ptr = ctr->devmode_ptr;
1429 if(ctr->devmode_ptr)
1430 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1433 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1435 if (!new_def || !def)
1436 return;
1438 DEBUG(8,("copy_printer_defaults\n"));
1440 new_def->datatype_ptr = def->datatype_ptr;
1442 if (def->datatype_ptr)
1443 copy_unistr2(&new_def->datatype, &def->datatype);
1445 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1447 new_def->access_required = def->access_required;
1450 /********************************************************************
1451 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1452 * SPOOL_Q_OPEN_PRINTER_EX structure
1453 ********************************************************************/
1455 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1457 if (!q_u_ex || !q_u)
1458 return WERR_OK;
1460 DEBUG(8,("convert_to_openprinterex\n"));
1462 if ( q_u->printername ) {
1463 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1464 if (q_u_ex->printername == NULL)
1465 return WERR_NOMEM;
1466 copy_unistr2(q_u_ex->printername, q_u->printername);
1469 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1471 return WERR_OK;
1474 /********************************************************************
1475 * spoolss_open_printer
1477 * called from the spoolss dispatcher
1478 ********************************************************************/
1480 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1482 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1483 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1485 if (!q_u || !r_u)
1486 return WERR_NOMEM;
1488 ZERO_STRUCT(q_u_ex);
1489 ZERO_STRUCT(r_u_ex);
1491 /* convert the OpenPrinter() call to OpenPrinterEx() */
1493 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1494 if (!W_ERROR_IS_OK(r_u_ex.status))
1495 return r_u_ex.status;
1497 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1499 /* convert back to OpenPrinter() */
1501 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1503 return r_u->status;
1506 /********************************************************************
1507 ********************************************************************/
1509 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1511 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1512 POLICY_HND *handle = &r_u->handle;
1514 fstring name;
1515 int snum;
1516 struct current_user user;
1517 Printer_entry *Printer=NULL;
1519 if ( !q_u->printername )
1520 return WERR_INVALID_PRINTER_NAME;
1522 /* some sanity check because you can open a printer or a print server */
1523 /* aka: \\server\printer or \\server */
1525 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1527 DEBUGADD(3,("checking name: %s\n",name));
1529 if (!open_printer_hnd(p, handle, name, 0))
1530 return WERR_INVALID_PRINTER_NAME;
1532 Printer=find_printer_index_by_hnd(p, handle);
1533 if ( !Printer ) {
1534 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1535 "handle we created for printer %s\n", name ));
1536 close_printer_handle(p,handle);
1537 return WERR_INVALID_PRINTER_NAME;
1540 get_current_user(&user, p);
1543 * First case: the user is opening the print server:
1545 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1546 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1548 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1549 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1550 * or if the user is listed in the smb.conf printer admin parameter.
1552 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1553 * client view printer folder, but does not show the MSAPW.
1555 * Note: this test needs code to check access rights here too. Jeremy
1556 * could you look at this?
1558 * Second case: the user is opening a printer:
1559 * NT doesn't let us connect to a printer if the connecting user
1560 * doesn't have print permission.
1562 * Third case: user is opening a Port Monitor
1563 * access checks same as opening a handle to the print server.
1566 switch (Printer->printer_type )
1568 case SPLHND_SERVER:
1569 case SPLHND_PORTMON_TCP:
1570 case SPLHND_PORTMON_LOCAL:
1571 /* Printserver handles use global struct... */
1573 snum = -1;
1575 /* Map standard access rights to object specific access rights */
1577 se_map_standard(&printer_default->access_required,
1578 &printserver_std_mapping);
1580 /* Deny any object specific bits that don't apply to print
1581 servers (i.e printer and job specific bits) */
1583 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1585 if (printer_default->access_required &
1586 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1587 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1588 close_printer_handle(p, handle);
1589 return WERR_ACCESS_DENIED;
1592 /* Allow admin access */
1594 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1596 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1598 if (!lp_ms_add_printer_wizard()) {
1599 close_printer_handle(p, handle);
1600 return WERR_ACCESS_DENIED;
1603 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1604 and not a printer admin, then fail */
1606 if ((user.ut.uid != 0) &&
1607 !user_has_privileges(user.nt_user_token,
1608 &se_printop ) &&
1609 !token_contains_name_in_list(
1610 uidtoname(user.ut.uid), NULL,
1611 user.nt_user_token,
1612 lp_printer_admin(snum))) {
1613 close_printer_handle(p, handle);
1614 return WERR_ACCESS_DENIED;
1617 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1619 else
1621 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1624 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1625 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1627 /* We fall through to return WERR_OK */
1628 break;
1630 case SPLHND_PRINTER:
1631 /* NT doesn't let us connect to a printer if the connecting user
1632 doesn't have print permission. */
1634 if (!get_printer_snum(p, handle, &snum)) {
1635 close_printer_handle(p, handle);
1636 return WERR_BADFID;
1639 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1641 /* map an empty access mask to the minimum access mask */
1642 if (printer_default->access_required == 0x0)
1643 printer_default->access_required = PRINTER_ACCESS_USE;
1646 * If we are not serving the printer driver for this printer,
1647 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1648 * will keep NT clients happy --jerry
1651 if (lp_use_client_driver(snum)
1652 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1654 printer_default->access_required = PRINTER_ACCESS_USE;
1657 /* check smb.conf parameters and the the sec_desc */
1659 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1660 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1661 return WERR_ACCESS_DENIED;
1664 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1665 snum) ||
1666 !print_access_check(&user, snum,
1667 printer_default->access_required)) {
1668 DEBUG(3, ("access DENIED for printer open\n"));
1669 close_printer_handle(p, handle);
1670 return WERR_ACCESS_DENIED;
1673 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1674 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1675 close_printer_handle(p, handle);
1676 return WERR_ACCESS_DENIED;
1679 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1680 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1681 else
1682 printer_default->access_required = PRINTER_ACCESS_USE;
1684 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1685 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1687 break;
1689 default:
1690 /* sanity check to prevent programmer error */
1691 return WERR_BADFID;
1694 Printer->access_granted = printer_default->access_required;
1697 * If the client sent a devmode in the OpenPrinter() call, then
1698 * save it here in case we get a job submission on this handle
1701 if ( (Printer->printer_type != SPLHND_SERVER)
1702 && q_u->printer_default.devmode_cont.devmode_ptr )
1704 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1705 &Printer->nt_devmode );
1708 #if 0 /* JERRY -- I'm doubtful this is really effective */
1709 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1710 optimization in Windows 2000 clients --jerry */
1712 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1713 && (RA_WIN2K == get_remote_arch()) )
1715 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1716 sys_usleep( 500000 );
1718 #endif
1720 return WERR_OK;
1723 /****************************************************************************
1724 ****************************************************************************/
1726 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1727 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1729 BOOL ret;
1731 switch (level) {
1732 case 2:
1733 /* allocate memory if needed. Messy because
1734 convert_printer_info is used to update an existing
1735 printer or build a new one */
1737 if ( !printer->info_2 ) {
1738 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1739 if ( !printer->info_2 ) {
1740 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1741 return False;
1745 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1746 printer->info_2->setuptime = time(NULL);
1748 return ret;
1751 return False;
1754 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1755 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1757 BOOL result = True;
1759 switch (level) {
1760 case 3:
1761 printer->info_3=NULL;
1762 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1763 result = False;
1764 break;
1765 case 6:
1766 printer->info_6=NULL;
1767 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1768 result = False;
1769 break;
1770 default:
1771 break;
1774 return result;
1777 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1778 NT_DEVICEMODE **pp_nt_devmode)
1780 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1783 * Ensure nt_devmode is a valid pointer
1784 * as we will be overwriting it.
1787 if (nt_devmode == NULL) {
1788 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1789 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1790 return False;
1793 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1794 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1796 nt_devmode->specversion=devmode->specversion;
1797 nt_devmode->driverversion=devmode->driverversion;
1798 nt_devmode->size=devmode->size;
1799 nt_devmode->fields=devmode->fields;
1800 nt_devmode->orientation=devmode->orientation;
1801 nt_devmode->papersize=devmode->papersize;
1802 nt_devmode->paperlength=devmode->paperlength;
1803 nt_devmode->paperwidth=devmode->paperwidth;
1804 nt_devmode->scale=devmode->scale;
1805 nt_devmode->copies=devmode->copies;
1806 nt_devmode->defaultsource=devmode->defaultsource;
1807 nt_devmode->printquality=devmode->printquality;
1808 nt_devmode->color=devmode->color;
1809 nt_devmode->duplex=devmode->duplex;
1810 nt_devmode->yresolution=devmode->yresolution;
1811 nt_devmode->ttoption=devmode->ttoption;
1812 nt_devmode->collate=devmode->collate;
1814 nt_devmode->logpixels=devmode->logpixels;
1815 nt_devmode->bitsperpel=devmode->bitsperpel;
1816 nt_devmode->pelswidth=devmode->pelswidth;
1817 nt_devmode->pelsheight=devmode->pelsheight;
1818 nt_devmode->displayflags=devmode->displayflags;
1819 nt_devmode->displayfrequency=devmode->displayfrequency;
1820 nt_devmode->icmmethod=devmode->icmmethod;
1821 nt_devmode->icmintent=devmode->icmintent;
1822 nt_devmode->mediatype=devmode->mediatype;
1823 nt_devmode->dithertype=devmode->dithertype;
1824 nt_devmode->reserved1=devmode->reserved1;
1825 nt_devmode->reserved2=devmode->reserved2;
1826 nt_devmode->panningwidth=devmode->panningwidth;
1827 nt_devmode->panningheight=devmode->panningheight;
1830 * Only change private and driverextra if the incoming devmode
1831 * has a new one. JRA.
1834 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1835 SAFE_FREE(nt_devmode->nt_dev_private);
1836 nt_devmode->driverextra=devmode->driverextra;
1837 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1838 return False;
1839 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1842 *pp_nt_devmode = nt_devmode;
1844 return True;
1847 /********************************************************************
1848 * _spoolss_enddocprinter_internal.
1849 ********************************************************************/
1851 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1853 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1854 int snum;
1856 if (!Printer) {
1857 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1858 return WERR_BADFID;
1861 if (!get_printer_snum(p, handle, &snum))
1862 return WERR_BADFID;
1864 Printer->document_started=False;
1865 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1866 /* error codes unhandled so far ... */
1868 return WERR_OK;
1871 /********************************************************************
1872 * api_spoolss_closeprinter
1873 ********************************************************************/
1875 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1877 POLICY_HND *handle = &q_u->handle;
1879 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1881 if (Printer && Printer->document_started)
1882 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1884 if (!close_printer_handle(p, handle))
1885 return WERR_BADFID;
1887 /* clear the returned printer handle. Observed behavior
1888 from Win2k server. Don't think this really matters.
1889 Previous code just copied the value of the closed
1890 handle. --jerry */
1892 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1894 return WERR_OK;
1897 /********************************************************************
1898 * api_spoolss_deleteprinter
1900 ********************************************************************/
1902 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1904 POLICY_HND *handle = &q_u->handle;
1905 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1906 WERROR result;
1908 if (Printer && Printer->document_started)
1909 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1911 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1913 result = delete_printer_handle(p, handle);
1915 update_c_setprinter(False);
1917 return result;
1920 /*******************************************************************
1921 * static function to lookup the version id corresponding to an
1922 * long architecture string
1923 ******************************************************************/
1925 static int get_version_id (char * arch)
1927 int i;
1928 struct table_node archi_table[]= {
1930 {"Windows 4.0", "WIN40", 0 },
1931 {"Windows NT x86", "W32X86", 2 },
1932 {"Windows NT R4000", "W32MIPS", 2 },
1933 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1934 {"Windows NT PowerPC", "W32PPC", 2 },
1935 {"Windows IA64", "IA64", 3 },
1936 {"Windows x64", "x64", 3 },
1937 {NULL, "", -1 }
1940 for (i=0; archi_table[i].long_archi != NULL; i++)
1942 if (strcmp(arch, archi_table[i].long_archi) == 0)
1943 return (archi_table[i].version);
1946 return -1;
1949 /********************************************************************
1950 * _spoolss_deleteprinterdriver
1951 ********************************************************************/
1953 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1955 fstring driver;
1956 fstring arch;
1957 NT_PRINTER_DRIVER_INFO_LEVEL info;
1958 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1959 int version;
1960 struct current_user user;
1961 WERROR status;
1962 WERROR status_win2k = WERR_ACCESS_DENIED;
1963 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1965 get_current_user(&user, p);
1967 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1968 and not a printer admin, then fail */
1970 if ( (user.ut.uid != 0)
1971 && !user_has_privileges(user.nt_user_token, &se_printop )
1972 && !token_contains_name_in_list( uidtoname(user.ut.uid),
1973 NULL, user.nt_user_token, lp_printer_admin(-1)) )
1975 return WERR_ACCESS_DENIED;
1978 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1979 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1981 /* check that we have a valid driver name first */
1983 if ((version=get_version_id(arch)) == -1)
1984 return WERR_INVALID_ENVIRONMENT;
1986 ZERO_STRUCT(info);
1987 ZERO_STRUCT(info_win2k);
1989 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1991 /* try for Win2k driver if "Windows NT x86" */
1993 if ( version == 2 ) {
1994 version = 3;
1995 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1996 status = WERR_UNKNOWN_PRINTER_DRIVER;
1997 goto done;
2000 /* otherwise it was a failure */
2001 else {
2002 status = WERR_UNKNOWN_PRINTER_DRIVER;
2003 goto done;
2008 if (printer_driver_in_use(info.info_3)) {
2009 status = WERR_PRINTER_DRIVER_IN_USE;
2010 goto done;
2013 if ( version == 2 )
2015 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2017 /* if we get to here, we now have 2 driver info structures to remove */
2018 /* remove the Win2k driver first*/
2020 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2021 free_a_printer_driver( info_win2k, 3 );
2023 /* this should not have failed---if it did, report to client */
2024 if ( !W_ERROR_IS_OK(status_win2k) )
2026 status = status_win2k;
2027 goto done;
2032 status = delete_printer_driver(info.info_3, &user, version, False);
2034 /* if at least one of the deletes succeeded return OK */
2036 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2037 status = WERR_OK;
2039 done:
2040 free_a_printer_driver( info, 3 );
2042 return status;
2045 /********************************************************************
2046 * spoolss_deleteprinterdriverex
2047 ********************************************************************/
2049 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2051 fstring driver;
2052 fstring arch;
2053 NT_PRINTER_DRIVER_INFO_LEVEL info;
2054 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2055 int version;
2056 uint32 flags = q_u->delete_flags;
2057 BOOL delete_files;
2058 struct current_user user;
2059 WERROR status;
2060 WERROR status_win2k = WERR_ACCESS_DENIED;
2061 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2063 get_current_user(&user, p);
2065 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2066 and not a printer admin, then fail */
2068 if ( (user.ut.uid != 0)
2069 && !user_has_privileges(user.nt_user_token, &se_printop )
2070 && !token_contains_name_in_list( uidtoname(user.ut.uid),
2071 NULL, user.nt_user_token, lp_printer_admin(-1)) )
2073 return WERR_ACCESS_DENIED;
2076 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2077 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2079 /* check that we have a valid driver name first */
2080 if ((version=get_version_id(arch)) == -1) {
2081 /* this is what NT returns */
2082 return WERR_INVALID_ENVIRONMENT;
2085 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2086 version = q_u->version;
2088 ZERO_STRUCT(info);
2089 ZERO_STRUCT(info_win2k);
2091 status = get_a_printer_driver(&info, 3, driver, arch, version);
2093 if ( !W_ERROR_IS_OK(status) )
2096 * if the client asked for a specific version,
2097 * or this is something other than Windows NT x86,
2098 * then we've failed
2101 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2102 goto done;
2104 /* try for Win2k driver if "Windows NT x86" */
2106 version = 3;
2107 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2108 status = WERR_UNKNOWN_PRINTER_DRIVER;
2109 goto done;
2113 if ( printer_driver_in_use(info.info_3) ) {
2114 status = WERR_PRINTER_DRIVER_IN_USE;
2115 goto done;
2119 * we have a couple of cases to consider.
2120 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2121 * then the delete should fail if **any** files overlap with
2122 * other drivers
2123 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2124 * non-overlapping files
2125 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2126 * is set, the do not delete any files
2127 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2130 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2132 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2134 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2135 /* no idea of the correct error here */
2136 status = WERR_ACCESS_DENIED;
2137 goto done;
2141 /* also check for W32X86/3 if necessary; maybe we already have? */
2143 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2144 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2147 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2148 /* no idea of the correct error here */
2149 free_a_printer_driver( info_win2k, 3 );
2150 status = WERR_ACCESS_DENIED;
2151 goto done;
2154 /* if we get to here, we now have 2 driver info structures to remove */
2155 /* remove the Win2k driver first*/
2157 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2158 free_a_printer_driver( info_win2k, 3 );
2160 /* this should not have failed---if it did, report to client */
2162 if ( !W_ERROR_IS_OK(status_win2k) )
2163 goto done;
2167 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2169 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2170 status = WERR_OK;
2171 done:
2172 free_a_printer_driver( info, 3 );
2174 return status;
2178 /****************************************************************************
2179 Internal routine for retreiving printerdata
2180 ***************************************************************************/
2182 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2183 const char *key, const char *value, uint32 *type, uint8 **data,
2184 uint32 *needed, uint32 in_size )
2186 REGISTRY_VALUE *val;
2187 uint32 size;
2188 int data_len;
2190 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2191 return WERR_BADFILE;
2193 *type = regval_type( val );
2195 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2197 size = regval_size( val );
2199 /* copy the min(in_size, len) */
2201 if ( in_size ) {
2202 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2204 /* special case for 0 length values */
2205 if ( data_len ) {
2206 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2207 return WERR_NOMEM;
2209 else {
2210 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2211 return WERR_NOMEM;
2214 else
2215 *data = NULL;
2217 *needed = size;
2219 DEBUG(5,("get_printer_dataex: copy done\n"));
2221 return WERR_OK;
2224 /****************************************************************************
2225 Internal routine for removing printerdata
2226 ***************************************************************************/
2228 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2230 return delete_printer_data( printer->info_2, key, value );
2233 /****************************************************************************
2234 Internal routine for storing printerdata
2235 ***************************************************************************/
2237 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2238 uint32 type, uint8 *data, int real_len )
2240 /* the registry objects enforce uniqueness based on value name */
2242 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2245 /********************************************************************
2246 GetPrinterData on a printer server Handle.
2247 ********************************************************************/
2249 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2251 int i;
2253 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2255 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2256 *type = REG_DWORD;
2257 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2258 return WERR_NOMEM;
2259 *needed = 0x4;
2260 return WERR_OK;
2263 if (!StrCaseCmp(value, "BeepEnabled")) {
2264 *type = REG_DWORD;
2265 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2266 return WERR_NOMEM;
2267 SIVAL(*data, 0, 0x00);
2268 *needed = 0x4;
2269 return WERR_OK;
2272 if (!StrCaseCmp(value, "EventLog")) {
2273 *type = REG_DWORD;
2274 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2275 return WERR_NOMEM;
2276 /* formally was 0x1b */
2277 SIVAL(*data, 0, 0x0);
2278 *needed = 0x4;
2279 return WERR_OK;
2282 if (!StrCaseCmp(value, "NetPopup")) {
2283 *type = REG_DWORD;
2284 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2285 return WERR_NOMEM;
2286 SIVAL(*data, 0, 0x00);
2287 *needed = 0x4;
2288 return WERR_OK;
2291 if (!StrCaseCmp(value, "MajorVersion")) {
2292 *type = REG_DWORD;
2293 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2294 return WERR_NOMEM;
2296 /* Windows NT 4.0 seems to not allow uploading of drivers
2297 to a server that reports 0x3 as the MajorVersion.
2298 need to investigate more how Win2k gets around this .
2299 -- jerry */
2301 if ( RA_WINNT == get_remote_arch() )
2302 SIVAL(*data, 0, 2);
2303 else
2304 SIVAL(*data, 0, 3);
2306 *needed = 0x4;
2307 return WERR_OK;
2310 if (!StrCaseCmp(value, "MinorVersion")) {
2311 *type = REG_DWORD;
2312 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2313 return WERR_NOMEM;
2314 SIVAL(*data, 0, 0);
2315 *needed = 0x4;
2316 return WERR_OK;
2319 /* REG_BINARY
2320 * uint32 size = 0x114
2321 * uint32 major = 5
2322 * uint32 minor = [0|1]
2323 * uint32 build = [2195|2600]
2324 * extra unicode string = e.g. "Service Pack 3"
2326 if (!StrCaseCmp(value, "OSVersion")) {
2327 *type = REG_BINARY;
2328 *needed = 0x114;
2330 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2331 return WERR_NOMEM;
2333 SIVAL(*data, 0, *needed); /* size */
2334 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2335 SIVAL(*data, 8, 0);
2336 SIVAL(*data, 12, 2195); /* build */
2338 /* leave extra string empty */
2340 return WERR_OK;
2344 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2345 const char *string="C:\\PRINTERS";
2346 *type = REG_SZ;
2347 *needed = 2*(strlen(string)+1);
2348 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2349 return WERR_NOMEM;
2350 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2352 /* it's done by hand ready to go on the wire */
2353 for (i=0; i<strlen(string); i++) {
2354 (*data)[2*i]=string[i];
2355 (*data)[2*i+1]='\0';
2357 return WERR_OK;
2360 if (!StrCaseCmp(value, "Architecture")) {
2361 const char *string="Windows NT x86";
2362 *type = REG_SZ;
2363 *needed = 2*(strlen(string)+1);
2364 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2365 return WERR_NOMEM;
2366 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2367 for (i=0; i<strlen(string); i++) {
2368 (*data)[2*i]=string[i];
2369 (*data)[2*i+1]='\0';
2371 return WERR_OK;
2374 if (!StrCaseCmp(value, "DsPresent")) {
2375 *type = REG_DWORD;
2376 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2377 return WERR_NOMEM;
2379 /* only show the publish check box if we are a
2380 memeber of a AD domain */
2382 if ( lp_security() == SEC_ADS )
2383 SIVAL(*data, 0, 0x01);
2384 else
2385 SIVAL(*data, 0, 0x00);
2387 *needed = 0x4;
2388 return WERR_OK;
2391 if (!StrCaseCmp(value, "DNSMachineName")) {
2392 pstring hostname;
2394 if (!get_mydnsfullname(hostname))
2395 return WERR_BADFILE;
2396 *type = REG_SZ;
2397 *needed = 2*(strlen(hostname)+1);
2398 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2399 return WERR_NOMEM;
2400 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2401 for (i=0; i<strlen(hostname); i++) {
2402 (*data)[2*i]=hostname[i];
2403 (*data)[2*i+1]='\0';
2405 return WERR_OK;
2409 return WERR_BADFILE;
2412 /********************************************************************
2413 * spoolss_getprinterdata
2414 ********************************************************************/
2416 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2418 POLICY_HND *handle = &q_u->handle;
2419 UNISTR2 *valuename = &q_u->valuename;
2420 uint32 in_size = q_u->size;
2421 uint32 *type = &r_u->type;
2422 uint32 *out_size = &r_u->size;
2423 uint8 **data = &r_u->data;
2424 uint32 *needed = &r_u->needed;
2425 WERROR status;
2426 fstring value;
2427 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2428 NT_PRINTER_INFO_LEVEL *printer = NULL;
2429 int snum = 0;
2432 * Reminder: when it's a string, the length is in BYTES
2433 * even if UNICODE is negociated.
2435 * JFM, 4/19/1999
2438 *out_size = in_size;
2440 /* in case of problem, return some default values */
2442 *needed = 0;
2443 *type = 0;
2445 DEBUG(4,("_spoolss_getprinterdata\n"));
2447 if ( !Printer ) {
2448 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2449 status = WERR_BADFID;
2450 goto done;
2453 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2455 if ( Printer->printer_type == SPLHND_SERVER )
2456 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2457 else
2459 if ( !get_printer_snum(p,handle, &snum) ) {
2460 status = WERR_BADFID;
2461 goto done;
2464 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2465 if ( !W_ERROR_IS_OK(status) )
2466 goto done;
2468 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2470 if ( strequal(value, "ChangeId") ) {
2471 *type = REG_DWORD;
2472 *needed = sizeof(uint32);
2473 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2474 status = WERR_NOMEM;
2475 goto done;
2477 SIVAL( *data, 0, printer->info_2->changeid );
2478 status = WERR_OK;
2480 else
2481 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2484 if (*needed > *out_size)
2485 status = WERR_MORE_DATA;
2487 done:
2488 if ( !W_ERROR_IS_OK(status) )
2490 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2492 /* reply this param doesn't exist */
2494 if ( *out_size ) {
2495 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2496 if ( printer )
2497 free_a_printer( &printer, 2 );
2498 return WERR_NOMEM;
2501 else {
2502 *data = NULL;
2506 /* cleanup & exit */
2508 if ( printer )
2509 free_a_printer( &printer, 2 );
2511 return status;
2514 /*********************************************************
2515 Connect to the client machine.
2516 **********************************************************/
2518 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2519 struct in_addr *client_ip, const char *remote_machine)
2521 NTSTATUS ret;
2522 struct cli_state *the_cli;
2523 struct in_addr rm_addr;
2525 if ( is_zero_ip(*client_ip) ) {
2526 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2527 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2528 return False;
2531 if ( ismyip( rm_addr )) {
2532 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2533 return False;
2535 } else {
2536 rm_addr.s_addr = client_ip->s_addr;
2537 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2538 inet_ntoa(*client_ip) ));
2541 /* setup the connection */
2543 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2544 &rm_addr, 0, "IPC$", "IPC",
2545 "", /* username */
2546 "", /* domain */
2547 "", /* password */
2548 0, lp_client_signing(), NULL );
2550 if ( !NT_STATUS_IS_OK( ret ) ) {
2551 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2552 remote_machine ));
2553 return False;
2556 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2557 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2558 cli_shutdown(the_cli);
2559 return False;
2563 * Ok - we have an anonymous connection to the IPC$ share.
2564 * Now start the NT Domain stuff :-).
2567 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2568 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2569 remote_machine, nt_errstr(ret)));
2570 cli_shutdown(the_cli);
2571 return False;
2574 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2576 (*pp_pipe)->cli = the_cli;
2578 return True;
2581 /***************************************************************************
2582 Connect to the client.
2583 ****************************************************************************/
2585 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2586 uint32 localprinter, uint32 type,
2587 POLICY_HND *handle, struct in_addr *client_ip)
2589 WERROR result;
2592 * If it's the first connection, contact the client
2593 * and connect to the IPC$ share anonymously
2595 if (smb_connections==0) {
2596 fstring unix_printer;
2598 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2600 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ip, unix_printer ))
2601 return False;
2603 message_register(MSG_PRINTER_NOTIFY2,
2604 receive_notify2_message_list, NULL);
2605 /* Tell the connections db we're now interested in printer
2606 * notify messages. */
2607 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2611 * Tell the specific printing tdb we want messages for this printer
2612 * by registering our PID.
2615 if (!print_notify_register_pid(snum))
2616 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2618 smb_connections++;
2620 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2621 type, handle);
2623 if (!W_ERROR_IS_OK(result))
2624 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2625 dos_errstr(result)));
2627 return (W_ERROR_IS_OK(result));
2630 /********************************************************************
2631 * _spoolss_rffpcnex
2632 * ReplyFindFirstPrinterChangeNotifyEx
2634 * before replying OK: status=0 a rpc call is made to the workstation
2635 * asking ReplyOpenPrinter
2637 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2638 * called from api_spoolss_rffpcnex
2639 ********************************************************************/
2641 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2643 POLICY_HND *handle = &q_u->handle;
2644 uint32 flags = q_u->flags;
2645 uint32 options = q_u->options;
2646 UNISTR2 *localmachine = &q_u->localmachine;
2647 uint32 printerlocal = q_u->printerlocal;
2648 int snum = -1;
2649 SPOOL_NOTIFY_OPTION *option = q_u->option;
2650 struct in_addr client_ip;
2652 /* store the notify value in the printer struct */
2654 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2656 if (!Printer) {
2657 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2658 return WERR_BADFID;
2661 Printer->notify.flags=flags;
2662 Printer->notify.options=options;
2663 Printer->notify.printerlocal=printerlocal;
2665 if (Printer->notify.option)
2666 free_spool_notify_option(&Printer->notify.option);
2668 Printer->notify.option=dup_spool_notify_option(option);
2670 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2671 sizeof(Printer->notify.localmachine)-1);
2673 /* Connect to the client machine and send a ReplyOpenPrinter */
2675 if ( Printer->printer_type == SPLHND_SERVER)
2676 snum = -1;
2677 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2678 !get_printer_snum(p, handle, &snum) )
2679 return WERR_BADFID;
2681 client_ip.s_addr = inet_addr(p->conn->client_address);
2683 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2684 Printer->notify.printerlocal, 1,
2685 &Printer->notify.client_hnd, &client_ip))
2686 return WERR_SERVER_UNAVAILABLE;
2688 Printer->notify.client_connected=True;
2690 return WERR_OK;
2693 /*******************************************************************
2694 * fill a notify_info_data with the servername
2695 ********************************************************************/
2697 void spoolss_notify_server_name(int snum,
2698 SPOOL_NOTIFY_INFO_DATA *data,
2699 print_queue_struct *queue,
2700 NT_PRINTER_INFO_LEVEL *printer,
2701 TALLOC_CTX *mem_ctx)
2703 pstring temp;
2704 uint32 len;
2706 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2708 data->notify_data.data.length = len;
2709 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2711 if (!data->notify_data.data.string) {
2712 data->notify_data.data.length = 0;
2713 return;
2716 memcpy(data->notify_data.data.string, temp, len);
2719 /*******************************************************************
2720 * fill a notify_info_data with the printername (not including the servername).
2721 ********************************************************************/
2723 void spoolss_notify_printer_name(int snum,
2724 SPOOL_NOTIFY_INFO_DATA *data,
2725 print_queue_struct *queue,
2726 NT_PRINTER_INFO_LEVEL *printer,
2727 TALLOC_CTX *mem_ctx)
2729 pstring temp;
2730 uint32 len;
2732 /* the notify name should not contain the \\server\ part */
2733 char *p = strrchr(printer->info_2->printername, '\\');
2735 if (!p) {
2736 p = printer->info_2->printername;
2737 } else {
2738 p++;
2741 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2743 data->notify_data.data.length = len;
2744 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2746 if (!data->notify_data.data.string) {
2747 data->notify_data.data.length = 0;
2748 return;
2751 memcpy(data->notify_data.data.string, temp, len);
2754 /*******************************************************************
2755 * fill a notify_info_data with the servicename
2756 ********************************************************************/
2758 void spoolss_notify_share_name(int snum,
2759 SPOOL_NOTIFY_INFO_DATA *data,
2760 print_queue_struct *queue,
2761 NT_PRINTER_INFO_LEVEL *printer,
2762 TALLOC_CTX *mem_ctx)
2764 pstring temp;
2765 uint32 len;
2767 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2769 data->notify_data.data.length = len;
2770 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2772 if (!data->notify_data.data.string) {
2773 data->notify_data.data.length = 0;
2774 return;
2777 memcpy(data->notify_data.data.string, temp, len);
2780 /*******************************************************************
2781 * fill a notify_info_data with the port name
2782 ********************************************************************/
2784 void spoolss_notify_port_name(int snum,
2785 SPOOL_NOTIFY_INFO_DATA *data,
2786 print_queue_struct *queue,
2787 NT_PRINTER_INFO_LEVEL *printer,
2788 TALLOC_CTX *mem_ctx)
2790 pstring temp;
2791 uint32 len;
2793 /* even if it's strange, that's consistant in all the code */
2795 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2797 data->notify_data.data.length = len;
2798 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2800 if (!data->notify_data.data.string) {
2801 data->notify_data.data.length = 0;
2802 return;
2805 memcpy(data->notify_data.data.string, temp, len);
2808 /*******************************************************************
2809 * fill a notify_info_data with the printername
2810 * but it doesn't exist, have to see what to do
2811 ********************************************************************/
2813 void spoolss_notify_driver_name(int snum,
2814 SPOOL_NOTIFY_INFO_DATA *data,
2815 print_queue_struct *queue,
2816 NT_PRINTER_INFO_LEVEL *printer,
2817 TALLOC_CTX *mem_ctx)
2819 pstring temp;
2820 uint32 len;
2822 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2824 data->notify_data.data.length = len;
2825 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2827 if (!data->notify_data.data.string) {
2828 data->notify_data.data.length = 0;
2829 return;
2832 memcpy(data->notify_data.data.string, temp, len);
2835 /*******************************************************************
2836 * fill a notify_info_data with the comment
2837 ********************************************************************/
2839 void spoolss_notify_comment(int snum,
2840 SPOOL_NOTIFY_INFO_DATA *data,
2841 print_queue_struct *queue,
2842 NT_PRINTER_INFO_LEVEL *printer,
2843 TALLOC_CTX *mem_ctx)
2845 pstring temp;
2846 uint32 len;
2848 if (*printer->info_2->comment == '\0')
2849 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2850 else
2851 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2853 data->notify_data.data.length = len;
2854 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2856 if (!data->notify_data.data.string) {
2857 data->notify_data.data.length = 0;
2858 return;
2861 memcpy(data->notify_data.data.string, temp, len);
2864 /*******************************************************************
2865 * fill a notify_info_data with the comment
2866 * location = "Room 1, floor 2, building 3"
2867 ********************************************************************/
2869 void spoolss_notify_location(int snum,
2870 SPOOL_NOTIFY_INFO_DATA *data,
2871 print_queue_struct *queue,
2872 NT_PRINTER_INFO_LEVEL *printer,
2873 TALLOC_CTX *mem_ctx)
2875 pstring temp;
2876 uint32 len;
2878 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2880 data->notify_data.data.length = len;
2881 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2883 if (!data->notify_data.data.string) {
2884 data->notify_data.data.length = 0;
2885 return;
2888 memcpy(data->notify_data.data.string, temp, len);
2891 /*******************************************************************
2892 * fill a notify_info_data with the device mode
2893 * jfm:xxxx don't to it for know but that's a real problem !!!
2894 ********************************************************************/
2896 static void spoolss_notify_devmode(int snum,
2897 SPOOL_NOTIFY_INFO_DATA *data,
2898 print_queue_struct *queue,
2899 NT_PRINTER_INFO_LEVEL *printer,
2900 TALLOC_CTX *mem_ctx)
2902 /* for a dummy implementation we have to zero the fields */
2903 data->notify_data.data.length = 0;
2904 data->notify_data.data.string = NULL;
2907 /*******************************************************************
2908 * fill a notify_info_data with the separator file name
2909 ********************************************************************/
2911 void spoolss_notify_sepfile(int snum,
2912 SPOOL_NOTIFY_INFO_DATA *data,
2913 print_queue_struct *queue,
2914 NT_PRINTER_INFO_LEVEL *printer,
2915 TALLOC_CTX *mem_ctx)
2917 pstring temp;
2918 uint32 len;
2920 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2922 data->notify_data.data.length = len;
2923 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2925 if (!data->notify_data.data.string) {
2926 data->notify_data.data.length = 0;
2927 return;
2930 memcpy(data->notify_data.data.string, temp, len);
2933 /*******************************************************************
2934 * fill a notify_info_data with the print processor
2935 * jfm:xxxx return always winprint to indicate we don't do anything to it
2936 ********************************************************************/
2938 void spoolss_notify_print_processor(int snum,
2939 SPOOL_NOTIFY_INFO_DATA *data,
2940 print_queue_struct *queue,
2941 NT_PRINTER_INFO_LEVEL *printer,
2942 TALLOC_CTX *mem_ctx)
2944 pstring temp;
2945 uint32 len;
2947 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2949 data->notify_data.data.length = len;
2950 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2952 if (!data->notify_data.data.string) {
2953 data->notify_data.data.length = 0;
2954 return;
2957 memcpy(data->notify_data.data.string, temp, len);
2960 /*******************************************************************
2961 * fill a notify_info_data with the print processor options
2962 * jfm:xxxx send an empty string
2963 ********************************************************************/
2965 void spoolss_notify_parameters(int snum,
2966 SPOOL_NOTIFY_INFO_DATA *data,
2967 print_queue_struct *queue,
2968 NT_PRINTER_INFO_LEVEL *printer,
2969 TALLOC_CTX *mem_ctx)
2971 pstring temp;
2972 uint32 len;
2974 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2976 data->notify_data.data.length = len;
2977 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2979 if (!data->notify_data.data.string) {
2980 data->notify_data.data.length = 0;
2981 return;
2984 memcpy(data->notify_data.data.string, temp, len);
2987 /*******************************************************************
2988 * fill a notify_info_data with the data type
2989 * jfm:xxxx always send RAW as data type
2990 ********************************************************************/
2992 void spoolss_notify_datatype(int snum,
2993 SPOOL_NOTIFY_INFO_DATA *data,
2994 print_queue_struct *queue,
2995 NT_PRINTER_INFO_LEVEL *printer,
2996 TALLOC_CTX *mem_ctx)
2998 pstring temp;
2999 uint32 len;
3001 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3003 data->notify_data.data.length = len;
3004 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3006 if (!data->notify_data.data.string) {
3007 data->notify_data.data.length = 0;
3008 return;
3011 memcpy(data->notify_data.data.string, temp, len);
3014 /*******************************************************************
3015 * fill a notify_info_data with the security descriptor
3016 * jfm:xxxx send an null pointer to say no security desc
3017 * have to implement security before !
3018 ********************************************************************/
3020 static void spoolss_notify_security_desc(int snum,
3021 SPOOL_NOTIFY_INFO_DATA *data,
3022 print_queue_struct *queue,
3023 NT_PRINTER_INFO_LEVEL *printer,
3024 TALLOC_CTX *mem_ctx)
3026 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3027 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3030 /*******************************************************************
3031 * fill a notify_info_data with the attributes
3032 * jfm:xxxx a samba printer is always shared
3033 ********************************************************************/
3035 void spoolss_notify_attributes(int snum,
3036 SPOOL_NOTIFY_INFO_DATA *data,
3037 print_queue_struct *queue,
3038 NT_PRINTER_INFO_LEVEL *printer,
3039 TALLOC_CTX *mem_ctx)
3041 data->notify_data.value[0] = printer->info_2->attributes;
3042 data->notify_data.value[1] = 0;
3045 /*******************************************************************
3046 * fill a notify_info_data with the priority
3047 ********************************************************************/
3049 static void spoolss_notify_priority(int snum,
3050 SPOOL_NOTIFY_INFO_DATA *data,
3051 print_queue_struct *queue,
3052 NT_PRINTER_INFO_LEVEL *printer,
3053 TALLOC_CTX *mem_ctx)
3055 data->notify_data.value[0] = printer->info_2->priority;
3056 data->notify_data.value[1] = 0;
3059 /*******************************************************************
3060 * fill a notify_info_data with the default priority
3061 ********************************************************************/
3063 static void spoolss_notify_default_priority(int snum,
3064 SPOOL_NOTIFY_INFO_DATA *data,
3065 print_queue_struct *queue,
3066 NT_PRINTER_INFO_LEVEL *printer,
3067 TALLOC_CTX *mem_ctx)
3069 data->notify_data.value[0] = printer->info_2->default_priority;
3070 data->notify_data.value[1] = 0;
3073 /*******************************************************************
3074 * fill a notify_info_data with the start time
3075 ********************************************************************/
3077 static void spoolss_notify_start_time(int snum,
3078 SPOOL_NOTIFY_INFO_DATA *data,
3079 print_queue_struct *queue,
3080 NT_PRINTER_INFO_LEVEL *printer,
3081 TALLOC_CTX *mem_ctx)
3083 data->notify_data.value[0] = printer->info_2->starttime;
3084 data->notify_data.value[1] = 0;
3087 /*******************************************************************
3088 * fill a notify_info_data with the until time
3089 ********************************************************************/
3091 static void spoolss_notify_until_time(int snum,
3092 SPOOL_NOTIFY_INFO_DATA *data,
3093 print_queue_struct *queue,
3094 NT_PRINTER_INFO_LEVEL *printer,
3095 TALLOC_CTX *mem_ctx)
3097 data->notify_data.value[0] = printer->info_2->untiltime;
3098 data->notify_data.value[1] = 0;
3101 /*******************************************************************
3102 * fill a notify_info_data with the status
3103 ********************************************************************/
3105 static void spoolss_notify_status(int snum,
3106 SPOOL_NOTIFY_INFO_DATA *data,
3107 print_queue_struct *queue,
3108 NT_PRINTER_INFO_LEVEL *printer,
3109 TALLOC_CTX *mem_ctx)
3111 print_status_struct status;
3113 print_queue_length(snum, &status);
3114 data->notify_data.value[0]=(uint32) status.status;
3115 data->notify_data.value[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the number of jobs queued
3120 ********************************************************************/
3122 void spoolss_notify_cjobs(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] = print_queue_length(snum, NULL);
3129 data->notify_data.value[1] = 0;
3132 /*******************************************************************
3133 * fill a notify_info_data with the average ppm
3134 ********************************************************************/
3136 static void spoolss_notify_average_ppm(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 /* always respond 8 pages per minutes */
3143 /* a little hard ! */
3144 data->notify_data.value[0] = printer->info_2->averageppm;
3145 data->notify_data.value[1] = 0;
3148 /*******************************************************************
3149 * fill a notify_info_data with username
3150 ********************************************************************/
3152 static void spoolss_notify_username(int snum,
3153 SPOOL_NOTIFY_INFO_DATA *data,
3154 print_queue_struct *queue,
3155 NT_PRINTER_INFO_LEVEL *printer,
3156 TALLOC_CTX *mem_ctx)
3158 pstring temp;
3159 uint32 len;
3161 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3163 data->notify_data.data.length = len;
3164 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3166 if (!data->notify_data.data.string) {
3167 data->notify_data.data.length = 0;
3168 return;
3171 memcpy(data->notify_data.data.string, temp, len);
3174 /*******************************************************************
3175 * fill a notify_info_data with job status
3176 ********************************************************************/
3178 static void spoolss_notify_job_status(int snum,
3179 SPOOL_NOTIFY_INFO_DATA *data,
3180 print_queue_struct *queue,
3181 NT_PRINTER_INFO_LEVEL *printer,
3182 TALLOC_CTX *mem_ctx)
3184 data->notify_data.value[0]=nt_printj_status(queue->status);
3185 data->notify_data.value[1] = 0;
3188 /*******************************************************************
3189 * fill a notify_info_data with job name
3190 ********************************************************************/
3192 static void spoolss_notify_job_name(int snum,
3193 SPOOL_NOTIFY_INFO_DATA *data,
3194 print_queue_struct *queue,
3195 NT_PRINTER_INFO_LEVEL *printer,
3196 TALLOC_CTX *mem_ctx)
3198 pstring temp;
3199 uint32 len;
3201 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3203 data->notify_data.data.length = len;
3204 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3206 if (!data->notify_data.data.string) {
3207 data->notify_data.data.length = 0;
3208 return;
3211 memcpy(data->notify_data.data.string, temp, len);
3214 /*******************************************************************
3215 * fill a notify_info_data with job status
3216 ********************************************************************/
3218 static void spoolss_notify_job_status_string(int snum,
3219 SPOOL_NOTIFY_INFO_DATA *data,
3220 print_queue_struct *queue,
3221 NT_PRINTER_INFO_LEVEL *printer,
3222 TALLOC_CTX *mem_ctx)
3225 * Now we're returning job status codes we just return a "" here. JRA.
3228 const char *p = "";
3229 pstring temp;
3230 uint32 len;
3232 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3233 p = "unknown";
3235 switch (queue->status) {
3236 case LPQ_QUEUED:
3237 p = "Queued";
3238 break;
3239 case LPQ_PAUSED:
3240 p = ""; /* NT provides the paused string */
3241 break;
3242 case LPQ_SPOOLING:
3243 p = "Spooling";
3244 break;
3245 case LPQ_PRINTING:
3246 p = "Printing";
3247 break;
3249 #endif /* NO LONGER NEEDED. */
3251 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3253 data->notify_data.data.length = len;
3254 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3256 if (!data->notify_data.data.string) {
3257 data->notify_data.data.length = 0;
3258 return;
3261 memcpy(data->notify_data.data.string, temp, len);
3264 /*******************************************************************
3265 * fill a notify_info_data with job time
3266 ********************************************************************/
3268 static void spoolss_notify_job_time(int snum,
3269 SPOOL_NOTIFY_INFO_DATA *data,
3270 print_queue_struct *queue,
3271 NT_PRINTER_INFO_LEVEL *printer,
3272 TALLOC_CTX *mem_ctx)
3274 data->notify_data.value[0]=0x0;
3275 data->notify_data.value[1]=0;
3278 /*******************************************************************
3279 * fill a notify_info_data with job size
3280 ********************************************************************/
3282 static void spoolss_notify_job_size(int snum,
3283 SPOOL_NOTIFY_INFO_DATA *data,
3284 print_queue_struct *queue,
3285 NT_PRINTER_INFO_LEVEL *printer,
3286 TALLOC_CTX *mem_ctx)
3288 data->notify_data.value[0]=queue->size;
3289 data->notify_data.value[1]=0;
3292 /*******************************************************************
3293 * fill a notify_info_data with page info
3294 ********************************************************************/
3295 static void spoolss_notify_total_pages(int snum,
3296 SPOOL_NOTIFY_INFO_DATA *data,
3297 print_queue_struct *queue,
3298 NT_PRINTER_INFO_LEVEL *printer,
3299 TALLOC_CTX *mem_ctx)
3301 data->notify_data.value[0]=queue->page_count;
3302 data->notify_data.value[1]=0;
3305 /*******************************************************************
3306 * fill a notify_info_data with pages printed info.
3307 ********************************************************************/
3308 static void spoolss_notify_pages_printed(int snum,
3309 SPOOL_NOTIFY_INFO_DATA *data,
3310 print_queue_struct *queue,
3311 NT_PRINTER_INFO_LEVEL *printer,
3312 TALLOC_CTX *mem_ctx)
3314 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3315 data->notify_data.value[1]=0;
3318 /*******************************************************************
3319 Fill a notify_info_data with job position.
3320 ********************************************************************/
3322 static void spoolss_notify_job_position(int snum,
3323 SPOOL_NOTIFY_INFO_DATA *data,
3324 print_queue_struct *queue,
3325 NT_PRINTER_INFO_LEVEL *printer,
3326 TALLOC_CTX *mem_ctx)
3328 data->notify_data.value[0]=queue->job;
3329 data->notify_data.value[1]=0;
3332 /*******************************************************************
3333 Fill a notify_info_data with submitted time.
3334 ********************************************************************/
3336 static void spoolss_notify_submitted_time(int snum,
3337 SPOOL_NOTIFY_INFO_DATA *data,
3338 print_queue_struct *queue,
3339 NT_PRINTER_INFO_LEVEL *printer,
3340 TALLOC_CTX *mem_ctx)
3342 struct tm *t;
3343 uint32 len;
3344 SYSTEMTIME st;
3345 char *p;
3347 t=gmtime(&queue->time);
3349 len = sizeof(SYSTEMTIME);
3351 data->notify_data.data.length = len;
3352 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3354 if (!data->notify_data.data.string) {
3355 data->notify_data.data.length = 0;
3356 return;
3359 make_systemtime(&st, t);
3362 * Systemtime must be linearized as a set of UINT16's.
3363 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3366 p = (char *)data->notify_data.data.string;
3367 SSVAL(p, 0, st.year);
3368 SSVAL(p, 2, st.month);
3369 SSVAL(p, 4, st.dayofweek);
3370 SSVAL(p, 6, st.day);
3371 SSVAL(p, 8, st.hour);
3372 SSVAL(p, 10, st.minute);
3373 SSVAL(p, 12, st.second);
3374 SSVAL(p, 14, st.milliseconds);
3377 struct s_notify_info_data_table
3379 uint16 type;
3380 uint16 field;
3381 const char *name;
3382 uint32 size;
3383 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3384 print_queue_struct *queue,
3385 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3388 /* A table describing the various print notification constants and
3389 whether the notification data is a pointer to a variable sized
3390 buffer, a one value uint32 or a two value uint32. */
3392 static const struct s_notify_info_data_table notify_info_data_table[] =
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3443 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3446 /*******************************************************************
3447 Return the size of info_data structure.
3448 ********************************************************************/
3450 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3452 int i=0;
3454 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3455 if ( (notify_info_data_table[i].type == type)
3456 && (notify_info_data_table[i].field == field) ) {
3457 switch(notify_info_data_table[i].size) {
3458 case NOTIFY_ONE_VALUE:
3459 case NOTIFY_TWO_VALUE:
3460 return 1;
3461 case NOTIFY_STRING:
3462 return 2;
3464 /* The only pointer notify data I have seen on
3465 the wire is the submitted time and this has
3466 the notify size set to 4. -tpot */
3468 case NOTIFY_POINTER:
3469 return 4;
3471 case NOTIFY_SECDESC:
3472 return 5;
3477 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3479 return 0;
3482 /*******************************************************************
3483 Return the type of notify_info_data.
3484 ********************************************************************/
3486 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3488 uint32 i=0;
3490 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3491 if (notify_info_data_table[i].type == type &&
3492 notify_info_data_table[i].field == field)
3493 return notify_info_data_table[i].size;
3496 return 0;
3499 /****************************************************************************
3500 ****************************************************************************/
3502 static BOOL search_notify(uint16 type, uint16 field, int *value)
3504 int i;
3506 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3507 if (notify_info_data_table[i].type == type &&
3508 notify_info_data_table[i].field == field &&
3509 notify_info_data_table[i].fn != NULL) {
3510 *value = i;
3511 return True;
3515 return False;
3518 /****************************************************************************
3519 ****************************************************************************/
3521 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3523 info_data->type = type;
3524 info_data->field = field;
3525 info_data->reserved = 0;
3527 info_data->size = size_of_notify_info_data(type, field);
3528 info_data->enc_type = type_of_notify_info_data(type, field);
3530 info_data->id = id;
3533 /*******************************************************************
3535 * fill a notify_info struct with info asked
3537 ********************************************************************/
3539 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3540 snum, SPOOL_NOTIFY_OPTION_TYPE
3541 *option_type, uint32 id,
3542 TALLOC_CTX *mem_ctx)
3544 int field_num,j;
3545 uint16 type;
3546 uint16 field;
3548 SPOOL_NOTIFY_INFO_DATA *current_data;
3549 NT_PRINTER_INFO_LEVEL *printer = NULL;
3550 print_queue_struct *queue=NULL;
3552 type=option_type->type;
3554 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3555 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3556 option_type->count, lp_servicename(snum)));
3558 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3559 return False;
3561 for(field_num=0; field_num<option_type->count; field_num++) {
3562 field = option_type->fields[field_num];
3564 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3566 if (!search_notify(type, field, &j) )
3567 continue;
3569 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3570 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3571 free_a_printer(&printer, 2);
3572 return False;
3575 current_data = &info->data[info->count];
3577 construct_info_data(current_data, type, field, id);
3579 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3580 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3582 notify_info_data_table[j].fn(snum, current_data, queue,
3583 printer, mem_ctx);
3585 info->count++;
3588 free_a_printer(&printer, 2);
3589 return True;
3592 /*******************************************************************
3594 * fill a notify_info struct with info asked
3596 ********************************************************************/
3598 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3599 SPOOL_NOTIFY_INFO *info,
3600 NT_PRINTER_INFO_LEVEL *printer,
3601 int snum, SPOOL_NOTIFY_OPTION_TYPE
3602 *option_type, uint32 id,
3603 TALLOC_CTX *mem_ctx)
3605 int field_num,j;
3606 uint16 type;
3607 uint16 field;
3609 SPOOL_NOTIFY_INFO_DATA *current_data;
3611 DEBUG(4,("construct_notify_jobs_info\n"));
3613 type = option_type->type;
3615 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3616 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3617 option_type->count));
3619 for(field_num=0; field_num<option_type->count; field_num++) {
3620 field = option_type->fields[field_num];
3622 if (!search_notify(type, field, &j) )
3623 continue;
3625 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3626 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3627 return False;
3630 current_data=&(info->data[info->count]);
3632 construct_info_data(current_data, type, field, id);
3633 notify_info_data_table[j].fn(snum, current_data, queue,
3634 printer, mem_ctx);
3635 info->count++;
3638 return True;
3642 * JFM: The enumeration is not that simple, it's even non obvious.
3644 * let's take an example: I want to monitor the PRINTER SERVER for
3645 * the printer's name and the number of jobs currently queued.
3646 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3647 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3649 * I have 3 printers on the back of my server.
3651 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3652 * structures.
3653 * Number Data Id
3654 * 1 printer 1 name 1
3655 * 2 printer 1 cjob 1
3656 * 3 printer 2 name 2
3657 * 4 printer 2 cjob 2
3658 * 5 printer 3 name 3
3659 * 6 printer 3 name 3
3661 * that's the print server case, the printer case is even worse.
3664 /*******************************************************************
3666 * enumerate all printers on the printserver
3667 * fill a notify_info struct with info asked
3669 ********************************************************************/
3671 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3672 SPOOL_NOTIFY_INFO *info,
3673 TALLOC_CTX *mem_ctx)
3675 int snum;
3676 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3677 int n_services=lp_numservices();
3678 int i;
3679 SPOOL_NOTIFY_OPTION *option;
3680 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3682 DEBUG(4,("printserver_notify_info\n"));
3684 if (!Printer)
3685 return WERR_BADFID;
3687 option=Printer->notify.option;
3688 info->version=2;
3689 info->data=NULL;
3690 info->count=0;
3692 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3693 sending a ffpcn() request first */
3695 if ( !option )
3696 return WERR_BADFID;
3698 for (i=0; i<option->count; i++) {
3699 option_type=&(option->ctr.type[i]);
3701 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3702 continue;
3704 for (snum=0; snum<n_services; snum++)
3706 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3707 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3711 #if 0
3713 * Debugging information, don't delete.
3716 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3717 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3718 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3720 for (i=0; i<info->count; i++) {
3721 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3722 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3723 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3725 #endif
3727 return WERR_OK;
3730 /*******************************************************************
3732 * fill a notify_info struct with info asked
3734 ********************************************************************/
3736 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3737 TALLOC_CTX *mem_ctx)
3739 int snum;
3740 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3741 int i;
3742 uint32 id;
3743 SPOOL_NOTIFY_OPTION *option;
3744 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3745 int count,j;
3746 print_queue_struct *queue=NULL;
3747 print_status_struct status;
3749 DEBUG(4,("printer_notify_info\n"));
3751 if (!Printer)
3752 return WERR_BADFID;
3754 option=Printer->notify.option;
3755 id = 0x0;
3756 info->version=2;
3757 info->data=NULL;
3758 info->count=0;
3760 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3761 sending a ffpcn() request first */
3763 if ( !option )
3764 return WERR_BADFID;
3766 get_printer_snum(p, hnd, &snum);
3768 for (i=0; i<option->count; i++) {
3769 option_type=&option->ctr.type[i];
3771 switch ( option_type->type ) {
3772 case PRINTER_NOTIFY_TYPE:
3773 if(construct_notify_printer_info(Printer, info, snum,
3774 option_type, id,
3775 mem_ctx))
3776 id--;
3777 break;
3779 case JOB_NOTIFY_TYPE: {
3780 NT_PRINTER_INFO_LEVEL *printer = NULL;
3782 count = print_queue_status(snum, &queue, &status);
3784 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3785 goto done;
3787 for (j=0; j<count; j++) {
3788 construct_notify_jobs_info(&queue[j], info,
3789 printer, snum,
3790 option_type,
3791 queue[j].job,
3792 mem_ctx);
3795 free_a_printer(&printer, 2);
3797 done:
3798 SAFE_FREE(queue);
3799 break;
3805 * Debugging information, don't delete.
3808 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3809 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3810 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3812 for (i=0; i<info->count; i++) {
3813 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3814 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3815 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3818 return WERR_OK;
3821 /********************************************************************
3822 * spoolss_rfnpcnex
3823 ********************************************************************/
3825 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3827 POLICY_HND *handle = &q_u->handle;
3828 SPOOL_NOTIFY_INFO *info = &r_u->info;
3830 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3831 WERROR result = WERR_BADFID;
3833 /* we always have a NOTIFY_INFO struct */
3834 r_u->info_ptr=0x1;
3836 if (!Printer) {
3837 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3838 OUR_HANDLE(handle)));
3839 goto done;
3842 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3845 * We are now using the change value, and
3846 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3847 * I don't have a global notification system, I'm sending back all the
3848 * informations even when _NOTHING_ has changed.
3851 /* We need to keep track of the change value to send back in
3852 RRPCN replies otherwise our updates are ignored. */
3854 Printer->notify.fnpcn = True;
3856 if (Printer->notify.client_connected) {
3857 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3858 Printer->notify.change = q_u->change;
3861 /* just ignore the SPOOL_NOTIFY_OPTION */
3863 switch (Printer->printer_type) {
3864 case SPLHND_SERVER:
3865 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3866 break;
3868 case SPLHND_PRINTER:
3869 result = printer_notify_info(p, handle, info, p->mem_ctx);
3870 break;
3873 Printer->notify.fnpcn = False;
3875 done:
3876 return result;
3879 /********************************************************************
3880 * construct_printer_info_0
3881 * fill a printer_info_0 struct
3882 ********************************************************************/
3884 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3886 pstring chaine;
3887 int count;
3888 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3889 counter_printer_0 *session_counter;
3890 uint32 global_counter;
3891 struct tm *t;
3892 time_t setuptime;
3893 print_status_struct status;
3895 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3896 return False;
3898 count = print_queue_length(snum, &status);
3900 /* check if we already have a counter for this printer */
3901 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3902 if (session_counter->snum == snum)
3903 break;
3906 /* it's the first time, add it to the list */
3907 if (session_counter==NULL) {
3908 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3909 free_a_printer(&ntprinter, 2);
3910 return False;
3912 ZERO_STRUCTP(session_counter);
3913 session_counter->snum=snum;
3914 session_counter->counter=0;
3915 DLIST_ADD(counter_list, session_counter);
3918 /* increment it */
3919 session_counter->counter++;
3921 /* JFM:
3922 * the global_counter should be stored in a TDB as it's common to all the clients
3923 * and should be zeroed on samba startup
3925 global_counter=session_counter->counter;
3927 pstrcpy(chaine,ntprinter->info_2->printername);
3929 init_unistr(&printer->printername, chaine);
3931 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3932 init_unistr(&printer->servername, chaine);
3934 printer->cjobs = count;
3935 printer->total_jobs = 0;
3936 printer->total_bytes = 0;
3938 setuptime = (time_t)ntprinter->info_2->setuptime;
3939 t=gmtime(&setuptime);
3941 printer->year = t->tm_year+1900;
3942 printer->month = t->tm_mon+1;
3943 printer->dayofweek = t->tm_wday;
3944 printer->day = t->tm_mday;
3945 printer->hour = t->tm_hour;
3946 printer->minute = t->tm_min;
3947 printer->second = t->tm_sec;
3948 printer->milliseconds = 0;
3950 printer->global_counter = global_counter;
3951 printer->total_pages = 0;
3953 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3954 printer->major_version = 0x0005; /* NT 5 */
3955 printer->build_version = 0x0893; /* build 2195 */
3957 printer->unknown7 = 0x1;
3958 printer->unknown8 = 0x0;
3959 printer->unknown9 = 0x0;
3960 printer->session_counter = session_counter->counter;
3961 printer->unknown11 = 0x0;
3962 printer->printer_errors = 0x0; /* number of print failure */
3963 printer->unknown13 = 0x0;
3964 printer->unknown14 = 0x1;
3965 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3966 printer->unknown16 = 0x0;
3967 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3968 printer->unknown18 = 0x0;
3969 printer->status = nt_printq_status(status.status);
3970 printer->unknown20 = 0x0;
3971 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3972 printer->unknown22 = 0x0;
3973 printer->unknown23 = 0x6; /* 6 ???*/
3974 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3975 printer->unknown25 = 0;
3976 printer->unknown26 = 0;
3977 printer->unknown27 = 0;
3978 printer->unknown28 = 0;
3979 printer->unknown29 = 0;
3981 free_a_printer(&ntprinter,2);
3982 return (True);
3985 /********************************************************************
3986 * construct_printer_info_1
3987 * fill a printer_info_1 struct
3988 ********************************************************************/
3989 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3991 pstring chaine;
3992 pstring chaine2;
3993 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3995 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3996 return False;
3998 printer->flags=flags;
4000 if (*ntprinter->info_2->comment == '\0') {
4001 init_unistr(&printer->comment, lp_comment(snum));
4002 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4003 ntprinter->info_2->drivername, lp_comment(snum));
4005 else {
4006 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4007 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4008 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4011 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4013 init_unistr(&printer->description, chaine);
4014 init_unistr(&printer->name, chaine2);
4016 free_a_printer(&ntprinter,2);
4018 return True;
4021 /****************************************************************************
4022 Free a DEVMODE struct.
4023 ****************************************************************************/
4025 static void free_dev_mode(DEVICEMODE *dev)
4027 if (dev == NULL)
4028 return;
4030 SAFE_FREE(dev->dev_private);
4031 SAFE_FREE(dev);
4035 /****************************************************************************
4036 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4037 should be valid upon entry
4038 ****************************************************************************/
4040 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4042 if ( !devmode || !ntdevmode )
4043 return False;
4045 init_unistr(&devmode->devicename, ntdevmode->devicename);
4047 init_unistr(&devmode->formname, ntdevmode->formname);
4049 devmode->specversion = ntdevmode->specversion;
4050 devmode->driverversion = ntdevmode->driverversion;
4051 devmode->size = ntdevmode->size;
4052 devmode->driverextra = ntdevmode->driverextra;
4053 devmode->fields = ntdevmode->fields;
4055 devmode->orientation = ntdevmode->orientation;
4056 devmode->papersize = ntdevmode->papersize;
4057 devmode->paperlength = ntdevmode->paperlength;
4058 devmode->paperwidth = ntdevmode->paperwidth;
4059 devmode->scale = ntdevmode->scale;
4060 devmode->copies = ntdevmode->copies;
4061 devmode->defaultsource = ntdevmode->defaultsource;
4062 devmode->printquality = ntdevmode->printquality;
4063 devmode->color = ntdevmode->color;
4064 devmode->duplex = ntdevmode->duplex;
4065 devmode->yresolution = ntdevmode->yresolution;
4066 devmode->ttoption = ntdevmode->ttoption;
4067 devmode->collate = ntdevmode->collate;
4068 devmode->icmmethod = ntdevmode->icmmethod;
4069 devmode->icmintent = ntdevmode->icmintent;
4070 devmode->mediatype = ntdevmode->mediatype;
4071 devmode->dithertype = ntdevmode->dithertype;
4073 if (ntdevmode->nt_dev_private != NULL) {
4074 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4075 return False;
4078 return True;
4081 /****************************************************************************
4082 Create a DEVMODE struct. Returns malloced memory.
4083 ****************************************************************************/
4085 DEVICEMODE *construct_dev_mode(const char *servicename)
4087 NT_PRINTER_INFO_LEVEL *printer = NULL;
4088 DEVICEMODE *devmode = NULL;
4090 DEBUG(7,("construct_dev_mode\n"));
4092 DEBUGADD(8,("getting printer characteristics\n"));
4094 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4095 return NULL;
4097 if ( !printer->info_2->devmode ) {
4098 DEBUG(5, ("BONG! There was no device mode!\n"));
4099 goto done;
4102 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4103 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4104 goto done;
4107 ZERO_STRUCTP(devmode);
4109 DEBUGADD(8,("loading DEVICEMODE\n"));
4111 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4112 free_dev_mode( devmode );
4113 devmode = NULL;
4116 done:
4117 free_a_printer(&printer,2);
4119 return devmode;
4122 /********************************************************************
4123 * construct_printer_info_2
4124 * fill a printer_info_2 struct
4125 ********************************************************************/
4127 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4129 int count;
4130 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4132 print_status_struct status;
4134 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4135 return False;
4137 count = print_queue_length(snum, &status);
4139 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4140 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4141 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4142 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4143 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4145 if (*ntprinter->info_2->comment == '\0')
4146 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4147 else
4148 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4150 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4151 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4152 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4153 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4154 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4156 printer->attributes = ntprinter->info_2->attributes;
4158 printer->priority = ntprinter->info_2->priority; /* priority */
4159 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4160 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4161 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4162 printer->status = nt_printq_status(status.status); /* status */
4163 printer->cjobs = count; /* jobs */
4164 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4166 if ( !(printer->devmode = construct_dev_mode(
4167 lp_const_servicename(snum))) )
4168 DEBUG(8, ("Returning NULL Devicemode!\n"));
4170 printer->secdesc = NULL;
4172 if ( ntprinter->info_2->secdesc_buf
4173 && ntprinter->info_2->secdesc_buf->len != 0 )
4175 /* don't use talloc_steal() here unless you do a deep steal of all
4176 the SEC_DESC members */
4178 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4179 ntprinter->info_2->secdesc_buf->sec );
4182 free_a_printer(&ntprinter, 2);
4184 return True;
4187 /********************************************************************
4188 * construct_printer_info_3
4189 * fill a printer_info_3 struct
4190 ********************************************************************/
4192 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4194 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4195 PRINTER_INFO_3 *printer = NULL;
4197 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4198 return False;
4200 *pp_printer = NULL;
4201 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4202 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4203 free_a_printer(&ntprinter, 2);
4204 return False;
4207 ZERO_STRUCTP(printer);
4209 /* These are the components of the SD we are returning. */
4211 printer->flags = 0x4;
4213 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4214 /* don't use talloc_steal() here unless you do a deep steal of all
4215 the SEC_DESC members */
4217 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4218 ntprinter->info_2->secdesc_buf->sec );
4221 free_a_printer(&ntprinter, 2);
4223 *pp_printer = printer;
4224 return True;
4227 /********************************************************************
4228 * construct_printer_info_4
4229 * fill a printer_info_4 struct
4230 ********************************************************************/
4232 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4234 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4236 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4237 return False;
4239 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4240 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4241 printer->attributes = ntprinter->info_2->attributes;
4243 free_a_printer(&ntprinter, 2);
4244 return True;
4247 /********************************************************************
4248 * construct_printer_info_5
4249 * fill a printer_info_5 struct
4250 ********************************************************************/
4252 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4254 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4256 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4257 return False;
4259 init_unistr(&printer->printername, ntprinter->info_2->printername);
4260 init_unistr(&printer->portname, ntprinter->info_2->portname);
4261 printer->attributes = ntprinter->info_2->attributes;
4263 /* these two are not used by NT+ according to MSDN */
4265 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4266 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4268 free_a_printer(&ntprinter, 2);
4270 return True;
4273 /********************************************************************
4274 * construct_printer_info_7
4275 * fill a printer_info_7 struct
4276 ********************************************************************/
4278 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4280 char *guid_str = NULL;
4281 struct GUID guid;
4283 if (is_printer_published(print_hnd, snum, &guid)) {
4284 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4285 strupper_m(guid_str);
4286 init_unistr(&printer->guid, guid_str);
4287 printer->action = SPOOL_DS_PUBLISH;
4288 } else {
4289 init_unistr(&printer->guid, "");
4290 printer->action = SPOOL_DS_UNPUBLISH;
4293 return True;
4296 /********************************************************************
4297 Spoolss_enumprinters.
4298 ********************************************************************/
4300 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4302 int snum;
4303 int i;
4304 int n_services=lp_numservices();
4305 PRINTER_INFO_1 *printers=NULL;
4306 PRINTER_INFO_1 current_prt;
4307 WERROR result = WERR_OK;
4309 DEBUG(4,("enum_all_printers_info_1\n"));
4311 for (snum=0; snum<n_services; snum++) {
4312 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4313 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4315 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4316 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4317 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4318 *returned=0;
4319 return WERR_NOMEM;
4321 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4323 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4324 (*returned)++;
4329 /* check the required size. */
4330 for (i=0; i<*returned; i++)
4331 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4333 if (*needed > offered) {
4334 result = WERR_INSUFFICIENT_BUFFER;
4335 goto out;
4338 if (!rpcbuf_alloc_size(buffer, *needed)) {
4339 result = WERR_NOMEM;
4340 goto out;
4343 /* fill the buffer with the structures */
4344 for (i=0; i<*returned; i++)
4345 smb_io_printer_info_1("", buffer, &printers[i], 0);
4347 out:
4348 /* clear memory */
4350 SAFE_FREE(printers);
4352 if ( !W_ERROR_IS_OK(result) )
4353 *returned = 0;
4355 return result;
4358 /********************************************************************
4359 enum_all_printers_info_1_local.
4360 *********************************************************************/
4362 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4364 DEBUG(4,("enum_all_printers_info_1_local\n"));
4366 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4369 /********************************************************************
4370 enum_all_printers_info_1_name.
4371 *********************************************************************/
4373 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4375 char *s = name;
4377 DEBUG(4,("enum_all_printers_info_1_name\n"));
4379 if ((name[0] == '\\') && (name[1] == '\\'))
4380 s = name + 2;
4382 if (is_myname_or_ipaddr(s)) {
4383 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4385 else
4386 return WERR_INVALID_NAME;
4389 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4390 /********************************************************************
4391 enum_all_printers_info_1_remote.
4392 *********************************************************************/
4394 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4396 PRINTER_INFO_1 *printer;
4397 fstring printername;
4398 fstring desc;
4399 fstring comment;
4400 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4401 WERROR result = WERR_OK;
4403 /* JFM: currently it's more a place holder than anything else.
4404 * In the spooler world there is a notion of server registration.
4405 * the print servers are registered on the PDC (in the same domain)
4407 * We should have a TDB here. The registration is done thru an
4408 * undocumented RPC call.
4411 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4412 return WERR_NOMEM;
4414 *returned=1;
4416 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4417 slprintf(desc, sizeof(desc)-1,"%s", name);
4418 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4420 init_unistr(&printer->description, desc);
4421 init_unistr(&printer->name, printername);
4422 init_unistr(&printer->comment, comment);
4423 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4425 /* check the required size. */
4426 *needed += spoolss_size_printer_info_1(printer);
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 smb_io_printer_info_1("", buffer, printer, 0);
4441 out:
4442 /* clear memory */
4443 SAFE_FREE(printer);
4445 if ( !W_ERROR_IS_OK(result) )
4446 *returned = 0;
4448 return result;
4451 #endif
4453 /********************************************************************
4454 enum_all_printers_info_1_network.
4455 *********************************************************************/
4457 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4459 char *s = name;
4461 DEBUG(4,("enum_all_printers_info_1_network\n"));
4463 /* If we respond to a enum_printers level 1 on our name with flags
4464 set to PRINTER_ENUM_REMOTE with a list of printers then these
4465 printers incorrectly appear in the APW browse list.
4466 Specifically the printers for the server appear at the workgroup
4467 level where all the other servers in the domain are
4468 listed. Windows responds to this call with a
4469 WERR_CAN_NOT_COMPLETE so we should do the same. */
4471 if (name[0] == '\\' && name[1] == '\\')
4472 s = name + 2;
4474 if (is_myname_or_ipaddr(s))
4475 return WERR_CAN_NOT_COMPLETE;
4477 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4480 /********************************************************************
4481 * api_spoolss_enumprinters
4483 * called from api_spoolss_enumprinters (see this to understand)
4484 ********************************************************************/
4486 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4488 int snum;
4489 int i;
4490 int n_services=lp_numservices();
4491 PRINTER_INFO_2 *printers=NULL;
4492 PRINTER_INFO_2 current_prt;
4493 WERROR result = WERR_OK;
4495 *returned = 0;
4497 for (snum=0; snum<n_services; snum++) {
4498 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4499 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4501 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4502 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4503 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4504 *returned = 0;
4505 return WERR_NOMEM;
4508 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4510 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4512 (*returned)++;
4517 /* check the required size. */
4518 for (i=0; i<*returned; i++)
4519 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4521 if (*needed > offered) {
4522 result = WERR_INSUFFICIENT_BUFFER;
4523 goto out;
4526 if (!rpcbuf_alloc_size(buffer, *needed)) {
4527 result = WERR_NOMEM;
4528 goto out;
4531 /* fill the buffer with the structures */
4532 for (i=0; i<*returned; i++)
4533 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4535 out:
4536 /* clear memory */
4538 for (i=0; i<*returned; i++)
4539 free_devmode(printers[i].devmode);
4541 SAFE_FREE(printers);
4543 if ( !W_ERROR_IS_OK(result) )
4544 *returned = 0;
4546 return result;
4549 /********************************************************************
4550 * handle enumeration of printers at level 1
4551 ********************************************************************/
4553 static WERROR enumprinters_level1( uint32 flags, fstring name,
4554 RPC_BUFFER *buffer, uint32 offered,
4555 uint32 *needed, uint32 *returned)
4557 /* Not all the flags are equals */
4559 if (flags & PRINTER_ENUM_LOCAL)
4560 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4562 if (flags & PRINTER_ENUM_NAME)
4563 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4565 #if 0 /* JERRY - disabled for now */
4566 if (flags & PRINTER_ENUM_REMOTE)
4567 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4568 #endif
4570 if (flags & PRINTER_ENUM_NETWORK)
4571 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4573 return WERR_OK; /* NT4sp5 does that */
4576 /********************************************************************
4577 * handle enumeration of printers at level 2
4578 ********************************************************************/
4580 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4581 RPC_BUFFER *buffer, uint32 offered,
4582 uint32 *needed, uint32 *returned)
4584 char *s = servername;
4586 if (flags & PRINTER_ENUM_LOCAL) {
4587 return enum_all_printers_info_2(buffer, offered, needed, returned);
4590 if (flags & PRINTER_ENUM_NAME) {
4591 if ((servername[0] == '\\') && (servername[1] == '\\'))
4592 s = servername + 2;
4593 if (is_myname_or_ipaddr(s))
4594 return enum_all_printers_info_2(buffer, offered, needed, returned);
4595 else
4596 return WERR_INVALID_NAME;
4599 if (flags & PRINTER_ENUM_REMOTE)
4600 return WERR_UNKNOWN_LEVEL;
4602 return WERR_OK;
4605 /********************************************************************
4606 * handle enumeration of printers at level 5
4607 ********************************************************************/
4609 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4610 RPC_BUFFER *buffer, uint32 offered,
4611 uint32 *needed, uint32 *returned)
4613 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4614 return WERR_OK;
4617 /********************************************************************
4618 * api_spoolss_enumprinters
4620 * called from api_spoolss_enumprinters (see this to understand)
4621 ********************************************************************/
4623 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4625 uint32 flags = q_u->flags;
4626 UNISTR2 *servername = &q_u->servername;
4627 uint32 level = q_u->level;
4628 RPC_BUFFER *buffer = NULL;
4629 uint32 offered = q_u->offered;
4630 uint32 *needed = &r_u->needed;
4631 uint32 *returned = &r_u->returned;
4633 fstring name;
4635 /* that's an [in out] buffer */
4637 if (!q_u->buffer && (offered!=0)) {
4638 return WERR_INVALID_PARAM;
4641 rpcbuf_move(q_u->buffer, &r_u->buffer);
4642 buffer = r_u->buffer;
4644 DEBUG(4,("_spoolss_enumprinters\n"));
4646 *needed=0;
4647 *returned=0;
4650 * Level 1:
4651 * flags==PRINTER_ENUM_NAME
4652 * if name=="" then enumerates all printers
4653 * if name!="" then enumerate the printer
4654 * flags==PRINTER_ENUM_REMOTE
4655 * name is NULL, enumerate printers
4656 * Level 2: name!="" enumerates printers, name can't be NULL
4657 * Level 3: doesn't exist
4658 * Level 4: does a local registry lookup
4659 * Level 5: same as Level 2
4662 unistr2_to_ascii(name, servername, sizeof(name)-1);
4663 strupper_m(name);
4665 switch (level) {
4666 case 1:
4667 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4668 case 2:
4669 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4670 case 5:
4671 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4672 case 3:
4673 case 4:
4674 break;
4676 return WERR_UNKNOWN_LEVEL;
4679 /****************************************************************************
4680 ****************************************************************************/
4682 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4684 PRINTER_INFO_0 *printer=NULL;
4685 WERROR result = WERR_OK;
4687 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4688 return WERR_NOMEM;
4690 construct_printer_info_0(print_hnd, printer, snum);
4692 /* check the required size. */
4693 *needed += spoolss_size_printer_info_0(printer);
4695 if (*needed > offered) {
4696 result = WERR_INSUFFICIENT_BUFFER;
4697 goto out;
4700 if (!rpcbuf_alloc_size(buffer, *needed)) {
4701 result = WERR_NOMEM;
4702 goto out;
4705 /* fill the buffer with the structures */
4706 smb_io_printer_info_0("", buffer, printer, 0);
4708 out:
4709 /* clear memory */
4711 SAFE_FREE(printer);
4713 return result;
4716 /****************************************************************************
4717 ****************************************************************************/
4719 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4721 PRINTER_INFO_1 *printer=NULL;
4722 WERROR result = WERR_OK;
4724 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4725 return WERR_NOMEM;
4727 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4729 /* check the required size. */
4730 *needed += spoolss_size_printer_info_1(printer);
4732 if (*needed > offered) {
4733 result = WERR_INSUFFICIENT_BUFFER;
4734 goto out;
4737 if (!rpcbuf_alloc_size(buffer, *needed)) {
4738 result = WERR_NOMEM;
4739 goto out;
4742 /* fill the buffer with the structures */
4743 smb_io_printer_info_1("", buffer, printer, 0);
4745 out:
4746 /* clear memory */
4747 SAFE_FREE(printer);
4749 return result;
4752 /****************************************************************************
4753 ****************************************************************************/
4755 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4757 PRINTER_INFO_2 *printer=NULL;
4758 WERROR result = WERR_OK;
4760 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4761 return WERR_NOMEM;
4763 construct_printer_info_2(print_hnd, printer, snum);
4765 /* check the required size. */
4766 *needed += spoolss_size_printer_info_2(printer);
4768 if (*needed > offered) {
4769 result = WERR_INSUFFICIENT_BUFFER;
4770 goto out;
4773 if (!rpcbuf_alloc_size(buffer, *needed)) {
4774 result = WERR_NOMEM;
4775 goto out;
4778 /* fill the buffer with the structures */
4779 if (!smb_io_printer_info_2("", buffer, printer, 0))
4780 result = WERR_NOMEM;
4782 out:
4783 /* clear memory */
4784 free_printer_info_2(printer);
4786 return result;
4789 /****************************************************************************
4790 ****************************************************************************/
4792 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4794 PRINTER_INFO_3 *printer=NULL;
4795 WERROR result = WERR_OK;
4797 if (!construct_printer_info_3(print_hnd, &printer, snum))
4798 return WERR_NOMEM;
4800 /* check the required size. */
4801 *needed += spoolss_size_printer_info_3(printer);
4803 if (*needed > offered) {
4804 result = WERR_INSUFFICIENT_BUFFER;
4805 goto out;
4808 if (!rpcbuf_alloc_size(buffer, *needed)) {
4809 result = WERR_NOMEM;
4810 goto out;
4813 /* fill the buffer with the structures */
4814 smb_io_printer_info_3("", buffer, printer, 0);
4816 out:
4817 /* clear memory */
4818 free_printer_info_3(printer);
4820 return result;
4823 /****************************************************************************
4824 ****************************************************************************/
4826 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4828 PRINTER_INFO_4 *printer=NULL;
4829 WERROR result = WERR_OK;
4831 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4832 return WERR_NOMEM;
4834 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4835 SAFE_FREE(printer);
4836 return WERR_NOMEM;
4839 /* check the required size. */
4840 *needed += spoolss_size_printer_info_4(printer);
4842 if (*needed > offered) {
4843 result = WERR_INSUFFICIENT_BUFFER;
4844 goto out;
4847 if (!rpcbuf_alloc_size(buffer, *needed)) {
4848 result = WERR_NOMEM;
4849 goto out;
4852 /* fill the buffer with the structures */
4853 smb_io_printer_info_4("", buffer, printer, 0);
4855 out:
4856 /* clear memory */
4857 free_printer_info_4(printer);
4859 return result;
4862 /****************************************************************************
4863 ****************************************************************************/
4865 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4867 PRINTER_INFO_5 *printer=NULL;
4868 WERROR result = WERR_OK;
4870 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4871 return WERR_NOMEM;
4873 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4874 free_printer_info_5(printer);
4875 return WERR_NOMEM;
4878 /* check the required size. */
4879 *needed += spoolss_size_printer_info_5(printer);
4881 if (*needed > offered) {
4882 result = WERR_INSUFFICIENT_BUFFER;
4883 goto out;
4886 if (!rpcbuf_alloc_size(buffer, *needed)) {
4887 result = WERR_NOMEM;
4888 goto out;
4891 /* fill the buffer with the structures */
4892 smb_io_printer_info_5("", buffer, printer, 0);
4894 out:
4895 /* clear memory */
4896 free_printer_info_5(printer);
4898 return result;
4901 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4903 PRINTER_INFO_7 *printer=NULL;
4904 WERROR result = WERR_OK;
4906 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4907 return WERR_NOMEM;
4909 if (!construct_printer_info_7(print_hnd, printer, snum))
4910 return WERR_NOMEM;
4912 /* check the required size. */
4913 *needed += spoolss_size_printer_info_7(printer);
4915 if (*needed > offered) {
4916 result = WERR_INSUFFICIENT_BUFFER;
4917 goto out;
4920 if (!rpcbuf_alloc_size(buffer, *needed)) {
4921 result = WERR_NOMEM;
4922 goto out;
4926 /* fill the buffer with the structures */
4927 smb_io_printer_info_7("", buffer, printer, 0);
4929 out:
4930 /* clear memory */
4931 free_printer_info_7(printer);
4933 return result;
4936 /****************************************************************************
4937 ****************************************************************************/
4939 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4941 POLICY_HND *handle = &q_u->handle;
4942 uint32 level = q_u->level;
4943 RPC_BUFFER *buffer = NULL;
4944 uint32 offered = q_u->offered;
4945 uint32 *needed = &r_u->needed;
4946 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4948 int snum;
4950 /* that's an [in out] buffer */
4952 if (!q_u->buffer && (offered!=0)) {
4953 return WERR_INVALID_PARAM;
4956 rpcbuf_move(q_u->buffer, &r_u->buffer);
4957 buffer = r_u->buffer;
4959 *needed=0;
4961 if (!get_printer_snum(p, handle, &snum))
4962 return WERR_BADFID;
4964 switch (level) {
4965 case 0:
4966 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4967 case 1:
4968 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4969 case 2:
4970 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4971 case 3:
4972 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4973 case 4:
4974 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4975 case 5:
4976 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4977 case 7:
4978 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4980 return WERR_UNKNOWN_LEVEL;
4983 /********************************************************************
4984 * fill a DRIVER_INFO_1 struct
4985 ********************************************************************/
4987 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4989 init_unistr( &info->name, driver.info_3->name);
4992 /********************************************************************
4993 * construct_printer_driver_info_1
4994 ********************************************************************/
4996 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4998 NT_PRINTER_INFO_LEVEL *printer = NULL;
4999 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5001 ZERO_STRUCT(driver);
5003 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5004 return WERR_INVALID_PRINTER_NAME;
5006 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5007 free_a_printer(&printer, 2);
5008 return WERR_UNKNOWN_PRINTER_DRIVER;
5011 fill_printer_driver_info_1(info, driver, servername, architecture);
5013 free_a_printer(&printer,2);
5015 return WERR_OK;
5018 /********************************************************************
5019 * construct_printer_driver_info_2
5020 * fill a printer_info_2 struct
5021 ********************************************************************/
5023 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5025 pstring temp;
5027 info->version=driver.info_3->cversion;
5029 init_unistr( &info->name, driver.info_3->name );
5030 init_unistr( &info->architecture, driver.info_3->environment );
5033 if (strlen(driver.info_3->driverpath)) {
5034 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5035 init_unistr( &info->driverpath, temp );
5036 } else
5037 init_unistr( &info->driverpath, "" );
5039 if (strlen(driver.info_3->datafile)) {
5040 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5041 init_unistr( &info->datafile, temp );
5042 } else
5043 init_unistr( &info->datafile, "" );
5045 if (strlen(driver.info_3->configfile)) {
5046 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5047 init_unistr( &info->configfile, temp );
5048 } else
5049 init_unistr( &info->configfile, "" );
5052 /********************************************************************
5053 * construct_printer_driver_info_2
5054 * fill a printer_info_2 struct
5055 ********************************************************************/
5057 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5059 NT_PRINTER_INFO_LEVEL *printer = NULL;
5060 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5062 ZERO_STRUCT(printer);
5063 ZERO_STRUCT(driver);
5065 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5066 return WERR_INVALID_PRINTER_NAME;
5068 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5069 free_a_printer(&printer, 2);
5070 return WERR_UNKNOWN_PRINTER_DRIVER;
5073 fill_printer_driver_info_2(info, driver, servername);
5075 free_a_printer(&printer,2);
5077 return WERR_OK;
5080 /********************************************************************
5081 * copy a strings array and convert to UNICODE
5083 * convert an array of ascii string to a UNICODE string
5084 ********************************************************************/
5086 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5088 int i=0;
5089 int j=0;
5090 const char *v;
5091 pstring line;
5093 DEBUG(6,("init_unistr_array\n"));
5094 *uni_array=NULL;
5096 while (True)
5098 if ( !char_array )
5099 v = "";
5100 else
5102 v = char_array[i];
5103 if (!v)
5104 v = ""; /* hack to handle null lists */
5107 /* hack to allow this to be used in places other than when generating
5108 the list of dependent files */
5110 if ( servername )
5111 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5112 else
5113 pstrcpy( line, v );
5115 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5117 /* add one extra unit16 for the second terminating NULL */
5119 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5120 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5121 return 0;
5124 if ( !strlen(v) )
5125 break;
5127 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5128 i++;
5131 if (*uni_array) {
5132 /* special case for ""; we need to add both NULL's here */
5133 if (!j)
5134 (*uni_array)[j++]=0x0000;
5135 (*uni_array)[j]=0x0000;
5138 DEBUGADD(6,("last one:done\n"));
5140 /* return size of array in uint16's */
5142 return j+1;
5145 /********************************************************************
5146 * construct_printer_info_3
5147 * fill a printer_info_3 struct
5148 ********************************************************************/
5150 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5152 pstring temp;
5154 ZERO_STRUCTP(info);
5156 info->version=driver.info_3->cversion;
5158 init_unistr( &info->name, driver.info_3->name );
5159 init_unistr( &info->architecture, driver.info_3->environment );
5161 if (strlen(driver.info_3->driverpath)) {
5162 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5163 init_unistr( &info->driverpath, temp );
5164 } else
5165 init_unistr( &info->driverpath, "" );
5167 if (strlen(driver.info_3->datafile)) {
5168 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5169 init_unistr( &info->datafile, temp );
5170 } else
5171 init_unistr( &info->datafile, "" );
5173 if (strlen(driver.info_3->configfile)) {
5174 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5175 init_unistr( &info->configfile, temp );
5176 } else
5177 init_unistr( &info->configfile, "" );
5179 if (strlen(driver.info_3->helpfile)) {
5180 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5181 init_unistr( &info->helpfile, temp );
5182 } else
5183 init_unistr( &info->helpfile, "" );
5185 init_unistr( &info->monitorname, driver.info_3->monitorname );
5186 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5188 info->dependentfiles=NULL;
5189 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5192 /********************************************************************
5193 * construct_printer_info_3
5194 * fill a printer_info_3 struct
5195 ********************************************************************/
5197 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5199 NT_PRINTER_INFO_LEVEL *printer = NULL;
5200 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5201 WERROR status;
5202 ZERO_STRUCT(driver);
5204 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5205 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5206 if (!W_ERROR_IS_OK(status))
5207 return WERR_INVALID_PRINTER_NAME;
5209 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5210 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5212 #if 0 /* JERRY */
5215 * I put this code in during testing. Helpful when commenting out the
5216 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5217 * as win2k always queries the driver using an infor level of 6.
5218 * I've left it in (but ifdef'd out) because I'll probably
5219 * use it in experimentation again in the future. --jerry 22/01/2002
5222 if (!W_ERROR_IS_OK(status)) {
5224 * Is this a W2k client ?
5226 if (version == 3) {
5227 /* Yes - try again with a WinNT driver. */
5228 version = 2;
5229 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5230 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5232 #endif
5234 if (!W_ERROR_IS_OK(status)) {
5235 free_a_printer(&printer,2);
5236 return WERR_UNKNOWN_PRINTER_DRIVER;
5239 #if 0 /* JERRY */
5241 #endif
5244 fill_printer_driver_info_3(info, driver, servername);
5246 free_a_printer(&printer,2);
5248 return WERR_OK;
5251 /********************************************************************
5252 * construct_printer_info_6
5253 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5254 ********************************************************************/
5256 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5258 pstring temp;
5259 fstring nullstr;
5261 ZERO_STRUCTP(info);
5262 memset(&nullstr, '\0', sizeof(fstring));
5264 info->version=driver.info_3->cversion;
5266 init_unistr( &info->name, driver.info_3->name );
5267 init_unistr( &info->architecture, driver.info_3->environment );
5269 if (strlen(driver.info_3->driverpath)) {
5270 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5271 init_unistr( &info->driverpath, temp );
5272 } else
5273 init_unistr( &info->driverpath, "" );
5275 if (strlen(driver.info_3->datafile)) {
5276 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5277 init_unistr( &info->datafile, temp );
5278 } else
5279 init_unistr( &info->datafile, "" );
5281 if (strlen(driver.info_3->configfile)) {
5282 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5283 init_unistr( &info->configfile, temp );
5284 } else
5285 init_unistr( &info->configfile, "" );
5287 if (strlen(driver.info_3->helpfile)) {
5288 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5289 init_unistr( &info->helpfile, temp );
5290 } else
5291 init_unistr( &info->helpfile, "" );
5293 init_unistr( &info->monitorname, driver.info_3->monitorname );
5294 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5296 info->dependentfiles = NULL;
5297 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5299 info->previousdrivernames=NULL;
5300 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5302 info->driver_date=0;
5304 info->padding=0;
5305 info->driver_version_low=0;
5306 info->driver_version_high=0;
5308 init_unistr( &info->mfgname, "");
5309 init_unistr( &info->oem_url, "");
5310 init_unistr( &info->hardware_id, "");
5311 init_unistr( &info->provider, "");
5314 /********************************************************************
5315 * construct_printer_info_6
5316 * fill a printer_info_6 struct
5317 ********************************************************************/
5319 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5320 fstring servername, fstring architecture, uint32 version)
5322 NT_PRINTER_INFO_LEVEL *printer = NULL;
5323 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5324 WERROR status;
5326 ZERO_STRUCT(driver);
5328 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5330 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5332 if (!W_ERROR_IS_OK(status))
5333 return WERR_INVALID_PRINTER_NAME;
5335 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5337 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5339 if (!W_ERROR_IS_OK(status))
5342 * Is this a W2k client ?
5345 if (version < 3) {
5346 free_a_printer(&printer,2);
5347 return WERR_UNKNOWN_PRINTER_DRIVER;
5350 /* Yes - try again with a WinNT driver. */
5351 version = 2;
5352 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5353 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5354 if (!W_ERROR_IS_OK(status)) {
5355 free_a_printer(&printer,2);
5356 return WERR_UNKNOWN_PRINTER_DRIVER;
5360 fill_printer_driver_info_6(info, driver, servername);
5362 free_a_printer(&printer,2);
5363 free_a_printer_driver(driver, 3);
5365 return WERR_OK;
5368 /****************************************************************************
5369 ****************************************************************************/
5371 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5373 SAFE_FREE(info->dependentfiles);
5376 /****************************************************************************
5377 ****************************************************************************/
5379 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5381 SAFE_FREE(info->dependentfiles);
5384 /****************************************************************************
5385 ****************************************************************************/
5387 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5389 DRIVER_INFO_1 *info=NULL;
5390 WERROR result;
5392 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5393 return WERR_NOMEM;
5395 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5396 if (!W_ERROR_IS_OK(result))
5397 goto out;
5399 /* check the required size. */
5400 *needed += spoolss_size_printer_driver_info_1(info);
5402 if (*needed > offered) {
5403 result = WERR_INSUFFICIENT_BUFFER;
5404 goto out;
5407 if (!rpcbuf_alloc_size(buffer, *needed)) {
5408 result = WERR_NOMEM;
5409 goto out;
5412 /* fill the buffer with the structures */
5413 smb_io_printer_driver_info_1("", buffer, info, 0);
5415 out:
5416 /* clear memory */
5417 SAFE_FREE(info);
5419 return result;
5422 /****************************************************************************
5423 ****************************************************************************/
5425 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5427 DRIVER_INFO_2 *info=NULL;
5428 WERROR result;
5430 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5431 return WERR_NOMEM;
5433 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5434 if (!W_ERROR_IS_OK(result))
5435 goto out;
5437 /* check the required size. */
5438 *needed += spoolss_size_printer_driver_info_2(info);
5440 if (*needed > offered) {
5441 result = WERR_INSUFFICIENT_BUFFER;
5442 goto out;
5445 if (!rpcbuf_alloc_size(buffer, *needed)) {
5446 result = WERR_NOMEM;
5447 goto out;
5450 /* fill the buffer with the structures */
5451 smb_io_printer_driver_info_2("", buffer, info, 0);
5453 out:
5454 /* clear memory */
5455 SAFE_FREE(info);
5457 return result;
5460 /****************************************************************************
5461 ****************************************************************************/
5463 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5465 DRIVER_INFO_3 info;
5466 WERROR result;
5468 ZERO_STRUCT(info);
5470 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5471 if (!W_ERROR_IS_OK(result))
5472 goto out;
5474 /* check the required size. */
5475 *needed += spoolss_size_printer_driver_info_3(&info);
5477 if (*needed > offered) {
5478 result = WERR_INSUFFICIENT_BUFFER;
5479 goto out;
5482 if (!rpcbuf_alloc_size(buffer, *needed)) {
5483 result = WERR_NOMEM;
5484 goto out;
5487 /* fill the buffer with the structures */
5488 smb_io_printer_driver_info_3("", buffer, &info, 0);
5490 out:
5491 free_printer_driver_info_3(&info);
5493 return result;
5496 /****************************************************************************
5497 ****************************************************************************/
5499 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5501 DRIVER_INFO_6 info;
5502 WERROR result;
5504 ZERO_STRUCT(info);
5506 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5507 if (!W_ERROR_IS_OK(result))
5508 goto out;
5510 /* check the required size. */
5511 *needed += spoolss_size_printer_driver_info_6(&info);
5513 if (*needed > offered) {
5514 result = WERR_INSUFFICIENT_BUFFER;
5515 goto out;
5518 if (!rpcbuf_alloc_size(buffer, *needed)) {
5519 result = WERR_NOMEM;
5520 goto out;
5523 /* fill the buffer with the structures */
5524 smb_io_printer_driver_info_6("", buffer, &info, 0);
5526 out:
5527 free_printer_driver_info_6(&info);
5529 return result;
5532 /****************************************************************************
5533 ****************************************************************************/
5535 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5537 POLICY_HND *handle = &q_u->handle;
5538 UNISTR2 *uni_arch = &q_u->architecture;
5539 uint32 level = q_u->level;
5540 uint32 clientmajorversion = q_u->clientmajorversion;
5541 RPC_BUFFER *buffer = NULL;
5542 uint32 offered = q_u->offered;
5543 uint32 *needed = &r_u->needed;
5544 uint32 *servermajorversion = &r_u->servermajorversion;
5545 uint32 *serverminorversion = &r_u->serverminorversion;
5546 Printer_entry *printer;
5548 fstring servername;
5549 fstring architecture;
5550 int snum;
5552 /* that's an [in out] buffer */
5554 if (!q_u->buffer && (offered!=0)) {
5555 return WERR_INVALID_PARAM;
5558 rpcbuf_move(q_u->buffer, &r_u->buffer);
5559 buffer = r_u->buffer;
5561 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5563 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5564 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5565 return WERR_INVALID_PRINTER_NAME;
5568 *needed = 0;
5569 *servermajorversion = 0;
5570 *serverminorversion = 0;
5572 fstrcpy(servername, get_server_name( printer ));
5573 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5575 if (!get_printer_snum(p, handle, &snum))
5576 return WERR_BADFID;
5578 switch (level) {
5579 case 1:
5580 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5581 case 2:
5582 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5583 case 3:
5584 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5585 case 6:
5586 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5587 #if 0 /* JERRY */
5588 case 101:
5589 /* apparently this call is the equivalent of
5590 EnumPrinterDataEx() for the DsDriver key */
5591 break;
5592 #endif
5595 return WERR_UNKNOWN_LEVEL;
5598 /****************************************************************************
5599 ****************************************************************************/
5601 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5603 POLICY_HND *handle = &q_u->handle;
5605 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5607 if (!Printer) {
5608 DEBUG(3,("Error in startpageprinter printer handle\n"));
5609 return WERR_BADFID;
5612 Printer->page_started=True;
5613 return WERR_OK;
5616 /****************************************************************************
5617 ****************************************************************************/
5619 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5621 POLICY_HND *handle = &q_u->handle;
5622 int snum;
5624 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5626 if (!Printer) {
5627 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5628 return WERR_BADFID;
5631 if (!get_printer_snum(p, handle, &snum))
5632 return WERR_BADFID;
5634 Printer->page_started=False;
5635 print_job_endpage(snum, Printer->jobid);
5637 return WERR_OK;
5640 /********************************************************************
5641 * api_spoolss_getprinter
5642 * called from the spoolss dispatcher
5644 ********************************************************************/
5646 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5648 POLICY_HND *handle = &q_u->handle;
5649 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5650 uint32 *jobid = &r_u->jobid;
5652 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5653 int snum;
5654 pstring jobname;
5655 fstring datatype;
5656 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5657 struct current_user user;
5659 if (!Printer) {
5660 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5661 return WERR_BADFID;
5664 get_current_user(&user, p);
5667 * a nice thing with NT is it doesn't listen to what you tell it.
5668 * when asked to send _only_ RAW datas, it tries to send datas
5669 * in EMF format.
5671 * So I add checks like in NT Server ...
5674 if (info_1->p_datatype != 0) {
5675 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5676 if (strcmp(datatype, "RAW") != 0) {
5677 (*jobid)=0;
5678 return WERR_INVALID_DATATYPE;
5682 /* get the share number of the printer */
5683 if (!get_printer_snum(p, handle, &snum)) {
5684 return WERR_BADFID;
5687 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5689 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5691 /* An error occured in print_job_start() so return an appropriate
5692 NT error code. */
5694 if (Printer->jobid == -1) {
5695 return map_werror_from_unix(errno);
5698 Printer->document_started=True;
5699 (*jobid) = Printer->jobid;
5701 return WERR_OK;
5704 /********************************************************************
5705 * api_spoolss_getprinter
5706 * called from the spoolss dispatcher
5708 ********************************************************************/
5710 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5712 POLICY_HND *handle = &q_u->handle;
5714 return _spoolss_enddocprinter_internal(p, handle);
5717 /****************************************************************************
5718 ****************************************************************************/
5720 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5722 POLICY_HND *handle = &q_u->handle;
5723 uint32 buffer_size = q_u->buffer_size;
5724 uint8 *buffer = q_u->buffer;
5725 uint32 *buffer_written = &q_u->buffer_size2;
5726 int snum;
5727 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5729 if (!Printer) {
5730 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5731 r_u->buffer_written = q_u->buffer_size2;
5732 return WERR_BADFID;
5735 if (!get_printer_snum(p, handle, &snum))
5736 return WERR_BADFID;
5738 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5739 (SMB_OFF_T)-1, (size_t)buffer_size);
5740 if (*buffer_written == (uint32)-1) {
5741 r_u->buffer_written = 0;
5742 if (errno == ENOSPC)
5743 return WERR_NO_SPOOL_SPACE;
5744 else
5745 return WERR_ACCESS_DENIED;
5748 r_u->buffer_written = q_u->buffer_size2;
5750 return WERR_OK;
5753 /********************************************************************
5754 * api_spoolss_getprinter
5755 * called from the spoolss dispatcher
5757 ********************************************************************/
5759 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5760 pipes_struct *p)
5762 struct current_user user;
5763 int snum;
5764 WERROR errcode = WERR_BADFUNC;
5765 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5767 get_current_user(&user, p);
5769 if (!Printer) {
5770 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5771 return WERR_BADFID;
5774 if (!get_printer_snum(p, handle, &snum))
5775 return WERR_BADFID;
5777 switch (command) {
5778 case PRINTER_CONTROL_PAUSE:
5779 if (print_queue_pause(&user, snum, &errcode)) {
5780 errcode = WERR_OK;
5782 break;
5783 case PRINTER_CONTROL_RESUME:
5784 case PRINTER_CONTROL_UNPAUSE:
5785 if (print_queue_resume(&user, snum, &errcode)) {
5786 errcode = WERR_OK;
5788 break;
5789 case PRINTER_CONTROL_PURGE:
5790 if (print_queue_purge(&user, snum, &errcode)) {
5791 errcode = WERR_OK;
5793 break;
5794 default:
5795 return WERR_UNKNOWN_LEVEL;
5798 return errcode;
5801 /********************************************************************
5802 * api_spoolss_abortprinter
5803 * From MSDN: "Deletes printer's spool file if printer is configured
5804 * for spooling"
5805 ********************************************************************/
5807 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5809 POLICY_HND *handle = &q_u->handle;
5810 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5811 int snum;
5812 struct current_user user;
5813 WERROR errcode = WERR_OK;
5815 if (!Printer) {
5816 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5817 return WERR_BADFID;
5820 if (!get_printer_snum(p, handle, &snum))
5821 return WERR_BADFID;
5823 get_current_user( &user, p );
5825 print_job_delete( &user, snum, Printer->jobid, &errcode );
5827 return errcode;
5830 /********************************************************************
5831 * called by spoolss_api_setprinter
5832 * when updating a printer description
5833 ********************************************************************/
5835 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5836 const SPOOL_PRINTER_INFO_LEVEL *info,
5837 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5839 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5840 WERROR result;
5841 int snum;
5843 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5845 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5846 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5847 OUR_HANDLE(handle)));
5849 result = WERR_BADFID;
5850 goto done;
5853 if (!secdesc_ctr) {
5854 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5855 result = WERR_INVALID_PARAM;
5856 goto done;
5859 /* Check the user has permissions to change the security
5860 descriptor. By experimentation with two NT machines, the user
5861 requires Full Access to the printer to change security
5862 information. */
5864 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5865 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5866 result = WERR_ACCESS_DENIED;
5867 goto done;
5870 /* NT seems to like setting the security descriptor even though
5871 nothing may have actually changed. */
5873 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5875 if (DEBUGLEVEL >= 10) {
5876 SEC_ACL *the_acl;
5877 int i;
5879 the_acl = old_secdesc_ctr->sec->dacl;
5880 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5881 PRINTERNAME(snum), the_acl->num_aces));
5883 for (i = 0; i < the_acl->num_aces; i++) {
5884 fstring sid_str;
5886 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5888 DEBUG(10, ("%s 0x%08x\n", sid_str,
5889 the_acl->aces[i].access_mask));
5892 the_acl = secdesc_ctr->sec->dacl;
5894 if (the_acl) {
5895 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5896 PRINTERNAME(snum), the_acl->num_aces));
5898 for (i = 0; i < the_acl->num_aces; i++) {
5899 fstring sid_str;
5901 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5903 DEBUG(10, ("%s 0x%08x\n", sid_str,
5904 the_acl->aces[i].access_mask));
5906 } else {
5907 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5911 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5912 if (!new_secdesc_ctr) {
5913 result = WERR_NOMEM;
5914 goto done;
5917 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5918 result = WERR_OK;
5919 goto done;
5922 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5924 done:
5926 return result;
5929 /********************************************************************
5930 Canonicalize printer info from a client
5932 ATTN: It does not matter what we set the servername to hear
5933 since we do the necessary work in get_a_printer() to set it to
5934 the correct value based on what the client sent in the
5935 _spoolss_open_printer_ex().
5936 ********************************************************************/
5938 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5940 fstring printername;
5941 const char *p;
5943 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5944 "portname=%s drivername=%s comment=%s location=%s\n",
5945 info->servername, info->printername, info->sharename,
5946 info->portname, info->drivername, info->comment, info->location));
5948 /* we force some elements to "correct" values */
5949 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5950 fstrcpy(info->sharename, lp_servicename(snum));
5952 /* check to see if we allow printername != sharename */
5954 if ( lp_force_printername(snum) ) {
5955 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5956 global_myname(), info->sharename );
5957 } else {
5959 /* make sure printername is in \\server\printername format */
5961 fstrcpy( printername, info->printername );
5962 p = printername;
5963 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5964 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5965 p++;
5968 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5969 global_myname(), p );
5972 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5973 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5977 return True;
5980 /****************************************************************************
5981 ****************************************************************************/
5983 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5985 char *cmd = lp_addport_cmd();
5986 pstring command;
5987 int ret;
5988 int fd;
5989 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5990 BOOL is_print_op = False;
5992 if ( !*cmd ) {
5993 return WERR_ACCESS_DENIED;
5996 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5998 if ( token )
5999 is_print_op = user_has_privileges( token, &se_printop );
6001 DEBUG(10,("Running [%s]\n", command));
6003 /********* BEGIN SePrintOperatorPrivilege **********/
6005 if ( is_print_op )
6006 become_root();
6008 ret = smbrun(command, &fd);
6010 if ( is_print_op )
6011 unbecome_root();
6013 /********* END SePrintOperatorPrivilege **********/
6015 DEBUGADD(10,("returned [%d]\n", ret));
6017 if ( ret != 0 ) {
6018 if (fd != -1)
6019 close(fd);
6020 return WERR_ACCESS_DENIED;
6023 return WERR_OK;
6026 /****************************************************************************
6027 ****************************************************************************/
6029 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6031 char *cmd = lp_addprinter_cmd();
6032 char **qlines;
6033 pstring command;
6034 int numlines;
6035 int ret;
6036 int fd;
6037 fstring remote_machine = "%m";
6038 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6039 BOOL is_print_op = False;
6041 standard_sub_basic(current_user_info.smb_name,
6042 current_user_info.domain,
6043 remote_machine,sizeof(remote_machine));
6045 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6046 cmd, printer->info_2->printername, printer->info_2->sharename,
6047 printer->info_2->portname, printer->info_2->drivername,
6048 printer->info_2->location, printer->info_2->comment, remote_machine);
6050 if ( token )
6051 is_print_op = user_has_privileges( token, &se_printop );
6053 DEBUG(10,("Running [%s]\n", command));
6055 /********* BEGIN SePrintOperatorPrivilege **********/
6057 if ( is_print_op )
6058 become_root();
6060 if ( (ret = smbrun(command, &fd)) == 0 ) {
6061 /* Tell everyone we updated smb.conf. */
6062 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6065 if ( is_print_op )
6066 unbecome_root();
6068 /********* END SePrintOperatorPrivilege **********/
6070 DEBUGADD(10,("returned [%d]\n", ret));
6072 if ( ret != 0 ) {
6073 if (fd != -1)
6074 close(fd);
6075 return False;
6078 /* reload our services immediately */
6079 reload_services( False );
6081 numlines = 0;
6082 /* Get lines and convert them back to dos-codepage */
6083 qlines = fd_lines_load(fd, &numlines, 0);
6084 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6085 close(fd);
6087 /* Set the portname to what the script says the portname should be. */
6088 /* but don't require anything to be return from the script exit a good error code */
6090 if (numlines) {
6091 /* Set the portname to what the script says the portname should be. */
6092 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6093 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6096 file_lines_free(qlines);
6097 return True;
6101 /********************************************************************
6102 * Called by spoolss_api_setprinter
6103 * when updating a printer description.
6104 ********************************************************************/
6106 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6107 const SPOOL_PRINTER_INFO_LEVEL *info,
6108 DEVICEMODE *devmode)
6110 int snum;
6111 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6112 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6113 WERROR result;
6114 UNISTR2 buffer;
6115 fstring asc_buffer;
6117 DEBUG(8,("update_printer\n"));
6119 result = WERR_OK;
6121 if (!Printer) {
6122 result = WERR_BADFID;
6123 goto done;
6126 if (!get_printer_snum(p, handle, &snum)) {
6127 result = WERR_BADFID;
6128 goto done;
6131 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6132 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6133 result = WERR_BADFID;
6134 goto done;
6137 DEBUGADD(8,("Converting info_2 struct\n"));
6140 * convert_printer_info converts the incoming
6141 * info from the client and overwrites the info
6142 * just read from the tdb in the pointer 'printer'.
6145 if (!convert_printer_info(info, printer, level)) {
6146 result = WERR_NOMEM;
6147 goto done;
6150 if (devmode) {
6151 /* we have a valid devmode
6152 convert it and link it*/
6154 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6155 if (!convert_devicemode(printer->info_2->printername, devmode,
6156 &printer->info_2->devmode)) {
6157 result = WERR_NOMEM;
6158 goto done;
6162 /* Do sanity check on the requested changes for Samba */
6164 if (!check_printer_ok(printer->info_2, snum)) {
6165 result = WERR_INVALID_PARAM;
6166 goto done;
6169 /* FIXME!!! If the driver has changed we really should verify that
6170 it is installed before doing much else --jerry */
6172 /* Check calling user has permission to update printer description */
6174 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6175 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6176 result = WERR_ACCESS_DENIED;
6177 goto done;
6180 /* Call addprinter hook */
6181 /* Check changes to see if this is really needed */
6183 if ( *lp_addprinter_cmd()
6184 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6185 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6186 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6187 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6189 /* add_printer_hook() will call reload_services() */
6191 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6192 result = WERR_ACCESS_DENIED;
6193 goto done;
6198 * When a *new* driver is bound to a printer, the drivername is used to
6199 * lookup previously saved driver initialization info, which is then
6200 * bound to the printer, simulating what happens in the Windows arch.
6202 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6204 if (!set_driver_init(printer, 2))
6206 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6207 printer->info_2->drivername));
6210 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6211 printer->info_2->drivername));
6213 notify_printer_driver(snum, printer->info_2->drivername);
6217 * flag which changes actually occured. This is a small subset of
6218 * all the possible changes. We also have to update things in the
6219 * DsSpooler key.
6222 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6223 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6224 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6225 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6227 notify_printer_comment(snum, printer->info_2->comment);
6230 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6231 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6232 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6233 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6235 notify_printer_sharename(snum, printer->info_2->sharename);
6238 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6239 char *pname;
6241 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6242 pname++;
6243 else
6244 pname = printer->info_2->printername;
6247 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6248 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6249 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6251 notify_printer_printername( snum, pname );
6254 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6255 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6256 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6257 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6259 notify_printer_port(snum, printer->info_2->portname);
6262 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6263 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6264 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6265 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6267 notify_printer_location(snum, printer->info_2->location);
6270 /* here we need to update some more DsSpooler keys */
6271 /* uNCName, serverName, shortServerName */
6273 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6274 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6275 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6276 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6277 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6279 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6280 global_myname(), printer->info_2->sharename );
6281 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6282 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6283 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6285 /* Update printer info */
6286 result = mod_a_printer(printer, 2);
6288 done:
6289 free_a_printer(&printer, 2);
6290 free_a_printer(&old_printer, 2);
6293 return result;
6296 /****************************************************************************
6297 ****************************************************************************/
6298 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6299 const SPOOL_PRINTER_INFO_LEVEL *info)
6301 #ifdef HAVE_ADS
6302 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6303 int snum;
6304 Printer_entry *Printer;
6306 if ( lp_security() != SEC_ADS ) {
6307 return WERR_UNKNOWN_LEVEL;
6310 Printer = find_printer_index_by_hnd(p, handle);
6312 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6314 if (!Printer)
6315 return WERR_BADFID;
6317 if (!get_printer_snum(p, handle, &snum))
6318 return WERR_BADFID;
6320 nt_printer_publish(Printer, snum, info7->action);
6322 return WERR_OK;
6323 #else
6324 return WERR_UNKNOWN_LEVEL;
6325 #endif
6327 /****************************************************************************
6328 ****************************************************************************/
6330 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6332 POLICY_HND *handle = &q_u->handle;
6333 uint32 level = q_u->level;
6334 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6335 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6336 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6337 uint32 command = q_u->command;
6338 WERROR result;
6340 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6342 if (!Printer) {
6343 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6344 return WERR_BADFID;
6347 /* check the level */
6348 switch (level) {
6349 case 0:
6350 return control_printer(handle, command, p);
6351 case 2:
6352 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6353 if (!W_ERROR_IS_OK(result))
6354 return result;
6355 if (secdesc_ctr)
6356 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6357 return result;
6358 case 3:
6359 return update_printer_sec(handle, level, info, p,
6360 secdesc_ctr);
6361 case 7:
6362 return publish_or_unpublish_printer(p, handle, info);
6363 default:
6364 return WERR_UNKNOWN_LEVEL;
6368 /****************************************************************************
6369 ****************************************************************************/
6371 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6373 POLICY_HND *handle = &q_u->handle;
6374 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6376 if (!Printer) {
6377 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6378 return WERR_BADFID;
6381 if (Printer->notify.client_connected==True) {
6382 int snum = -1;
6384 if ( Printer->printer_type == SPLHND_SERVER)
6385 snum = -1;
6386 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6387 !get_printer_snum(p, handle, &snum) )
6388 return WERR_BADFID;
6390 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6393 Printer->notify.flags=0;
6394 Printer->notify.options=0;
6395 Printer->notify.localmachine[0]='\0';
6396 Printer->notify.printerlocal=0;
6397 if (Printer->notify.option)
6398 free_spool_notify_option(&Printer->notify.option);
6399 Printer->notify.client_connected=False;
6401 return WERR_OK;
6404 /****************************************************************************
6405 ****************************************************************************/
6407 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6409 /* that's an [in out] buffer */
6411 if (!q_u->buffer && (q_u->offered!=0)) {
6412 return WERR_INVALID_PARAM;
6415 rpcbuf_move(q_u->buffer, &r_u->buffer);
6417 r_u->needed = 0;
6418 return WERR_INVALID_PARAM; /* this is what a NT server
6419 returns for AddJob. AddJob
6420 must fail on non-local
6421 printers */
6424 /****************************************************************************
6425 ****************************************************************************/
6427 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6428 int position, int snum,
6429 const NT_PRINTER_INFO_LEVEL *ntprinter)
6431 struct tm *t;
6433 t=gmtime(&queue->time);
6435 job_info->jobid=queue->job;
6436 init_unistr(&job_info->printername, lp_servicename(snum));
6437 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6438 init_unistr(&job_info->username, queue->fs_user);
6439 init_unistr(&job_info->document, queue->fs_file);
6440 init_unistr(&job_info->datatype, "RAW");
6441 init_unistr(&job_info->text_status, "");
6442 job_info->status=nt_printj_status(queue->status);
6443 job_info->priority=queue->priority;
6444 job_info->position=position;
6445 job_info->totalpages=queue->page_count;
6446 job_info->pagesprinted=0;
6448 make_systemtime(&job_info->submitted, t);
6451 /****************************************************************************
6452 ****************************************************************************/
6454 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6455 int position, int snum,
6456 const NT_PRINTER_INFO_LEVEL *ntprinter,
6457 DEVICEMODE *devmode)
6459 struct tm *t;
6461 t=gmtime(&queue->time);
6463 job_info->jobid=queue->job;
6465 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6467 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6468 init_unistr(&job_info->username, queue->fs_user);
6469 init_unistr(&job_info->document, queue->fs_file);
6470 init_unistr(&job_info->notifyname, queue->fs_user);
6471 init_unistr(&job_info->datatype, "RAW");
6472 init_unistr(&job_info->printprocessor, "winprint");
6473 init_unistr(&job_info->parameters, "");
6474 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6475 init_unistr(&job_info->text_status, "");
6477 /* and here the security descriptor */
6479 job_info->status=nt_printj_status(queue->status);
6480 job_info->priority=queue->priority;
6481 job_info->position=position;
6482 job_info->starttime=0;
6483 job_info->untiltime=0;
6484 job_info->totalpages=queue->page_count;
6485 job_info->size=queue->size;
6486 make_systemtime(&(job_info->submitted), t);
6487 job_info->timeelapsed=0;
6488 job_info->pagesprinted=0;
6490 job_info->devmode = devmode;
6492 return (True);
6495 /****************************************************************************
6496 Enumjobs at level 1.
6497 ****************************************************************************/
6499 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6500 const NT_PRINTER_INFO_LEVEL *ntprinter,
6501 RPC_BUFFER *buffer, uint32 offered,
6502 uint32 *needed, uint32 *returned)
6504 JOB_INFO_1 *info;
6505 int i;
6506 WERROR result = WERR_OK;
6508 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6509 if (info==NULL) {
6510 *returned=0;
6511 return WERR_NOMEM;
6514 for (i=0; i<*returned; i++)
6515 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6517 /* check the required size. */
6518 for (i=0; i<*returned; i++)
6519 (*needed) += spoolss_size_job_info_1(&info[i]);
6521 if (*needed > offered) {
6522 result = WERR_INSUFFICIENT_BUFFER;
6523 goto out;
6526 if (!rpcbuf_alloc_size(buffer, *needed)) {
6527 result = WERR_NOMEM;
6528 goto out;
6531 /* fill the buffer with the structures */
6532 for (i=0; i<*returned; i++)
6533 smb_io_job_info_1("", buffer, &info[i], 0);
6535 out:
6536 /* clear memory */
6537 SAFE_FREE(info);
6539 if ( !W_ERROR_IS_OK(result) )
6540 *returned = 0;
6542 return result;
6545 /****************************************************************************
6546 Enumjobs at level 2.
6547 ****************************************************************************/
6549 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6550 const NT_PRINTER_INFO_LEVEL *ntprinter,
6551 RPC_BUFFER *buffer, uint32 offered,
6552 uint32 *needed, uint32 *returned)
6554 JOB_INFO_2 *info = NULL;
6555 int i;
6556 WERROR result = WERR_OK;
6557 DEVICEMODE *devmode = NULL;
6559 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6560 *returned=0;
6561 return WERR_NOMEM;
6564 /* this should not be a failure condition if the devmode is NULL */
6566 devmode = construct_dev_mode(lp_const_servicename(snum));
6568 for (i=0; i<*returned; i++)
6569 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6571 /* check the required size. */
6572 for (i=0; i<*returned; i++)
6573 (*needed) += spoolss_size_job_info_2(&info[i]);
6575 if (*needed > offered) {
6576 result = WERR_INSUFFICIENT_BUFFER;
6577 goto out;
6580 if (!rpcbuf_alloc_size(buffer, *needed)) {
6581 result = WERR_NOMEM;
6582 goto out;
6585 /* fill the buffer with the structures */
6586 for (i=0; i<*returned; i++)
6587 smb_io_job_info_2("", buffer, &info[i], 0);
6589 out:
6590 free_devmode(devmode);
6591 SAFE_FREE(info);
6593 if ( !W_ERROR_IS_OK(result) )
6594 *returned = 0;
6596 return result;
6600 /****************************************************************************
6601 Enumjobs.
6602 ****************************************************************************/
6604 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6606 POLICY_HND *handle = &q_u->handle;
6607 uint32 level = q_u->level;
6608 RPC_BUFFER *buffer = NULL;
6609 uint32 offered = q_u->offered;
6610 uint32 *needed = &r_u->needed;
6611 uint32 *returned = &r_u->returned;
6612 WERROR wret;
6613 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6614 int snum;
6615 print_status_struct prt_status;
6616 print_queue_struct *queue=NULL;
6618 /* that's an [in out] buffer */
6620 if (!q_u->buffer && (offered!=0)) {
6621 return WERR_INVALID_PARAM;
6624 rpcbuf_move(q_u->buffer, &r_u->buffer);
6625 buffer = r_u->buffer;
6627 DEBUG(4,("_spoolss_enumjobs\n"));
6629 *needed=0;
6630 *returned=0;
6632 /* lookup the printer snum and tdb entry */
6634 if (!get_printer_snum(p, handle, &snum))
6635 return WERR_BADFID;
6637 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6638 if ( !W_ERROR_IS_OK(wret) )
6639 return wret;
6641 *returned = print_queue_status(snum, &queue, &prt_status);
6642 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6644 if (*returned == 0) {
6645 SAFE_FREE(queue);
6646 free_a_printer(&ntprinter, 2);
6647 return WERR_OK;
6650 switch (level) {
6651 case 1:
6652 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6653 break;
6654 case 2:
6655 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6656 break;
6657 default:
6658 *returned=0;
6659 wret = WERR_UNKNOWN_LEVEL;
6660 break;
6663 SAFE_FREE(queue);
6664 free_a_printer( &ntprinter, 2 );
6665 return wret;
6668 /****************************************************************************
6669 ****************************************************************************/
6671 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6673 return WERR_OK;
6676 /****************************************************************************
6677 ****************************************************************************/
6679 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6681 POLICY_HND *handle = &q_u->handle;
6682 uint32 jobid = q_u->jobid;
6683 uint32 command = q_u->command;
6685 struct current_user user;
6686 int snum;
6687 WERROR errcode = WERR_BADFUNC;
6689 if (!get_printer_snum(p, handle, &snum)) {
6690 return WERR_BADFID;
6693 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6694 return WERR_INVALID_PRINTER_NAME;
6697 get_current_user(&user, p);
6699 switch (command) {
6700 case JOB_CONTROL_CANCEL:
6701 case JOB_CONTROL_DELETE:
6702 if (print_job_delete(&user, snum, jobid, &errcode)) {
6703 errcode = WERR_OK;
6705 break;
6706 case JOB_CONTROL_PAUSE:
6707 if (print_job_pause(&user, snum, jobid, &errcode)) {
6708 errcode = WERR_OK;
6710 break;
6711 case JOB_CONTROL_RESTART:
6712 case JOB_CONTROL_RESUME:
6713 if (print_job_resume(&user, snum, jobid, &errcode)) {
6714 errcode = WERR_OK;
6716 break;
6717 default:
6718 return WERR_UNKNOWN_LEVEL;
6721 return errcode;
6724 /****************************************************************************
6725 Enumerates all printer drivers at level 1.
6726 ****************************************************************************/
6728 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6730 int i;
6731 int ndrivers;
6732 uint32 version;
6733 fstring *list = NULL;
6734 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6735 DRIVER_INFO_1 *driver_info_1=NULL;
6736 WERROR result = WERR_OK;
6738 *returned=0;
6740 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6741 list=NULL;
6742 ndrivers=get_ntdrivers(&list, architecture, version);
6743 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6745 if(ndrivers == -1) {
6746 SAFE_FREE(driver_info_1);
6747 return WERR_NOMEM;
6750 if(ndrivers != 0) {
6751 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6752 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6753 SAFE_FREE(list);
6754 return WERR_NOMEM;
6758 for (i=0; i<ndrivers; i++) {
6759 WERROR status;
6760 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6761 ZERO_STRUCT(driver);
6762 status = get_a_printer_driver(&driver, 3, list[i],
6763 architecture, version);
6764 if (!W_ERROR_IS_OK(status)) {
6765 SAFE_FREE(list);
6766 SAFE_FREE(driver_info_1);
6767 return status;
6769 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6770 free_a_printer_driver(driver, 3);
6773 *returned+=ndrivers;
6774 SAFE_FREE(list);
6777 /* check the required size. */
6778 for (i=0; i<*returned; i++) {
6779 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6780 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6783 if (*needed > offered) {
6784 result = WERR_INSUFFICIENT_BUFFER;
6785 goto out;
6788 if (!rpcbuf_alloc_size(buffer, *needed)) {
6789 result = WERR_NOMEM;
6790 goto out;
6793 /* fill the buffer with the driver structures */
6794 for (i=0; i<*returned; i++) {
6795 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6796 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6799 out:
6800 SAFE_FREE(driver_info_1);
6802 if ( !W_ERROR_IS_OK(result) )
6803 *returned = 0;
6805 return result;
6808 /****************************************************************************
6809 Enumerates all printer drivers at level 2.
6810 ****************************************************************************/
6812 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6814 int i;
6815 int ndrivers;
6816 uint32 version;
6817 fstring *list = NULL;
6818 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6819 DRIVER_INFO_2 *driver_info_2=NULL;
6820 WERROR result = WERR_OK;
6822 *returned=0;
6824 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6825 list=NULL;
6826 ndrivers=get_ntdrivers(&list, architecture, version);
6827 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6829 if(ndrivers == -1) {
6830 SAFE_FREE(driver_info_2);
6831 return WERR_NOMEM;
6834 if(ndrivers != 0) {
6835 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6836 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6837 SAFE_FREE(list);
6838 return WERR_NOMEM;
6842 for (i=0; i<ndrivers; i++) {
6843 WERROR status;
6845 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6846 ZERO_STRUCT(driver);
6847 status = get_a_printer_driver(&driver, 3, list[i],
6848 architecture, version);
6849 if (!W_ERROR_IS_OK(status)) {
6850 SAFE_FREE(list);
6851 SAFE_FREE(driver_info_2);
6852 return status;
6854 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6855 free_a_printer_driver(driver, 3);
6858 *returned+=ndrivers;
6859 SAFE_FREE(list);
6862 /* check the required size. */
6863 for (i=0; i<*returned; i++) {
6864 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6865 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6868 if (*needed > offered) {
6869 result = WERR_INSUFFICIENT_BUFFER;
6870 goto out;
6873 if (!rpcbuf_alloc_size(buffer, *needed)) {
6874 result = WERR_NOMEM;
6875 goto out;
6878 /* fill the buffer with the form structures */
6879 for (i=0; i<*returned; i++) {
6880 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6881 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6884 out:
6885 SAFE_FREE(driver_info_2);
6887 if ( !W_ERROR_IS_OK(result) )
6888 *returned = 0;
6890 return result;
6893 /****************************************************************************
6894 Enumerates all printer drivers at level 3.
6895 ****************************************************************************/
6897 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6899 int i;
6900 int ndrivers;
6901 uint32 version;
6902 fstring *list = NULL;
6903 DRIVER_INFO_3 *driver_info_3=NULL;
6904 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6905 WERROR result = WERR_OK;
6907 *returned=0;
6909 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6910 list=NULL;
6911 ndrivers=get_ntdrivers(&list, architecture, version);
6912 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6914 if(ndrivers == -1) {
6915 SAFE_FREE(driver_info_3);
6916 return WERR_NOMEM;
6919 if(ndrivers != 0) {
6920 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6921 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6922 SAFE_FREE(list);
6923 return WERR_NOMEM;
6927 for (i=0; i<ndrivers; i++) {
6928 WERROR status;
6930 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6931 ZERO_STRUCT(driver);
6932 status = get_a_printer_driver(&driver, 3, list[i],
6933 architecture, version);
6934 if (!W_ERROR_IS_OK(status)) {
6935 SAFE_FREE(list);
6936 SAFE_FREE(driver_info_3);
6937 return status;
6939 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6940 free_a_printer_driver(driver, 3);
6943 *returned+=ndrivers;
6944 SAFE_FREE(list);
6947 /* check the required size. */
6948 for (i=0; i<*returned; i++) {
6949 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6950 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6953 if (*needed > offered) {
6954 result = WERR_INSUFFICIENT_BUFFER;
6955 goto out;
6958 if (!rpcbuf_alloc_size(buffer, *needed)) {
6959 result = WERR_NOMEM;
6960 goto out;
6963 /* fill the buffer with the driver structures */
6964 for (i=0; i<*returned; i++) {
6965 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6966 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6969 out:
6970 for (i=0; i<*returned; i++) {
6971 SAFE_FREE(driver_info_3[i].dependentfiles);
6974 SAFE_FREE(driver_info_3);
6976 if ( !W_ERROR_IS_OK(result) )
6977 *returned = 0;
6979 return result;
6982 /****************************************************************************
6983 Enumerates all printer drivers.
6984 ****************************************************************************/
6986 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6988 uint32 level = q_u->level;
6989 RPC_BUFFER *buffer = NULL;
6990 uint32 offered = q_u->offered;
6991 uint32 *needed = &r_u->needed;
6992 uint32 *returned = &r_u->returned;
6994 fstring servername;
6995 fstring architecture;
6997 /* that's an [in out] buffer */
6999 if (!q_u->buffer && (offered!=0)) {
7000 return WERR_INVALID_PARAM;
7003 rpcbuf_move(q_u->buffer, &r_u->buffer);
7004 buffer = r_u->buffer;
7006 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7008 *needed = 0;
7009 *returned = 0;
7011 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7012 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7014 if ( !is_myname_or_ipaddr( servername ) )
7015 return WERR_UNKNOWN_PRINTER_DRIVER;
7017 switch (level) {
7018 case 1:
7019 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7020 case 2:
7021 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7022 case 3:
7023 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7024 default:
7025 return WERR_UNKNOWN_LEVEL;
7029 /****************************************************************************
7030 ****************************************************************************/
7032 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7034 form->flag=list->flag;
7035 init_unistr(&form->name, list->name);
7036 form->width=list->width;
7037 form->length=list->length;
7038 form->left=list->left;
7039 form->top=list->top;
7040 form->right=list->right;
7041 form->bottom=list->bottom;
7044 /****************************************************************************
7045 ****************************************************************************/
7047 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7049 uint32 level = q_u->level;
7050 RPC_BUFFER *buffer = NULL;
7051 uint32 offered = q_u->offered;
7052 uint32 *needed = &r_u->needed;
7053 uint32 *numofforms = &r_u->numofforms;
7054 uint32 numbuiltinforms;
7056 nt_forms_struct *list=NULL;
7057 nt_forms_struct *builtinlist=NULL;
7058 FORM_1 *forms_1;
7059 int buffer_size=0;
7060 int i;
7062 /* that's an [in out] buffer */
7064 if (!q_u->buffer && (offered!=0) ) {
7065 return WERR_INVALID_PARAM;
7068 rpcbuf_move(q_u->buffer, &r_u->buffer);
7069 buffer = r_u->buffer;
7071 DEBUG(4,("_spoolss_enumforms\n"));
7072 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7073 DEBUGADD(5,("Info level [%d]\n", level));
7075 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7076 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7077 *numofforms = get_ntforms(&list);
7078 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7079 *numofforms += numbuiltinforms;
7081 if (*numofforms == 0) {
7082 SAFE_FREE(builtinlist);
7083 SAFE_FREE(list);
7084 return WERR_NO_MORE_ITEMS;
7087 switch (level) {
7088 case 1:
7089 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7090 SAFE_FREE(builtinlist);
7091 SAFE_FREE(list);
7092 *numofforms=0;
7093 return WERR_NOMEM;
7096 /* construct the list of form structures */
7097 for (i=0; i<numbuiltinforms; i++) {
7098 DEBUGADD(6,("Filling form number [%d]\n",i));
7099 fill_form_1(&forms_1[i], &builtinlist[i]);
7102 SAFE_FREE(builtinlist);
7104 for (; i<*numofforms; i++) {
7105 DEBUGADD(6,("Filling form number [%d]\n",i));
7106 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7109 SAFE_FREE(list);
7111 /* check the required size. */
7112 for (i=0; i<numbuiltinforms; i++) {
7113 DEBUGADD(6,("adding form [%d]'s size\n",i));
7114 buffer_size += spoolss_size_form_1(&forms_1[i]);
7116 for (; i<*numofforms; i++) {
7117 DEBUGADD(6,("adding form [%d]'s size\n",i));
7118 buffer_size += spoolss_size_form_1(&forms_1[i]);
7121 *needed=buffer_size;
7123 if (*needed > offered) {
7124 SAFE_FREE(forms_1);
7125 *numofforms=0;
7126 return WERR_INSUFFICIENT_BUFFER;
7129 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7130 SAFE_FREE(forms_1);
7131 *numofforms=0;
7132 return WERR_NOMEM;
7135 /* fill the buffer with the form structures */
7136 for (i=0; i<numbuiltinforms; i++) {
7137 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7138 smb_io_form_1("", buffer, &forms_1[i], 0);
7140 for (; i<*numofforms; i++) {
7141 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7142 smb_io_form_1("", buffer, &forms_1[i], 0);
7145 SAFE_FREE(forms_1);
7147 return WERR_OK;
7149 default:
7150 SAFE_FREE(list);
7151 SAFE_FREE(builtinlist);
7152 return WERR_UNKNOWN_LEVEL;
7156 /****************************************************************************
7157 ****************************************************************************/
7159 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7161 uint32 level = q_u->level;
7162 UNISTR2 *uni_formname = &q_u->formname;
7163 RPC_BUFFER *buffer = NULL;
7164 uint32 offered = q_u->offered;
7165 uint32 *needed = &r_u->needed;
7167 nt_forms_struct *list=NULL;
7168 nt_forms_struct builtin_form;
7169 BOOL foundBuiltin;
7170 FORM_1 form_1;
7171 fstring form_name;
7172 int buffer_size=0;
7173 int numofforms=0, i=0;
7175 /* that's an [in out] buffer */
7177 if (!q_u->buffer && (offered!=0)) {
7178 return WERR_INVALID_PARAM;
7181 rpcbuf_move(q_u->buffer, &r_u->buffer);
7182 buffer = r_u->buffer;
7184 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7186 DEBUG(4,("_spoolss_getform\n"));
7187 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7188 DEBUGADD(5,("Info level [%d]\n", level));
7190 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7191 if (!foundBuiltin) {
7192 numofforms = get_ntforms(&list);
7193 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7195 if (numofforms == 0)
7196 return WERR_BADFID;
7199 switch (level) {
7200 case 1:
7201 if (foundBuiltin) {
7202 fill_form_1(&form_1, &builtin_form);
7203 } else {
7205 /* Check if the requested name is in the list of form structures */
7206 for (i=0; i<numofforms; i++) {
7208 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7210 if (strequal(form_name, list[i].name)) {
7211 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7212 fill_form_1(&form_1, &list[i]);
7213 break;
7217 SAFE_FREE(list);
7218 if (i == numofforms) {
7219 return WERR_BADFID;
7222 /* check the required size. */
7224 *needed=spoolss_size_form_1(&form_1);
7226 if (*needed > offered)
7227 return WERR_INSUFFICIENT_BUFFER;
7229 if (!rpcbuf_alloc_size(buffer, buffer_size))
7230 return WERR_NOMEM;
7232 /* fill the buffer with the form structures */
7233 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7234 smb_io_form_1("", buffer, &form_1, 0);
7236 return WERR_OK;
7238 default:
7239 SAFE_FREE(list);
7240 return WERR_UNKNOWN_LEVEL;
7244 /****************************************************************************
7245 ****************************************************************************/
7247 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7249 init_unistr(&port->port_name, name);
7252 /****************************************************************************
7253 TODO: This probably needs distinguish between TCP/IP and Local ports
7254 somehow.
7255 ****************************************************************************/
7257 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7259 init_unistr(&port->port_name, name);
7260 init_unistr(&port->monitor_name, "Local Monitor");
7261 init_unistr(&port->description, SPL_LOCAL_PORT );
7262 port->port_type=PORT_TYPE_WRITE;
7263 port->reserved=0x0;
7267 /****************************************************************************
7268 wrapper around the enumer ports command
7269 ****************************************************************************/
7271 WERROR enumports_hook( int *count, char ***lines )
7273 char *cmd = lp_enumports_cmd();
7274 char **qlines;
7275 pstring command;
7276 int numlines;
7277 int ret;
7278 int fd;
7280 *count = 0;
7281 *lines = NULL;
7283 /* if no hook then just fill in the default port */
7285 if ( !*cmd ) {
7286 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7287 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7288 qlines[1] = NULL;
7289 numlines = 1;
7291 else {
7292 /* we have a valid enumport command */
7294 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7296 DEBUG(10,("Running [%s]\n", command));
7297 ret = smbrun(command, &fd);
7298 DEBUG(10,("Returned [%d]\n", ret));
7299 if (ret != 0) {
7300 if (fd != -1) {
7301 close(fd);
7303 return WERR_ACCESS_DENIED;
7306 numlines = 0;
7307 qlines = fd_lines_load(fd, &numlines, 0);
7308 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7309 close(fd);
7312 *count = numlines;
7313 *lines = qlines;
7315 return WERR_OK;
7318 /****************************************************************************
7319 enumports level 1.
7320 ****************************************************************************/
7322 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7324 PORT_INFO_1 *ports=NULL;
7325 int i=0;
7326 WERROR result = WERR_OK;
7327 char **qlines = NULL;
7328 int numlines = 0;
7330 result = enumports_hook( &numlines, &qlines );
7331 if (!W_ERROR_IS_OK(result)) {
7332 file_lines_free(qlines);
7333 return result;
7336 if(numlines) {
7337 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7338 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7339 dos_errstr(WERR_NOMEM)));
7340 file_lines_free(qlines);
7341 return WERR_NOMEM;
7344 for (i=0; i<numlines; i++) {
7345 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7346 fill_port_1(&ports[i], qlines[i]);
7349 file_lines_free(qlines);
7351 *returned = numlines;
7353 /* check the required size. */
7354 for (i=0; i<*returned; i++) {
7355 DEBUGADD(6,("adding port [%d]'s size\n", i));
7356 *needed += spoolss_size_port_info_1(&ports[i]);
7359 if (*needed > offered) {
7360 result = WERR_INSUFFICIENT_BUFFER;
7361 goto out;
7364 if (!rpcbuf_alloc_size(buffer, *needed)) {
7365 result = WERR_NOMEM;
7366 goto out;
7369 /* fill the buffer with the ports structures */
7370 for (i=0; i<*returned; i++) {
7371 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7372 smb_io_port_1("", buffer, &ports[i], 0);
7375 out:
7376 SAFE_FREE(ports);
7378 if ( !W_ERROR_IS_OK(result) )
7379 *returned = 0;
7381 return result;
7384 /****************************************************************************
7385 enumports level 2.
7386 ****************************************************************************/
7388 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7390 PORT_INFO_2 *ports=NULL;
7391 int i=0;
7392 WERROR result = WERR_OK;
7393 char **qlines = NULL;
7394 int numlines = 0;
7396 result = enumports_hook( &numlines, &qlines );
7397 if ( !W_ERROR_IS_OK(result)) {
7398 file_lines_free(qlines);
7399 return result;
7402 if(numlines) {
7403 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7404 file_lines_free(qlines);
7405 return WERR_NOMEM;
7408 for (i=0; i<numlines; i++) {
7409 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7410 fill_port_2(&(ports[i]), qlines[i]);
7414 file_lines_free(qlines);
7416 *returned = numlines;
7418 /* check the required size. */
7419 for (i=0; i<*returned; i++) {
7420 DEBUGADD(6,("adding port [%d]'s size\n", i));
7421 *needed += spoolss_size_port_info_2(&ports[i]);
7424 if (*needed > offered) {
7425 result = WERR_INSUFFICIENT_BUFFER;
7426 goto out;
7429 if (!rpcbuf_alloc_size(buffer, *needed)) {
7430 result = WERR_NOMEM;
7431 goto out;
7434 /* fill the buffer with the ports structures */
7435 for (i=0; i<*returned; i++) {
7436 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7437 smb_io_port_2("", buffer, &ports[i], 0);
7440 out:
7441 SAFE_FREE(ports);
7443 if ( !W_ERROR_IS_OK(result) )
7444 *returned = 0;
7446 return result;
7449 /****************************************************************************
7450 enumports.
7451 ****************************************************************************/
7453 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7455 uint32 level = q_u->level;
7456 RPC_BUFFER *buffer = NULL;
7457 uint32 offered = q_u->offered;
7458 uint32 *needed = &r_u->needed;
7459 uint32 *returned = &r_u->returned;
7461 /* that's an [in out] buffer */
7463 if (!q_u->buffer && (offered!=0)) {
7464 return WERR_INVALID_PARAM;
7467 rpcbuf_move(q_u->buffer, &r_u->buffer);
7468 buffer = r_u->buffer;
7470 DEBUG(4,("_spoolss_enumports\n"));
7472 *returned=0;
7473 *needed=0;
7475 switch (level) {
7476 case 1:
7477 return enumports_level_1(buffer, offered, needed, returned);
7478 case 2:
7479 return enumports_level_2(buffer, offered, needed, returned);
7480 default:
7481 return WERR_UNKNOWN_LEVEL;
7485 /****************************************************************************
7486 ****************************************************************************/
7488 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7489 const SPOOL_PRINTER_INFO_LEVEL *info,
7490 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7491 uint32 user_switch, const SPOOL_USER_CTR *user,
7492 POLICY_HND *handle)
7494 NT_PRINTER_INFO_LEVEL *printer = NULL;
7495 fstring name;
7496 int snum;
7497 WERROR err = WERR_OK;
7499 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7500 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7501 return WERR_NOMEM;
7504 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7505 if (!convert_printer_info(info, printer, 2)) {
7506 free_a_printer(&printer, 2);
7507 return WERR_NOMEM;
7510 /* check to see if the printer already exists */
7512 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7513 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7514 printer->info_2->sharename));
7515 free_a_printer(&printer, 2);
7516 return WERR_PRINTER_ALREADY_EXISTS;
7519 /* FIXME!!! smbd should check to see if the driver is installed before
7520 trying to add a printer like this --jerry */
7522 if (*lp_addprinter_cmd() ) {
7523 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7524 free_a_printer(&printer,2);
7525 return WERR_ACCESS_DENIED;
7527 } else {
7528 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7529 "smb.conf parameter \"addprinter command\" is defined. This"
7530 "parameter must exist for this call to succeed\n",
7531 printer->info_2->sharename ));
7534 /* use our primary netbios name since get_a_printer() will convert
7535 it to what the client expects on a case by case basis */
7537 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7538 printer->info_2->sharename);
7541 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7542 free_a_printer(&printer,2);
7543 return WERR_ACCESS_DENIED;
7546 /* you must be a printer admin to add a new printer */
7547 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7548 free_a_printer(&printer,2);
7549 return WERR_ACCESS_DENIED;
7553 * Do sanity check on the requested changes for Samba.
7556 if (!check_printer_ok(printer->info_2, snum)) {
7557 free_a_printer(&printer,2);
7558 return WERR_INVALID_PARAM;
7562 * When a printer is created, the drivername bound to the printer is used
7563 * to lookup previously saved driver initialization info, which is then
7564 * bound to the new printer, simulating what happens in the Windows arch.
7567 if (!devmode)
7569 set_driver_init(printer, 2);
7571 else
7573 /* A valid devmode was included, convert and link it
7575 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7577 if (!convert_devicemode(printer->info_2->printername, devmode,
7578 &printer->info_2->devmode))
7579 return WERR_NOMEM;
7582 /* write the ASCII on disk */
7583 err = mod_a_printer(printer, 2);
7584 if (!W_ERROR_IS_OK(err)) {
7585 free_a_printer(&printer,2);
7586 return err;
7589 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7590 /* Handle open failed - remove addition. */
7591 del_a_printer(printer->info_2->sharename);
7592 free_a_printer(&printer,2);
7593 return WERR_ACCESS_DENIED;
7596 update_c_setprinter(False);
7597 free_a_printer(&printer,2);
7599 return WERR_OK;
7602 /****************************************************************************
7603 ****************************************************************************/
7605 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7607 UNISTR2 *uni_srv_name = q_u->server_name;
7608 uint32 level = q_u->level;
7609 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7610 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7611 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7612 uint32 user_switch = q_u->user_switch;
7613 SPOOL_USER_CTR *user = &q_u->user_ctr;
7614 POLICY_HND *handle = &r_u->handle;
7616 switch (level) {
7617 case 1:
7618 /* we don't handle yet */
7619 /* but I know what to do ... */
7620 return WERR_UNKNOWN_LEVEL;
7621 case 2:
7622 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7623 devmode, sdb,
7624 user_switch, user, handle);
7625 default:
7626 return WERR_UNKNOWN_LEVEL;
7630 /****************************************************************************
7631 ****************************************************************************/
7633 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7635 uint32 level = q_u->level;
7636 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7637 WERROR err = WERR_OK;
7638 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7639 struct current_user user;
7640 fstring driver_name;
7641 uint32 version;
7643 ZERO_STRUCT(driver);
7645 get_current_user(&user, p);
7647 if (!convert_printer_driver_info(info, &driver, level)) {
7648 err = WERR_NOMEM;
7649 goto done;
7652 DEBUG(5,("Cleaning driver's information\n"));
7653 err = clean_up_driver_struct(driver, level, &user);
7654 if (!W_ERROR_IS_OK(err))
7655 goto done;
7657 DEBUG(5,("Moving driver to final destination\n"));
7658 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7659 goto done;
7662 if (add_a_printer_driver(driver, level)!=0) {
7663 err = WERR_ACCESS_DENIED;
7664 goto done;
7668 * I think this is where he DrvUpgradePrinter() hook would be
7669 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7670 * server. Right now, we just need to send ourselves a message
7671 * to update each printer bound to this driver. --jerry
7674 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7675 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7676 driver_name));
7680 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7681 * decide if the driver init data should be deleted. The rules are:
7682 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7683 * 2) delete init data only if there is no 2k/Xp driver
7684 * 3) always delete init data
7685 * The generalized rule is always use init data from the highest order driver.
7686 * It is necessary to follow the driver install by an initialization step to
7687 * finish off this process.
7689 if (level == 3)
7690 version = driver.info_3->cversion;
7691 else if (level == 6)
7692 version = driver.info_6->version;
7693 else
7694 version = -1;
7695 switch (version) {
7697 * 9x printer driver - never delete init data
7699 case 0:
7700 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7701 driver_name));
7702 break;
7705 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7706 * there is no 2k/Xp driver init data for this driver name.
7708 case 2:
7710 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7712 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7714 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7716 if (!del_driver_init(driver_name))
7717 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7718 } else {
7720 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7722 free_a_printer_driver(driver1,3);
7723 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7724 driver_name));
7727 break;
7730 * 2k or Xp printer driver - always delete init data
7732 case 3:
7733 if (!del_driver_init(driver_name))
7734 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7735 break;
7737 default:
7738 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7739 break;
7743 done:
7744 free_a_printer_driver(driver, level);
7745 return err;
7748 /********************************************************************
7749 * spoolss_addprinterdriverex
7750 ********************************************************************/
7752 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7754 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7755 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7758 * we only support the semantics of AddPrinterDriver()
7759 * i.e. only copy files that are newer than existing ones
7762 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7763 return WERR_ACCESS_DENIED;
7765 ZERO_STRUCT(q_u_local);
7766 ZERO_STRUCT(r_u_local);
7768 /* just pass the information off to _spoolss_addprinterdriver() */
7769 q_u_local.server_name_ptr = q_u->server_name_ptr;
7770 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7771 q_u_local.level = q_u->level;
7772 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7774 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7777 /****************************************************************************
7778 ****************************************************************************/
7780 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7782 init_unistr(&info->name, name);
7785 /****************************************************************************
7786 ****************************************************************************/
7788 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7790 pstring path;
7791 pstring long_archi;
7792 fstring servername;
7793 char *pservername;
7794 const char *short_archi;
7795 DRIVER_DIRECTORY_1 *info=NULL;
7796 WERROR result = WERR_OK;
7798 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7799 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7801 /* check for beginning double '\'s and that the server
7802 long enough */
7804 pservername = servername;
7805 if ( *pservername == '\\' && strlen(servername)>2 ) {
7806 pservername += 2;
7809 if ( !is_myname_or_ipaddr( pservername ) )
7810 return WERR_INVALID_PARAM;
7812 if (!(short_archi = get_short_archi(long_archi)))
7813 return WERR_INVALID_ENVIRONMENT;
7815 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7816 return WERR_NOMEM;
7818 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7820 DEBUG(4,("printer driver directory: [%s]\n", path));
7822 fill_driverdir_1(info, path);
7824 *needed += spoolss_size_driverdir_info_1(info);
7826 if (*needed > offered) {
7827 result = WERR_INSUFFICIENT_BUFFER;
7828 goto out;
7831 if (!rpcbuf_alloc_size(buffer, *needed)) {
7832 result = WERR_NOMEM;
7833 goto out;
7836 smb_io_driverdir_1("", buffer, info, 0);
7838 out:
7839 SAFE_FREE(info);
7841 return result;
7844 /****************************************************************************
7845 ****************************************************************************/
7847 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7849 UNISTR2 *name = &q_u->name;
7850 UNISTR2 *uni_environment = &q_u->environment;
7851 uint32 level = q_u->level;
7852 RPC_BUFFER *buffer = NULL;
7853 uint32 offered = q_u->offered;
7854 uint32 *needed = &r_u->needed;
7856 /* that's an [in out] buffer */
7858 if (!q_u->buffer && (offered!=0)) {
7859 return WERR_INVALID_PARAM;
7862 rpcbuf_move(q_u->buffer, &r_u->buffer);
7863 buffer = r_u->buffer;
7865 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7867 *needed=0;
7869 switch(level) {
7870 case 1:
7871 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7872 default:
7873 return WERR_UNKNOWN_LEVEL;
7877 /****************************************************************************
7878 ****************************************************************************/
7880 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7882 POLICY_HND *handle = &q_u->handle;
7883 uint32 idx = q_u->index;
7884 uint32 in_value_len = q_u->valuesize;
7885 uint32 in_data_len = q_u->datasize;
7886 uint32 *out_max_value_len = &r_u->valuesize;
7887 uint16 **out_value = &r_u->value;
7888 uint32 *out_value_len = &r_u->realvaluesize;
7889 uint32 *out_type = &r_u->type;
7890 uint32 *out_max_data_len = &r_u->datasize;
7891 uint8 **data_out = &r_u->data;
7892 uint32 *out_data_len = &r_u->realdatasize;
7894 NT_PRINTER_INFO_LEVEL *printer = NULL;
7896 uint32 biggest_valuesize;
7897 uint32 biggest_datasize;
7898 uint32 data_len;
7899 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7900 int snum;
7901 WERROR result;
7902 REGISTRY_VALUE *val = NULL;
7903 NT_PRINTER_DATA *p_data;
7904 int i, key_index, num_values;
7905 int name_length;
7907 *out_type = 0;
7909 *out_max_data_len = 0;
7910 *data_out = NULL;
7911 *out_data_len = 0;
7913 DEBUG(5,("spoolss_enumprinterdata\n"));
7915 if (!Printer) {
7916 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7917 return WERR_BADFID;
7920 if (!get_printer_snum(p,handle, &snum))
7921 return WERR_BADFID;
7923 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7924 if (!W_ERROR_IS_OK(result))
7925 return result;
7927 p_data = printer->info_2->data;
7928 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7930 result = WERR_OK;
7933 * The NT machine wants to know the biggest size of value and data
7935 * cf: MSDN EnumPrinterData remark section
7938 if ( !in_value_len && !in_data_len && (key_index != -1) )
7940 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7942 biggest_valuesize = 0;
7943 biggest_datasize = 0;
7945 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7947 for ( i=0; i<num_values; i++ )
7949 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7951 name_length = strlen(val->valuename);
7952 if ( strlen(val->valuename) > biggest_valuesize )
7953 biggest_valuesize = name_length;
7955 if ( val->size > biggest_datasize )
7956 biggest_datasize = val->size;
7958 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7959 biggest_datasize));
7962 /* the value is an UNICODE string but real_value_size is the length
7963 in bytes including the trailing 0 */
7965 *out_value_len = 2 * (1+biggest_valuesize);
7966 *out_data_len = biggest_datasize;
7968 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7970 goto done;
7974 * the value len is wrong in NT sp3
7975 * that's the number of bytes not the number of unicode chars
7978 if ( key_index != -1 )
7979 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7981 if ( !val )
7984 /* out_value should default to "" or else NT4 has
7985 problems unmarshalling the response */
7987 *out_max_value_len=(in_value_len/sizeof(uint16));
7989 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7991 result = WERR_NOMEM;
7992 goto done;
7995 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7997 /* the data is counted in bytes */
7999 *out_max_data_len = in_data_len;
8000 *out_data_len = in_data_len;
8002 /* only allocate when given a non-zero data_len */
8004 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8006 result = WERR_NOMEM;
8007 goto done;
8010 result = WERR_NO_MORE_ITEMS;
8012 else
8015 * the value is:
8016 * - counted in bytes in the request
8017 * - counted in UNICODE chars in the max reply
8018 * - counted in bytes in the real size
8020 * take a pause *before* coding not *during* coding
8023 /* name */
8024 *out_max_value_len=(in_value_len/sizeof(uint16));
8025 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8027 result = WERR_NOMEM;
8028 goto done;
8031 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8033 /* type */
8035 *out_type = regval_type( val );
8037 /* data - counted in bytes */
8039 *out_max_data_len = in_data_len;
8040 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8042 result = WERR_NOMEM;
8043 goto done;
8045 data_len = regval_size(val);
8046 if ( *data_out )
8047 memcpy( *data_out, regval_data_p(val), data_len );
8048 *out_data_len = data_len;
8051 done:
8052 free_a_printer(&printer, 2);
8053 return result;
8056 /****************************************************************************
8057 ****************************************************************************/
8059 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8061 POLICY_HND *handle = &q_u->handle;
8062 UNISTR2 *value = &q_u->value;
8063 uint32 type = q_u->type;
8064 uint8 *data = q_u->data;
8065 uint32 real_len = q_u->real_len;
8067 NT_PRINTER_INFO_LEVEL *printer = NULL;
8068 int snum=0;
8069 WERROR status = WERR_OK;
8070 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8071 fstring valuename;
8073 DEBUG(5,("spoolss_setprinterdata\n"));
8075 if (!Printer) {
8076 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8077 return WERR_BADFID;
8080 if ( Printer->printer_type == SPLHND_SERVER ) {
8081 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8082 return WERR_INVALID_PARAM;
8085 if (!get_printer_snum(p,handle, &snum))
8086 return WERR_BADFID;
8089 * Access check : NT returns "access denied" if you make a
8090 * SetPrinterData call without the necessary privildge.
8091 * we were originally returning OK if nothing changed
8092 * which made Win2k issue **a lot** of SetPrinterData
8093 * when connecting to a printer --jerry
8096 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8098 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8099 status = WERR_ACCESS_DENIED;
8100 goto done;
8103 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8104 if (!W_ERROR_IS_OK(status))
8105 return status;
8107 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8110 * When client side code sets a magic printer data key, detect it and save
8111 * the current printer data and the magic key's data (its the DEVMODE) for
8112 * future printer/driver initializations.
8114 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8116 /* Set devmode and printer initialization info */
8117 status = save_driver_init( printer, 2, data, real_len );
8119 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8121 else
8123 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8124 type, data, real_len );
8125 if ( W_ERROR_IS_OK(status) )
8126 status = mod_a_printer(printer, 2);
8129 done:
8130 free_a_printer(&printer, 2);
8132 return status;
8135 /****************************************************************************
8136 ****************************************************************************/
8138 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8140 POLICY_HND *handle = &q_u->handle;
8141 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8142 int snum;
8144 DEBUG(5,("_spoolss_resetprinter\n"));
8147 * All we do is to check to see if the handle and queue is valid.
8148 * This call really doesn't mean anything to us because we only
8149 * support RAW printing. --jerry
8152 if (!Printer) {
8153 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8154 return WERR_BADFID;
8157 if (!get_printer_snum(p,handle, &snum))
8158 return WERR_BADFID;
8161 /* blindly return success */
8162 return WERR_OK;
8166 /****************************************************************************
8167 ****************************************************************************/
8169 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8171 POLICY_HND *handle = &q_u->handle;
8172 UNISTR2 *value = &q_u->valuename;
8174 NT_PRINTER_INFO_LEVEL *printer = NULL;
8175 int snum=0;
8176 WERROR status = WERR_OK;
8177 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8178 pstring valuename;
8180 DEBUG(5,("spoolss_deleteprinterdata\n"));
8182 if (!Printer) {
8183 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8184 return WERR_BADFID;
8187 if (!get_printer_snum(p, handle, &snum))
8188 return WERR_BADFID;
8190 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8191 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8192 return WERR_ACCESS_DENIED;
8195 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8196 if (!W_ERROR_IS_OK(status))
8197 return status;
8199 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8201 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8203 if ( W_ERROR_IS_OK(status) )
8204 mod_a_printer( printer, 2 );
8206 free_a_printer(&printer, 2);
8208 return status;
8211 /****************************************************************************
8212 ****************************************************************************/
8214 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8216 POLICY_HND *handle = &q_u->handle;
8217 FORM *form = &q_u->form;
8218 nt_forms_struct tmpForm;
8219 int snum;
8220 WERROR status = WERR_OK;
8221 NT_PRINTER_INFO_LEVEL *printer = NULL;
8223 int count=0;
8224 nt_forms_struct *list=NULL;
8225 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8227 DEBUG(5,("spoolss_addform\n"));
8229 if (!Printer) {
8230 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8231 return WERR_BADFID;
8235 /* forms can be added on printer of on the print server handle */
8237 if ( Printer->printer_type == SPLHND_PRINTER )
8239 if (!get_printer_snum(p,handle, &snum))
8240 return WERR_BADFID;
8242 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8243 if (!W_ERROR_IS_OK(status))
8244 goto done;
8247 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8248 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8249 status = WERR_ACCESS_DENIED;
8250 goto done;
8253 /* can't add if builtin */
8255 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8256 status = WERR_ALREADY_EXISTS;
8257 goto done;
8260 count = get_ntforms(&list);
8262 if(!add_a_form(&list, form, &count)) {
8263 status = WERR_NOMEM;
8264 goto done;
8267 write_ntforms(&list, count);
8270 * ChangeID must always be set if this is a printer
8273 if ( Printer->printer_type == SPLHND_PRINTER )
8274 status = mod_a_printer(printer, 2);
8276 done:
8277 if ( printer )
8278 free_a_printer(&printer, 2);
8279 SAFE_FREE(list);
8281 return status;
8284 /****************************************************************************
8285 ****************************************************************************/
8287 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8289 POLICY_HND *handle = &q_u->handle;
8290 UNISTR2 *form_name = &q_u->name;
8291 nt_forms_struct tmpForm;
8292 int count=0;
8293 nt_forms_struct *list=NULL;
8294 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8295 int snum;
8296 WERROR status = WERR_OK;
8297 NT_PRINTER_INFO_LEVEL *printer = NULL;
8299 DEBUG(5,("spoolss_deleteform\n"));
8301 if (!Printer) {
8302 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8303 return WERR_BADFID;
8306 /* forms can be deleted on printer of on the print server handle */
8308 if ( Printer->printer_type == SPLHND_PRINTER )
8310 if (!get_printer_snum(p,handle, &snum))
8311 return WERR_BADFID;
8313 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8314 if (!W_ERROR_IS_OK(status))
8315 goto done;
8318 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8319 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8320 status = WERR_ACCESS_DENIED;
8321 goto done;
8324 /* can't delete if builtin */
8326 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8327 status = WERR_INVALID_PARAM;
8328 goto done;
8331 count = get_ntforms(&list);
8333 if ( !delete_a_form(&list, form_name, &count, &status ))
8334 goto done;
8337 * ChangeID must always be set if this is a printer
8340 if ( Printer->printer_type == SPLHND_PRINTER )
8341 status = mod_a_printer(printer, 2);
8343 done:
8344 if ( printer )
8345 free_a_printer(&printer, 2);
8346 SAFE_FREE(list);
8348 return status;
8351 /****************************************************************************
8352 ****************************************************************************/
8354 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8356 POLICY_HND *handle = &q_u->handle;
8357 FORM *form = &q_u->form;
8358 nt_forms_struct tmpForm;
8359 int snum;
8360 WERROR status = WERR_OK;
8361 NT_PRINTER_INFO_LEVEL *printer = NULL;
8363 int count=0;
8364 nt_forms_struct *list=NULL;
8365 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8367 DEBUG(5,("spoolss_setform\n"));
8369 if (!Printer) {
8370 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8371 return WERR_BADFID;
8374 /* forms can be modified on printer of on the print server handle */
8376 if ( Printer->printer_type == SPLHND_PRINTER )
8378 if (!get_printer_snum(p,handle, &snum))
8379 return WERR_BADFID;
8381 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8382 if (!W_ERROR_IS_OK(status))
8383 goto done;
8386 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8387 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8388 status = WERR_ACCESS_DENIED;
8389 goto done;
8392 /* can't set if builtin */
8393 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8394 status = WERR_INVALID_PARAM;
8395 goto done;
8398 count = get_ntforms(&list);
8399 update_a_form(&list, form, count);
8400 write_ntforms(&list, count);
8403 * ChangeID must always be set if this is a printer
8406 if ( Printer->printer_type == SPLHND_PRINTER )
8407 status = mod_a_printer(printer, 2);
8410 done:
8411 if ( printer )
8412 free_a_printer(&printer, 2);
8413 SAFE_FREE(list);
8415 return status;
8418 /****************************************************************************
8419 enumprintprocessors level 1.
8420 ****************************************************************************/
8422 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8424 PRINTPROCESSOR_1 *info_1=NULL;
8425 WERROR result = WERR_OK;
8427 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8428 return WERR_NOMEM;
8430 (*returned) = 0x1;
8432 init_unistr(&info_1->name, "winprint");
8434 *needed += spoolss_size_printprocessor_info_1(info_1);
8436 if (*needed > offered) {
8437 result = WERR_INSUFFICIENT_BUFFER;
8438 goto out;
8441 if (!rpcbuf_alloc_size(buffer, *needed)) {
8442 result = WERR_NOMEM;
8443 goto out;
8446 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8448 out:
8449 SAFE_FREE(info_1);
8451 if ( !W_ERROR_IS_OK(result) )
8452 *returned = 0;
8454 return result;
8457 /****************************************************************************
8458 ****************************************************************************/
8460 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8462 uint32 level = q_u->level;
8463 RPC_BUFFER *buffer = NULL;
8464 uint32 offered = q_u->offered;
8465 uint32 *needed = &r_u->needed;
8466 uint32 *returned = &r_u->returned;
8468 /* that's an [in out] buffer */
8470 if (!q_u->buffer && (offered!=0)) {
8471 return WERR_INVALID_PARAM;
8474 rpcbuf_move(q_u->buffer, &r_u->buffer);
8475 buffer = r_u->buffer;
8477 DEBUG(5,("spoolss_enumprintprocessors\n"));
8480 * Enumerate the print processors ...
8482 * Just reply with "winprint", to keep NT happy
8483 * and I can use my nice printer checker.
8486 *returned=0;
8487 *needed=0;
8489 switch (level) {
8490 case 1:
8491 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8492 default:
8493 return WERR_UNKNOWN_LEVEL;
8497 /****************************************************************************
8498 enumprintprocdatatypes level 1.
8499 ****************************************************************************/
8501 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8503 PRINTPROCDATATYPE_1 *info_1=NULL;
8504 WERROR result = WERR_OK;
8506 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8507 return WERR_NOMEM;
8509 (*returned) = 0x1;
8511 init_unistr(&info_1->name, "RAW");
8513 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8515 if (*needed > offered) {
8516 result = WERR_INSUFFICIENT_BUFFER;
8517 goto out;
8520 if (!rpcbuf_alloc_size(buffer, *needed)) {
8521 result = WERR_NOMEM;
8522 goto out;
8525 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8527 out:
8528 SAFE_FREE(info_1);
8530 if ( !W_ERROR_IS_OK(result) )
8531 *returned = 0;
8533 return result;
8536 /****************************************************************************
8537 ****************************************************************************/
8539 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8541 uint32 level = q_u->level;
8542 RPC_BUFFER *buffer = NULL;
8543 uint32 offered = q_u->offered;
8544 uint32 *needed = &r_u->needed;
8545 uint32 *returned = &r_u->returned;
8547 /* that's an [in out] buffer */
8549 if (!q_u->buffer && (offered!=0)) {
8550 return WERR_INVALID_PARAM;
8553 rpcbuf_move(q_u->buffer, &r_u->buffer);
8554 buffer = r_u->buffer;
8556 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8558 *returned=0;
8559 *needed=0;
8561 switch (level) {
8562 case 1:
8563 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8564 default:
8565 return WERR_UNKNOWN_LEVEL;
8569 /****************************************************************************
8570 enumprintmonitors level 1.
8571 ****************************************************************************/
8573 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8575 PRINTMONITOR_1 *info_1;
8576 WERROR result = WERR_OK;
8577 int i;
8579 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8580 return WERR_NOMEM;
8582 *returned = 2;
8584 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8585 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8587 for ( i=0; i<*returned; i++ ) {
8588 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8591 if (*needed > offered) {
8592 result = WERR_INSUFFICIENT_BUFFER;
8593 goto out;
8596 if (!rpcbuf_alloc_size(buffer, *needed)) {
8597 result = WERR_NOMEM;
8598 goto out;
8601 for ( i=0; i<*returned; i++ ) {
8602 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8605 out:
8606 SAFE_FREE(info_1);
8608 if ( !W_ERROR_IS_OK(result) )
8609 *returned = 0;
8611 return result;
8614 /****************************************************************************
8615 enumprintmonitors level 2.
8616 ****************************************************************************/
8618 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8620 PRINTMONITOR_2 *info_2;
8621 WERROR result = WERR_OK;
8622 int i;
8624 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8625 return WERR_NOMEM;
8627 *returned = 2;
8629 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8630 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8631 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8633 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8634 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8635 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8637 for ( i=0; i<*returned; i++ ) {
8638 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8641 if (*needed > offered) {
8642 result = WERR_INSUFFICIENT_BUFFER;
8643 goto out;
8646 if (!rpcbuf_alloc_size(buffer, *needed)) {
8647 result = WERR_NOMEM;
8648 goto out;
8651 for ( i=0; i<*returned; i++ ) {
8652 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8655 out:
8656 SAFE_FREE(info_2);
8658 if ( !W_ERROR_IS_OK(result) )
8659 *returned = 0;
8661 return result;
8664 /****************************************************************************
8665 ****************************************************************************/
8667 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8669 uint32 level = q_u->level;
8670 RPC_BUFFER *buffer = NULL;
8671 uint32 offered = q_u->offered;
8672 uint32 *needed = &r_u->needed;
8673 uint32 *returned = &r_u->returned;
8675 /* that's an [in out] buffer */
8677 if (!q_u->buffer && (offered!=0)) {
8678 return WERR_INVALID_PARAM;
8681 rpcbuf_move(q_u->buffer, &r_u->buffer);
8682 buffer = r_u->buffer;
8684 DEBUG(5,("spoolss_enumprintmonitors\n"));
8687 * Enumerate the print monitors ...
8689 * Just reply with "Local Port", to keep NT happy
8690 * and I can use my nice printer checker.
8693 *returned=0;
8694 *needed=0;
8696 switch (level) {
8697 case 1:
8698 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8699 case 2:
8700 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8701 default:
8702 return WERR_UNKNOWN_LEVEL;
8706 /****************************************************************************
8707 ****************************************************************************/
8709 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8710 NT_PRINTER_INFO_LEVEL *ntprinter,
8711 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8712 uint32 *needed)
8714 int i=0;
8715 BOOL found=False;
8716 JOB_INFO_1 *info_1=NULL;
8717 WERROR result = WERR_OK;
8719 info_1=SMB_MALLOC_P(JOB_INFO_1);
8721 if (info_1 == NULL) {
8722 return WERR_NOMEM;
8725 for (i=0; i<count && found==False; i++) {
8726 if ((*queue)[i].job==(int)jobid)
8727 found=True;
8730 if (found==False) {
8731 SAFE_FREE(info_1);
8732 /* NT treats not found as bad param... yet another bad choice */
8733 return WERR_INVALID_PARAM;
8736 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8738 *needed += spoolss_size_job_info_1(info_1);
8740 if (*needed > offered) {
8741 result = WERR_INSUFFICIENT_BUFFER;
8742 goto out;
8745 if (!rpcbuf_alloc_size(buffer, *needed)) {
8746 result = WERR_NOMEM;
8747 goto out;
8750 smb_io_job_info_1("", buffer, info_1, 0);
8752 out:
8753 SAFE_FREE(info_1);
8755 return result;
8758 /****************************************************************************
8759 ****************************************************************************/
8761 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8762 NT_PRINTER_INFO_LEVEL *ntprinter,
8763 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8764 uint32 *needed)
8766 int i = 0;
8767 BOOL found = False;
8768 JOB_INFO_2 *info_2;
8769 WERROR result;
8770 DEVICEMODE *devmode = NULL;
8771 NT_DEVICEMODE *nt_devmode = NULL;
8773 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8774 return WERR_NOMEM;
8776 ZERO_STRUCTP(info_2);
8778 for ( i=0; i<count && found==False; i++ )
8780 if ((*queue)[i].job == (int)jobid)
8781 found = True;
8784 if ( !found ) {
8785 /* NT treats not found as bad param... yet another bad
8786 choice */
8787 result = WERR_INVALID_PARAM;
8788 goto done;
8792 * if the print job does not have a DEVMODE associated with it,
8793 * just use the one for the printer. A NULL devicemode is not
8794 * a failure condition
8797 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8798 devmode = construct_dev_mode(lp_const_servicename(snum));
8799 else {
8800 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8801 ZERO_STRUCTP( devmode );
8802 convert_nt_devicemode( devmode, nt_devmode );
8806 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8808 *needed += spoolss_size_job_info_2(info_2);
8810 if (*needed > offered) {
8811 result = WERR_INSUFFICIENT_BUFFER;
8812 goto done;
8815 if (!rpcbuf_alloc_size(buffer, *needed)) {
8816 result = WERR_NOMEM;
8817 goto done;
8820 smb_io_job_info_2("", buffer, info_2, 0);
8822 result = WERR_OK;
8824 done:
8825 /* Cleanup allocated memory */
8827 free_job_info_2(info_2); /* Also frees devmode */
8828 SAFE_FREE(info_2);
8830 return result;
8833 /****************************************************************************
8834 ****************************************************************************/
8836 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8838 POLICY_HND *handle = &q_u->handle;
8839 uint32 jobid = q_u->jobid;
8840 uint32 level = q_u->level;
8841 RPC_BUFFER *buffer = NULL;
8842 uint32 offered = q_u->offered;
8843 uint32 *needed = &r_u->needed;
8844 WERROR wstatus = WERR_OK;
8845 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8846 int snum;
8847 int count;
8848 print_queue_struct *queue = NULL;
8849 print_status_struct prt_status;
8851 /* that's an [in out] buffer */
8853 if (!q_u->buffer && (offered!=0)) {
8854 return WERR_INVALID_PARAM;
8857 rpcbuf_move(q_u->buffer, &r_u->buffer);
8858 buffer = r_u->buffer;
8860 DEBUG(5,("spoolss_getjob\n"));
8862 *needed = 0;
8864 if (!get_printer_snum(p, handle, &snum))
8865 return WERR_BADFID;
8867 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8868 if ( !W_ERROR_IS_OK(wstatus) )
8869 return wstatus;
8871 count = print_queue_status(snum, &queue, &prt_status);
8873 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8874 count, prt_status.status, prt_status.message));
8876 switch ( level ) {
8877 case 1:
8878 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8879 buffer, offered, needed);
8880 break;
8881 case 2:
8882 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8883 buffer, offered, needed);
8884 break;
8885 default:
8886 wstatus = WERR_UNKNOWN_LEVEL;
8887 break;
8890 SAFE_FREE(queue);
8891 free_a_printer( &ntprinter, 2 );
8893 return wstatus;
8896 /********************************************************************
8897 spoolss_getprinterdataex
8899 From MSDN documentation of GetPrinterDataEx: pass request
8900 to GetPrinterData if key is "PrinterDriverData".
8901 ********************************************************************/
8903 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8905 POLICY_HND *handle = &q_u->handle;
8906 uint32 in_size = q_u->size;
8907 uint32 *type = &r_u->type;
8908 uint32 *out_size = &r_u->size;
8909 uint8 **data = &r_u->data;
8910 uint32 *needed = &r_u->needed;
8911 fstring keyname, valuename;
8913 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8915 NT_PRINTER_INFO_LEVEL *printer = NULL;
8916 int snum = 0;
8917 WERROR status = WERR_OK;
8919 DEBUG(4,("_spoolss_getprinterdataex\n"));
8921 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8922 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8924 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8925 keyname, valuename));
8927 /* in case of problem, return some default values */
8929 *needed = 0;
8930 *type = 0;
8931 *out_size = in_size;
8933 if (!Printer) {
8934 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8935 status = WERR_BADFID;
8936 goto done;
8939 /* Is the handle to a printer or to the server? */
8941 if (Printer->printer_type == SPLHND_SERVER) {
8942 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8943 status = WERR_INVALID_PARAM;
8944 goto done;
8947 if ( !get_printer_snum(p,handle, &snum) )
8948 return WERR_BADFID;
8950 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8951 if ( !W_ERROR_IS_OK(status) )
8952 goto done;
8954 /* check to see if the keyname is valid */
8955 if ( !strlen(keyname) ) {
8956 status = WERR_INVALID_PARAM;
8957 goto done;
8960 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8961 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8962 free_a_printer( &printer, 2 );
8963 status = WERR_BADFILE;
8964 goto done;
8967 /* When given a new keyname, we should just create it */
8969 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8971 if (*needed > *out_size)
8972 status = WERR_MORE_DATA;
8974 done:
8975 if ( !W_ERROR_IS_OK(status) )
8977 DEBUG(5, ("error: allocating %d\n", *out_size));
8979 /* reply this param doesn't exist */
8981 if ( *out_size )
8983 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8984 status = WERR_NOMEM;
8985 goto done;
8988 else {
8989 *data = NULL;
8993 if ( printer )
8994 free_a_printer( &printer, 2 );
8996 return status;
8999 /********************************************************************
9000 * spoolss_setprinterdataex
9001 ********************************************************************/
9003 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9005 POLICY_HND *handle = &q_u->handle;
9006 uint32 type = q_u->type;
9007 uint8 *data = q_u->data;
9008 uint32 real_len = q_u->real_len;
9010 NT_PRINTER_INFO_LEVEL *printer = NULL;
9011 int snum = 0;
9012 WERROR status = WERR_OK;
9013 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9014 fstring valuename;
9015 fstring keyname;
9016 char *oid_string;
9018 DEBUG(4,("_spoolss_setprinterdataex\n"));
9020 /* From MSDN documentation of SetPrinterDataEx: pass request to
9021 SetPrinterData if key is "PrinterDriverData" */
9023 if (!Printer) {
9024 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9025 return WERR_BADFID;
9028 if ( Printer->printer_type == SPLHND_SERVER ) {
9029 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9030 return WERR_INVALID_PARAM;
9033 if ( !get_printer_snum(p,handle, &snum) )
9034 return WERR_BADFID;
9037 * Access check : NT returns "access denied" if you make a
9038 * SetPrinterData call without the necessary privildge.
9039 * we were originally returning OK if nothing changed
9040 * which made Win2k issue **a lot** of SetPrinterData
9041 * when connecting to a printer --jerry
9044 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9046 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9047 return WERR_ACCESS_DENIED;
9050 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9051 if (!W_ERROR_IS_OK(status))
9052 return status;
9054 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9055 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9057 /* check for OID in valuename */
9059 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9061 *oid_string = '\0';
9062 oid_string++;
9065 /* save the registry data */
9067 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9069 if ( W_ERROR_IS_OK(status) )
9071 /* save the OID if one was specified */
9072 if ( oid_string ) {
9073 fstrcat( keyname, "\\" );
9074 fstrcat( keyname, SPOOL_OID_KEY );
9077 * I'm not checking the status here on purpose. Don't know
9078 * if this is right, but I'm returning the status from the
9079 * previous set_printer_dataex() call. I have no idea if
9080 * this is right. --jerry
9083 set_printer_dataex( printer, keyname, valuename,
9084 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9087 status = mod_a_printer(printer, 2);
9090 free_a_printer(&printer, 2);
9092 return status;
9096 /********************************************************************
9097 * spoolss_deleteprinterdataex
9098 ********************************************************************/
9100 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9102 POLICY_HND *handle = &q_u->handle;
9103 UNISTR2 *value = &q_u->valuename;
9104 UNISTR2 *key = &q_u->keyname;
9106 NT_PRINTER_INFO_LEVEL *printer = NULL;
9107 int snum=0;
9108 WERROR status = WERR_OK;
9109 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9110 pstring valuename, keyname;
9112 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9114 if (!Printer) {
9115 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9116 return WERR_BADFID;
9119 if (!get_printer_snum(p, handle, &snum))
9120 return WERR_BADFID;
9122 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9123 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9124 return WERR_ACCESS_DENIED;
9127 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9128 if (!W_ERROR_IS_OK(status))
9129 return status;
9131 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9132 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9134 status = delete_printer_dataex( printer, keyname, valuename );
9136 if ( W_ERROR_IS_OK(status) )
9137 mod_a_printer( printer, 2 );
9139 free_a_printer(&printer, 2);
9141 return status;
9144 /********************************************************************
9145 * spoolss_enumprinterkey
9146 ********************************************************************/
9149 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9151 fstring key;
9152 fstring *keynames = NULL;
9153 uint16 *enumkeys = NULL;
9154 int num_keys;
9155 int printerkey_len;
9156 POLICY_HND *handle = &q_u->handle;
9157 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9158 NT_PRINTER_DATA *data;
9159 NT_PRINTER_INFO_LEVEL *printer = NULL;
9160 int snum = 0;
9161 WERROR status = WERR_BADFILE;
9164 DEBUG(4,("_spoolss_enumprinterkey\n"));
9166 if (!Printer) {
9167 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9168 return WERR_BADFID;
9171 if ( !get_printer_snum(p,handle, &snum) )
9172 return WERR_BADFID;
9174 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9175 if (!W_ERROR_IS_OK(status))
9176 return status;
9178 /* get the list of subkey names */
9180 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9181 data = printer->info_2->data;
9183 num_keys = get_printer_subkeys( data, key, &keynames );
9185 if ( num_keys == -1 ) {
9186 status = WERR_BADFILE;
9187 goto done;
9190 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9192 r_u->needed = printerkey_len*2;
9194 if ( q_u->size < r_u->needed ) {
9195 status = WERR_MORE_DATA;
9196 goto done;
9199 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9200 status = WERR_NOMEM;
9201 goto done;
9204 status = WERR_OK;
9206 if ( q_u->size < r_u->needed )
9207 status = WERR_MORE_DATA;
9209 done:
9210 free_a_printer( &printer, 2 );
9211 SAFE_FREE( keynames );
9213 return status;
9216 /********************************************************************
9217 * spoolss_deleteprinterkey
9218 ********************************************************************/
9220 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9222 POLICY_HND *handle = &q_u->handle;
9223 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9224 fstring key;
9225 NT_PRINTER_INFO_LEVEL *printer = NULL;
9226 int snum=0;
9227 WERROR status;
9229 DEBUG(5,("spoolss_deleteprinterkey\n"));
9231 if (!Printer) {
9232 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9233 return WERR_BADFID;
9236 /* if keyname == NULL, return error */
9238 if ( !q_u->keyname.buffer )
9239 return WERR_INVALID_PARAM;
9241 if (!get_printer_snum(p, handle, &snum))
9242 return WERR_BADFID;
9244 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9245 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9246 return WERR_ACCESS_DENIED;
9249 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9250 if (!W_ERROR_IS_OK(status))
9251 return status;
9253 /* delete the key and all subneys */
9255 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9257 status = delete_all_printer_data( printer->info_2, key );
9259 if ( W_ERROR_IS_OK(status) )
9260 status = mod_a_printer(printer, 2);
9262 free_a_printer( &printer, 2 );
9264 return status;
9268 /********************************************************************
9269 * spoolss_enumprinterdataex
9270 ********************************************************************/
9272 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9274 POLICY_HND *handle = &q_u->handle;
9275 uint32 in_size = q_u->size;
9276 uint32 num_entries,
9277 needed;
9278 NT_PRINTER_INFO_LEVEL *printer = NULL;
9279 PRINTER_ENUM_VALUES *enum_values = NULL;
9280 NT_PRINTER_DATA *p_data;
9281 fstring key;
9282 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9283 int snum;
9284 WERROR result;
9285 int key_index;
9286 int i;
9287 REGISTRY_VALUE *val;
9288 char *value_name;
9289 uint32 data_len;
9292 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9294 if (!Printer) {
9295 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9296 return WERR_BADFID;
9300 * first check for a keyname of NULL or "". Win2k seems to send
9301 * this a lot and we should send back WERR_INVALID_PARAM
9302 * no need to spend time looking up the printer in this case.
9303 * --jerry
9306 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9307 if ( !strlen(key) ) {
9308 result = WERR_INVALID_PARAM;
9309 goto done;
9312 /* get the printer off of disk */
9314 if (!get_printer_snum(p,handle, &snum))
9315 return WERR_BADFID;
9317 ZERO_STRUCT(printer);
9318 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9319 if (!W_ERROR_IS_OK(result))
9320 return result;
9322 /* now look for a match on the key name */
9324 p_data = printer->info_2->data;
9326 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9327 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9329 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9330 result = WERR_INVALID_PARAM;
9331 goto done;
9334 result = WERR_OK;
9335 needed = 0;
9337 /* allocate the memory for the array of pointers -- if necessary */
9339 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9340 if ( num_entries )
9342 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9344 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9345 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9346 result = WERR_NOMEM;
9347 goto done;
9350 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9354 * loop through all params and build the array to pass
9355 * back to the client
9358 for ( i=0; i<num_entries; i++ )
9360 /* lookup the registry value */
9362 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9363 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9365 /* copy the data */
9367 value_name = regval_name( val );
9368 init_unistr( &enum_values[i].valuename, value_name );
9369 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9370 enum_values[i].type = regval_type( val );
9372 data_len = regval_size( val );
9373 if ( data_len ) {
9374 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9376 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9377 data_len ));
9378 result = WERR_NOMEM;
9379 goto done;
9382 enum_values[i].data_len = data_len;
9384 /* keep track of the size of the array in bytes */
9386 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9389 /* housekeeping information in the reply */
9391 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9392 * the hand marshalled container size is a multiple
9393 * of 4 bytes for RPC alignment.
9396 if (needed % 4) {
9397 needed += 4-(needed % 4);
9400 r_u->needed = needed;
9401 r_u->returned = num_entries;
9403 if (needed > in_size) {
9404 result = WERR_MORE_DATA;
9405 goto done;
9408 /* copy data into the reply */
9410 r_u->ctr.size = r_u->needed;
9412 r_u->ctr.size_of_array = r_u->returned;
9413 r_u->ctr.values = enum_values;
9417 done:
9418 if ( printer )
9419 free_a_printer(&printer, 2);
9421 return result;
9424 /****************************************************************************
9425 ****************************************************************************/
9427 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9429 init_unistr(&info->name, name);
9432 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9433 UNISTR2 *environment,
9434 RPC_BUFFER *buffer,
9435 uint32 offered,
9436 uint32 *needed)
9438 pstring path;
9439 pstring long_archi;
9440 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9441 WERROR result = WERR_OK;
9443 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9445 if (!get_short_archi(long_archi))
9446 return WERR_INVALID_ENVIRONMENT;
9448 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9449 return WERR_NOMEM;
9451 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9453 fill_printprocessordirectory_1(info, path);
9455 *needed += spoolss_size_printprocessordirectory_info_1(info);
9457 if (*needed > offered) {
9458 result = WERR_INSUFFICIENT_BUFFER;
9459 goto out;
9462 if (!rpcbuf_alloc_size(buffer, *needed)) {
9463 result = WERR_INSUFFICIENT_BUFFER;
9464 goto out;
9467 smb_io_printprocessordirectory_1("", buffer, info, 0);
9469 out:
9470 SAFE_FREE(info);
9472 return result;
9475 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9477 uint32 level = q_u->level;
9478 RPC_BUFFER *buffer = NULL;
9479 uint32 offered = q_u->offered;
9480 uint32 *needed = &r_u->needed;
9481 WERROR result;
9483 /* that's an [in out] buffer */
9485 if (!q_u->buffer && (offered!=0)) {
9486 return WERR_INVALID_PARAM;
9489 rpcbuf_move(q_u->buffer, &r_u->buffer);
9490 buffer = r_u->buffer;
9492 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9494 *needed=0;
9496 switch(level) {
9497 case 1:
9498 result = getprintprocessordirectory_level_1
9499 (&q_u->name, &q_u->environment, buffer, offered, needed);
9500 break;
9501 default:
9502 result = WERR_UNKNOWN_LEVEL;
9505 return result;
9508 /*******************************************************************
9509 Streams the monitor UI DLL name in UNICODE
9510 *******************************************************************/
9512 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9513 RPC_BUFFER *out, uint32 *needed )
9515 const char *dllname = "tcpmonui.dll";
9517 *needed = (strlen(dllname)+1) * 2;
9519 if ( rpcbuf_get_size(out) < *needed ) {
9520 return WERR_INSUFFICIENT_BUFFER;
9523 if ( !make_monitorui_buf( out, dllname ) ) {
9524 return WERR_NOMEM;
9527 return WERR_OK;
9530 /*******************************************************************
9531 Create a new TCP/IP port
9532 *******************************************************************/
9534 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9535 RPC_BUFFER *out, uint32 *needed )
9537 NT_PORT_DATA_1 port1;
9538 pstring device_uri;
9540 ZERO_STRUCT( port1 );
9542 /* convert to our internal port data structure */
9544 if ( !convert_port_data_1( &port1, in ) ) {
9545 return WERR_NOMEM;
9548 /* create the device URI and call the add_port_hook() */
9550 switch ( port1.protocol ) {
9551 case PORT_PROTOCOL_DIRECT:
9552 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9553 break;
9555 case PORT_PROTOCOL_LPR:
9556 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9557 break;
9559 default:
9560 return WERR_UNKNOWN_PORT;
9563 return add_port_hook( token, port1.name, device_uri );
9566 /*******************************************************************
9567 *******************************************************************/
9569 struct xcv_api_table xcvtcp_cmds[] = {
9570 { "MonitorUI", xcvtcp_monitorui },
9571 { "AddPort", xcvtcp_addport},
9572 { NULL, NULL }
9575 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9576 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9577 uint32 *needed )
9579 int i;
9581 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9583 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9584 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9585 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9588 return WERR_BADFUNC;
9591 /*******************************************************************
9592 *******************************************************************/
9593 #if 0 /* don't support management using the "Local Port" monitor */
9595 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9596 RPC_BUFFER *out, uint32 *needed )
9598 const char *dllname = "localui.dll";
9600 *needed = (strlen(dllname)+1) * 2;
9602 if ( rpcbuf_get_size(out) < *needed ) {
9603 return WERR_INSUFFICIENT_BUFFER;
9606 if ( !make_monitorui_buf( out, dllname )) {
9607 return WERR_NOMEM;
9610 return WERR_OK;
9613 /*******************************************************************
9614 *******************************************************************/
9616 struct xcv_api_table xcvlocal_cmds[] = {
9617 { "MonitorUI", xcvlocal_monitorui },
9618 { NULL, NULL }
9620 #else
9621 struct xcv_api_table xcvlocal_cmds[] = {
9622 { NULL, NULL }
9624 #endif
9628 /*******************************************************************
9629 *******************************************************************/
9631 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9632 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9633 uint32 *needed )
9635 int i;
9637 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9639 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9640 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9641 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9643 return WERR_BADFUNC;
9646 /*******************************************************************
9647 *******************************************************************/
9649 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9651 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9652 fstring command;
9654 if (!Printer) {
9655 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9656 return WERR_BADFID;
9659 /* Has to be a handle to the TCP/IP port monitor */
9661 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9662 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9663 return WERR_BADFID;
9666 /* requires administrative access to the server */
9668 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9669 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9670 return WERR_ACCESS_DENIED;
9673 /* Get the command name. There's numerous commands supported by the
9674 TCPMON interface. */
9676 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9677 q_u->dataname.uni_str_len*2, 0);
9679 /* Allocate the outgoing buffer */
9681 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9683 switch ( Printer->printer_type ) {
9684 case SPLHND_PORTMON_TCP:
9685 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9686 &q_u->indata, &r_u->outdata, &r_u->needed );
9687 case SPLHND_PORTMON_LOCAL:
9688 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9689 &q_u->indata, &r_u->outdata, &r_u->needed );
9692 return WERR_INVALID_PRINT_MONITOR;