[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob4cf43f04e49ca884ea47a4bf82ce468fb12f18f9
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 if (prs_offset(&ps)) {
719 data->notify_data.data.string = (uint16 *)
720 TALLOC(mem_ctx, prs_offset(&ps));
721 if (!data->notify_data.data.string) {
722 prs_mem_free(&ps);
723 return;
725 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
726 } else {
727 data->notify_data.data.string = NULL;
730 prs_mem_free(&ps);
733 struct notify2_message_table {
734 const char *name;
735 void (*fn)(struct spoolss_notify_msg *msg,
736 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
739 static struct notify2_message_table printer_notify_table[] = {
740 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
741 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
742 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
743 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
744 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
745 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
746 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
747 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
748 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
749 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
750 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
751 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
752 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
753 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
754 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
755 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
756 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
757 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
758 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
761 static struct notify2_message_table job_notify_table[] = {
762 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
763 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
764 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
765 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
766 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
767 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
768 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
769 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
770 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
771 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
772 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
773 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
774 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
775 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
776 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
777 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
778 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
779 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
780 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
781 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
782 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
783 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
784 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
785 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
789 /***********************************************************************
790 Allocate talloc context for container object
791 **********************************************************************/
793 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
795 if ( !ctr )
796 return;
798 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
800 return;
803 /***********************************************************************
804 release all allocated memory and zero out structure
805 **********************************************************************/
807 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
809 if ( !ctr )
810 return;
812 if ( ctr->ctx )
813 talloc_destroy(ctr->ctx);
815 ZERO_STRUCTP(ctr);
817 return;
820 /***********************************************************************
821 **********************************************************************/
823 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
825 if ( !ctr )
826 return NULL;
828 return ctr->ctx;
831 /***********************************************************************
832 **********************************************************************/
834 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
836 if ( !ctr || !ctr->msg_groups )
837 return NULL;
839 if ( idx >= ctr->num_groups )
840 return NULL;
842 return &ctr->msg_groups[idx];
846 /***********************************************************************
847 How many groups of change messages do we have ?
848 **********************************************************************/
850 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
852 if ( !ctr )
853 return 0;
855 return ctr->num_groups;
858 /***********************************************************************
859 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
860 **********************************************************************/
862 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
864 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
865 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
866 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
867 int i, new_slot;
869 if ( !ctr || !msg )
870 return 0;
872 /* loop over all groups looking for a matching printer name */
874 for ( i=0; i<ctr->num_groups; i++ ) {
875 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
876 break;
879 /* add a new group? */
881 if ( i == ctr->num_groups ) {
882 ctr->num_groups++;
884 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
885 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
886 return 0;
888 ctr->msg_groups = groups;
890 /* clear the new entry and set the printer name */
892 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
893 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
896 /* add the change messages; 'i' is the correct index now regardless */
898 msg_grp = &ctr->msg_groups[i];
900 msg_grp->num_msgs++;
902 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
903 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
904 return 0;
906 msg_grp->msgs = msg_list;
908 new_slot = msg_grp->num_msgs-1;
909 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
911 /* need to allocate own copy of data */
913 if ( msg->len != 0 )
914 msg_grp->msgs[new_slot].notify.data = (char *)
915 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
917 return ctr->num_groups;
920 /***********************************************************************
921 Send a change notication message on all handles which have a call
922 back registered
923 **********************************************************************/
925 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
927 Printer_entry *p;
928 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
929 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
930 SPOOLSS_NOTIFY_MSG *messages;
931 int sending_msg_count;
933 if ( !msg_group ) {
934 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
935 return;
938 messages = msg_group->msgs;
940 if ( !messages ) {
941 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
942 return;
945 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
947 /* loop over all printers */
949 for (p = printers_list; p; p = p->next) {
950 SPOOL_NOTIFY_INFO_DATA *data;
951 uint32 data_len = 0;
952 uint32 id;
953 int i;
955 /* Is there notification on this handle? */
957 if ( !p->notify.client_connected )
958 continue;
960 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
962 /* For this printer? Print servers always receive
963 notifications. */
965 if ( ( p->printer_type == SPLHND_PRINTER ) &&
966 ( !strequal(msg_group->printername, p->sharename) ) )
967 continue;
969 DEBUG(10,("Our printer\n"));
971 /* allocate the max entries possible */
973 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
974 if (!data) {
975 return;
978 ZERO_STRUCTP(data);
980 /* build the array of change notifications */
982 sending_msg_count = 0;
984 for ( i=0; i<msg_group->num_msgs; i++ ) {
985 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
987 /* Are we monitoring this event? */
989 if (!is_monitoring_event(p, msg->type, msg->field))
990 continue;
992 sending_msg_count++;
995 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
996 msg->type, msg->field, p->sharename));
999 * if the is a printer notification handle and not a job notification
1000 * type, then set the id to 0. Other wise just use what was specified
1001 * in the message.
1003 * When registering change notification on a print server handle
1004 * we always need to send back the id (snum) matching the printer
1005 * for which the change took place. For change notify registered
1006 * on a printer handle, this does not matter and the id should be 0.
1008 * --jerry
1011 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1012 id = 0;
1013 else
1014 id = msg->id;
1017 /* Convert unix jobid to smb jobid */
1019 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1020 id = sysjob_to_jobid(msg->id);
1022 if (id == -1) {
1023 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1024 goto done;
1028 construct_info_data( &data[data_len], msg->type, msg->field, id );
1030 switch(msg->type) {
1031 case PRINTER_NOTIFY_TYPE:
1032 if ( printer_notify_table[msg->field].fn )
1033 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1034 break;
1036 case JOB_NOTIFY_TYPE:
1037 if ( job_notify_table[msg->field].fn )
1038 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1039 break;
1041 default:
1042 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1043 goto done;
1046 data_len++;
1049 if ( sending_msg_count ) {
1050 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1051 data_len, data, p->notify.change, 0 );
1055 done:
1056 DEBUG(8,("send_notify2_changes: Exit...\n"));
1057 return;
1060 /***********************************************************************
1061 **********************************************************************/
1063 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1066 uint32 tv_sec, tv_usec;
1067 size_t offset = 0;
1069 /* Unpack message */
1071 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1072 msg->printer);
1074 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1075 &tv_sec, &tv_usec,
1076 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1078 if (msg->len == 0)
1079 tdb_unpack((char *)buf + offset, len - offset, "dd",
1080 &msg->notify.value[0], &msg->notify.value[1]);
1081 else
1082 tdb_unpack((char *)buf + offset, len - offset, "B",
1083 &msg->len, &msg->notify.data);
1085 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1086 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1088 tv->tv_sec = tv_sec;
1089 tv->tv_usec = tv_usec;
1091 if (msg->len == 0)
1092 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1093 msg->notify.value[1]));
1094 else
1095 dump_data(3, msg->notify.data, msg->len);
1097 return True;
1100 /********************************************************************
1101 Receive a notify2 message list
1102 ********************************************************************/
1104 static void receive_notify2_message_list(int msg_type, struct process_id src,
1105 void *msg, size_t len,
1106 void *private_data)
1108 size_t msg_count, i;
1109 char *buf = (char *)msg;
1110 char *msg_ptr;
1111 size_t msg_len;
1112 SPOOLSS_NOTIFY_MSG notify;
1113 SPOOLSS_NOTIFY_MSG_CTR messages;
1114 int num_groups;
1116 if (len < 4) {
1117 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1118 return;
1121 msg_count = IVAL(buf, 0);
1122 msg_ptr = buf + 4;
1124 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1126 if (msg_count == 0) {
1127 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1128 return;
1131 /* initialize the container */
1133 ZERO_STRUCT( messages );
1134 notify_msg_ctr_init( &messages );
1137 * build message groups for each printer identified
1138 * in a change_notify msg. Remember that a PCN message
1139 * includes the handle returned for the srv_spoolss_replyopenprinter()
1140 * call. Therefore messages are grouped according to printer handle.
1143 for ( i=0; i<msg_count; i++ ) {
1144 struct timeval msg_tv;
1146 if (msg_ptr + 4 - buf > len) {
1147 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1148 return;
1151 msg_len = IVAL(msg_ptr,0);
1152 msg_ptr += 4;
1154 if (msg_ptr + msg_len - buf > len) {
1155 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1156 return;
1159 /* unpack messages */
1161 ZERO_STRUCT( notify );
1162 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1163 msg_ptr += msg_len;
1165 /* add to correct list in container */
1167 notify_msg_ctr_addmsg( &messages, &notify );
1169 /* free memory that might have been allocated by notify2_unpack_msg() */
1171 if ( notify.len != 0 )
1172 SAFE_FREE( notify.notify.data );
1175 /* process each group of messages */
1177 num_groups = notify_msg_ctr_numgroups( &messages );
1178 for ( i=0; i<num_groups; i++ )
1179 send_notify2_changes( &messages, i );
1182 /* cleanup */
1184 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1186 notify_msg_ctr_destroy( &messages );
1188 return;
1191 /********************************************************************
1192 Send a message to ourself about new driver being installed
1193 so we can upgrade the information for each printer bound to this
1194 driver
1195 ********************************************************************/
1197 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1199 int len = strlen(drivername);
1201 if (!len)
1202 return False;
1204 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1205 drivername));
1207 message_send_pid(pid_to_procid(sys_getpid()),
1208 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1210 return True;
1213 /**********************************************************************
1214 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1215 over all printers, upgrading ones as necessary
1216 **********************************************************************/
1218 void do_drv_upgrade_printer(int msg_type, struct process_id src,
1219 void *buf, size_t len, void *private_data)
1221 fstring drivername;
1222 int snum;
1223 int n_services = lp_numservices();
1225 len = MIN(len,sizeof(drivername)-1);
1226 strncpy(drivername, (const char *)buf, len);
1228 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1230 /* Iterate the printer list */
1232 for (snum=0; snum<n_services; snum++)
1234 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1236 WERROR result;
1237 NT_PRINTER_INFO_LEVEL *printer = NULL;
1239 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1240 if (!W_ERROR_IS_OK(result))
1241 continue;
1243 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1245 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1247 /* all we care about currently is the change_id */
1249 result = mod_a_printer(printer, 2);
1250 if (!W_ERROR_IS_OK(result)) {
1251 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1252 dos_errstr(result)));
1256 free_a_printer(&printer, 2);
1260 /* all done */
1263 /********************************************************************
1264 Update the cache for all printq's with a registered client
1265 connection
1266 ********************************************************************/
1268 void update_monitored_printq_cache( void )
1270 Printer_entry *printer = printers_list;
1271 int snum;
1273 /* loop through all printers and update the cache where
1274 client_connected == True */
1275 while ( printer )
1277 if ( (printer->printer_type == SPLHND_PRINTER)
1278 && printer->notify.client_connected )
1280 snum = print_queue_snum(printer->sharename);
1281 print_queue_status( snum, NULL, NULL );
1284 printer = printer->next;
1287 return;
1289 /********************************************************************
1290 Send a message to ourself about new driver being installed
1291 so we can upgrade the information for each printer bound to this
1292 driver
1293 ********************************************************************/
1295 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1297 int len = strlen(drivername);
1299 if (!len)
1300 return False;
1302 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1303 drivername));
1305 message_send_pid(pid_to_procid(sys_getpid()),
1306 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1308 return True;
1311 /**********************************************************************
1312 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1313 over all printers, resetting printer data as neessary
1314 **********************************************************************/
1316 void reset_all_printerdata(int msg_type, struct process_id src,
1317 void *buf, size_t len, void *private_data)
1319 fstring drivername;
1320 int snum;
1321 int n_services = lp_numservices();
1323 len = MIN( len, sizeof(drivername)-1 );
1324 strncpy( drivername, (const char *)buf, len );
1326 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1328 /* Iterate the printer list */
1330 for ( snum=0; snum<n_services; snum++ )
1332 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1334 WERROR result;
1335 NT_PRINTER_INFO_LEVEL *printer = NULL;
1337 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1338 if ( !W_ERROR_IS_OK(result) )
1339 continue;
1342 * if the printer is bound to the driver,
1343 * then reset to the new driver initdata
1346 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1348 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1350 if ( !set_driver_init(printer, 2) ) {
1351 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1352 printer->info_2->printername, printer->info_2->drivername));
1355 result = mod_a_printer( printer, 2 );
1356 if ( !W_ERROR_IS_OK(result) ) {
1357 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1358 get_dos_error_msg(result)));
1362 free_a_printer( &printer, 2 );
1366 /* all done */
1368 return;
1371 /********************************************************************
1372 Copy routines used by convert_to_openprinterex()
1373 *******************************************************************/
1375 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1377 DEVICEMODE *d;
1378 int len;
1380 if (!devmode)
1381 return NULL;
1383 DEBUG (8,("dup_devmode\n"));
1385 /* bulk copy first */
1387 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1388 if (!d)
1389 return NULL;
1391 /* dup the pointer members separately */
1393 len = unistrlen(devmode->devicename.buffer);
1394 if (len != -1) {
1395 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1396 if (!d->devicename.buffer) {
1397 return NULL;
1399 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1400 return NULL;
1404 len = unistrlen(devmode->formname.buffer);
1405 if (len != -1) {
1406 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1407 if (!d->devicename.buffer) {
1408 return NULL;
1410 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1411 return NULL;
1414 if (devmode->driverextra) {
1415 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1416 devmode->driverextra);
1417 if (!d->dev_private) {
1418 return NULL;
1420 } else {
1421 d->dev_private = NULL;
1423 return d;
1426 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1428 if (!new_ctr || !ctr)
1429 return;
1431 DEBUG(8,("copy_devmode_ctr\n"));
1433 new_ctr->size = ctr->size;
1434 new_ctr->devmode_ptr = ctr->devmode_ptr;
1436 if(ctr->devmode_ptr)
1437 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1440 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1442 if (!new_def || !def)
1443 return;
1445 DEBUG(8,("copy_printer_defaults\n"));
1447 new_def->datatype_ptr = def->datatype_ptr;
1449 if (def->datatype_ptr)
1450 copy_unistr2(&new_def->datatype, &def->datatype);
1452 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1454 new_def->access_required = def->access_required;
1457 /********************************************************************
1458 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1459 * SPOOL_Q_OPEN_PRINTER_EX structure
1460 ********************************************************************/
1462 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1464 if (!q_u_ex || !q_u)
1465 return WERR_OK;
1467 DEBUG(8,("convert_to_openprinterex\n"));
1469 if ( q_u->printername ) {
1470 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1471 if (q_u_ex->printername == NULL)
1472 return WERR_NOMEM;
1473 copy_unistr2(q_u_ex->printername, q_u->printername);
1476 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1478 return WERR_OK;
1481 /********************************************************************
1482 * spoolss_open_printer
1484 * called from the spoolss dispatcher
1485 ********************************************************************/
1487 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1489 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1490 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1492 if (!q_u || !r_u)
1493 return WERR_NOMEM;
1495 ZERO_STRUCT(q_u_ex);
1496 ZERO_STRUCT(r_u_ex);
1498 /* convert the OpenPrinter() call to OpenPrinterEx() */
1500 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1501 if (!W_ERROR_IS_OK(r_u_ex.status))
1502 return r_u_ex.status;
1504 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1506 /* convert back to OpenPrinter() */
1508 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1510 return r_u->status;
1513 /********************************************************************
1514 ********************************************************************/
1516 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1518 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1519 POLICY_HND *handle = &r_u->handle;
1521 fstring name;
1522 int snum;
1523 struct current_user user;
1524 Printer_entry *Printer=NULL;
1526 if ( !q_u->printername )
1527 return WERR_INVALID_PRINTER_NAME;
1529 /* some sanity check because you can open a printer or a print server */
1530 /* aka: \\server\printer or \\server */
1532 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1534 DEBUGADD(3,("checking name: %s\n",name));
1536 if (!open_printer_hnd(p, handle, name, 0))
1537 return WERR_INVALID_PRINTER_NAME;
1539 Printer=find_printer_index_by_hnd(p, handle);
1540 if ( !Printer ) {
1541 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1542 "handle we created for printer %s\n", name ));
1543 close_printer_handle(p,handle);
1544 return WERR_INVALID_PRINTER_NAME;
1547 get_current_user(&user, p);
1550 * First case: the user is opening the print server:
1552 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1553 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1555 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1556 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1557 * or if the user is listed in the smb.conf printer admin parameter.
1559 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1560 * client view printer folder, but does not show the MSAPW.
1562 * Note: this test needs code to check access rights here too. Jeremy
1563 * could you look at this?
1565 * Second case: the user is opening a printer:
1566 * NT doesn't let us connect to a printer if the connecting user
1567 * doesn't have print permission.
1569 * Third case: user is opening a Port Monitor
1570 * access checks same as opening a handle to the print server.
1573 switch (Printer->printer_type )
1575 case SPLHND_SERVER:
1576 case SPLHND_PORTMON_TCP:
1577 case SPLHND_PORTMON_LOCAL:
1578 /* Printserver handles use global struct... */
1580 snum = -1;
1582 /* Map standard access rights to object specific access rights */
1584 se_map_standard(&printer_default->access_required,
1585 &printserver_std_mapping);
1587 /* Deny any object specific bits that don't apply to print
1588 servers (i.e printer and job specific bits) */
1590 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1592 if (printer_default->access_required &
1593 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1594 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1595 close_printer_handle(p, handle);
1596 return WERR_ACCESS_DENIED;
1599 /* Allow admin access */
1601 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1603 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1605 if (!lp_ms_add_printer_wizard()) {
1606 close_printer_handle(p, handle);
1607 return WERR_ACCESS_DENIED;
1610 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1611 and not a printer admin, then fail */
1613 if ((user.ut.uid != 0) &&
1614 !user_has_privileges(user.nt_user_token,
1615 &se_printop ) &&
1616 !token_contains_name_in_list(
1617 uidtoname(user.ut.uid), NULL,
1618 user.nt_user_token,
1619 lp_printer_admin(snum))) {
1620 close_printer_handle(p, handle);
1621 return WERR_ACCESS_DENIED;
1624 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1626 else
1628 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1631 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1632 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1634 /* We fall through to return WERR_OK */
1635 break;
1637 case SPLHND_PRINTER:
1638 /* NT doesn't let us connect to a printer if the connecting user
1639 doesn't have print permission. */
1641 if (!get_printer_snum(p, handle, &snum)) {
1642 close_printer_handle(p, handle);
1643 return WERR_BADFID;
1646 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1648 /* map an empty access mask to the minimum access mask */
1649 if (printer_default->access_required == 0x0)
1650 printer_default->access_required = PRINTER_ACCESS_USE;
1653 * If we are not serving the printer driver for this printer,
1654 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1655 * will keep NT clients happy --jerry
1658 if (lp_use_client_driver(snum)
1659 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1661 printer_default->access_required = PRINTER_ACCESS_USE;
1664 /* check smb.conf parameters and the the sec_desc */
1666 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1667 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1668 return WERR_ACCESS_DENIED;
1671 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1672 snum) ||
1673 !print_access_check(&user, snum,
1674 printer_default->access_required)) {
1675 DEBUG(3, ("access DENIED for printer open\n"));
1676 close_printer_handle(p, handle);
1677 return WERR_ACCESS_DENIED;
1680 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1681 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1682 close_printer_handle(p, handle);
1683 return WERR_ACCESS_DENIED;
1686 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1687 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1688 else
1689 printer_default->access_required = PRINTER_ACCESS_USE;
1691 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1692 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1694 break;
1696 default:
1697 /* sanity check to prevent programmer error */
1698 return WERR_BADFID;
1701 Printer->access_granted = printer_default->access_required;
1704 * If the client sent a devmode in the OpenPrinter() call, then
1705 * save it here in case we get a job submission on this handle
1708 if ( (Printer->printer_type != SPLHND_SERVER)
1709 && q_u->printer_default.devmode_cont.devmode_ptr )
1711 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1712 &Printer->nt_devmode );
1715 #if 0 /* JERRY -- I'm doubtful this is really effective */
1716 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1717 optimization in Windows 2000 clients --jerry */
1719 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1720 && (RA_WIN2K == get_remote_arch()) )
1722 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1723 sys_usleep( 500000 );
1725 #endif
1727 return WERR_OK;
1730 /****************************************************************************
1731 ****************************************************************************/
1733 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1734 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1736 BOOL ret;
1738 switch (level) {
1739 case 2:
1740 /* allocate memory if needed. Messy because
1741 convert_printer_info is used to update an existing
1742 printer or build a new one */
1744 if ( !printer->info_2 ) {
1745 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1746 if ( !printer->info_2 ) {
1747 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1748 return False;
1752 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1753 printer->info_2->setuptime = time(NULL);
1755 return ret;
1758 return False;
1761 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1762 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1764 BOOL result = True;
1766 switch (level) {
1767 case 3:
1768 printer->info_3=NULL;
1769 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1770 result = False;
1771 break;
1772 case 6:
1773 printer->info_6=NULL;
1774 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1775 result = False;
1776 break;
1777 default:
1778 break;
1781 return result;
1784 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1785 NT_DEVICEMODE **pp_nt_devmode)
1787 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1790 * Ensure nt_devmode is a valid pointer
1791 * as we will be overwriting it.
1794 if (nt_devmode == NULL) {
1795 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1796 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1797 return False;
1800 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1801 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1803 nt_devmode->specversion=devmode->specversion;
1804 nt_devmode->driverversion=devmode->driverversion;
1805 nt_devmode->size=devmode->size;
1806 nt_devmode->fields=devmode->fields;
1807 nt_devmode->orientation=devmode->orientation;
1808 nt_devmode->papersize=devmode->papersize;
1809 nt_devmode->paperlength=devmode->paperlength;
1810 nt_devmode->paperwidth=devmode->paperwidth;
1811 nt_devmode->scale=devmode->scale;
1812 nt_devmode->copies=devmode->copies;
1813 nt_devmode->defaultsource=devmode->defaultsource;
1814 nt_devmode->printquality=devmode->printquality;
1815 nt_devmode->color=devmode->color;
1816 nt_devmode->duplex=devmode->duplex;
1817 nt_devmode->yresolution=devmode->yresolution;
1818 nt_devmode->ttoption=devmode->ttoption;
1819 nt_devmode->collate=devmode->collate;
1821 nt_devmode->logpixels=devmode->logpixels;
1822 nt_devmode->bitsperpel=devmode->bitsperpel;
1823 nt_devmode->pelswidth=devmode->pelswidth;
1824 nt_devmode->pelsheight=devmode->pelsheight;
1825 nt_devmode->displayflags=devmode->displayflags;
1826 nt_devmode->displayfrequency=devmode->displayfrequency;
1827 nt_devmode->icmmethod=devmode->icmmethod;
1828 nt_devmode->icmintent=devmode->icmintent;
1829 nt_devmode->mediatype=devmode->mediatype;
1830 nt_devmode->dithertype=devmode->dithertype;
1831 nt_devmode->reserved1=devmode->reserved1;
1832 nt_devmode->reserved2=devmode->reserved2;
1833 nt_devmode->panningwidth=devmode->panningwidth;
1834 nt_devmode->panningheight=devmode->panningheight;
1837 * Only change private and driverextra if the incoming devmode
1838 * has a new one. JRA.
1841 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1842 SAFE_FREE(nt_devmode->nt_dev_private);
1843 nt_devmode->driverextra=devmode->driverextra;
1844 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1845 return False;
1846 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1849 *pp_nt_devmode = nt_devmode;
1851 return True;
1854 /********************************************************************
1855 * _spoolss_enddocprinter_internal.
1856 ********************************************************************/
1858 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1860 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1861 int snum;
1863 if (!Printer) {
1864 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1865 return WERR_BADFID;
1868 if (!get_printer_snum(p, handle, &snum))
1869 return WERR_BADFID;
1871 Printer->document_started=False;
1872 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1873 /* error codes unhandled so far ... */
1875 return WERR_OK;
1878 /********************************************************************
1879 * api_spoolss_closeprinter
1880 ********************************************************************/
1882 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1884 POLICY_HND *handle = &q_u->handle;
1886 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1888 if (Printer && Printer->document_started)
1889 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1891 if (!close_printer_handle(p, handle))
1892 return WERR_BADFID;
1894 /* clear the returned printer handle. Observed behavior
1895 from Win2k server. Don't think this really matters.
1896 Previous code just copied the value of the closed
1897 handle. --jerry */
1899 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1901 return WERR_OK;
1904 /********************************************************************
1905 * api_spoolss_deleteprinter
1907 ********************************************************************/
1909 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1911 POLICY_HND *handle = &q_u->handle;
1912 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1913 WERROR result;
1915 if (Printer && Printer->document_started)
1916 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1918 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1920 result = delete_printer_handle(p, handle);
1922 update_c_setprinter(False);
1924 return result;
1927 /*******************************************************************
1928 * static function to lookup the version id corresponding to an
1929 * long architecture string
1930 ******************************************************************/
1932 static int get_version_id (char * arch)
1934 int i;
1935 struct table_node archi_table[]= {
1937 {"Windows 4.0", "WIN40", 0 },
1938 {"Windows NT x86", "W32X86", 2 },
1939 {"Windows NT R4000", "W32MIPS", 2 },
1940 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1941 {"Windows NT PowerPC", "W32PPC", 2 },
1942 {"Windows IA64", "IA64", 3 },
1943 {"Windows x64", "x64", 3 },
1944 {NULL, "", -1 }
1947 for (i=0; archi_table[i].long_archi != NULL; i++)
1949 if (strcmp(arch, archi_table[i].long_archi) == 0)
1950 return (archi_table[i].version);
1953 return -1;
1956 /********************************************************************
1957 * _spoolss_deleteprinterdriver
1958 ********************************************************************/
1960 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1962 fstring driver;
1963 fstring arch;
1964 NT_PRINTER_DRIVER_INFO_LEVEL info;
1965 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1966 int version;
1967 struct current_user user;
1968 WERROR status;
1969 WERROR status_win2k = WERR_ACCESS_DENIED;
1970 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1972 get_current_user(&user, p);
1974 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1975 and not a printer admin, then fail */
1977 if ( (user.ut.uid != 0)
1978 && !user_has_privileges(user.nt_user_token, &se_printop )
1979 && !token_contains_name_in_list( uidtoname(user.ut.uid),
1980 NULL, user.nt_user_token, lp_printer_admin(-1)) )
1982 return WERR_ACCESS_DENIED;
1985 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1986 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1988 /* check that we have a valid driver name first */
1990 if ((version=get_version_id(arch)) == -1)
1991 return WERR_INVALID_ENVIRONMENT;
1993 ZERO_STRUCT(info);
1994 ZERO_STRUCT(info_win2k);
1996 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1998 /* try for Win2k driver if "Windows NT x86" */
2000 if ( version == 2 ) {
2001 version = 3;
2002 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2003 status = WERR_UNKNOWN_PRINTER_DRIVER;
2004 goto done;
2007 /* otherwise it was a failure */
2008 else {
2009 status = WERR_UNKNOWN_PRINTER_DRIVER;
2010 goto done;
2015 if (printer_driver_in_use(info.info_3)) {
2016 status = WERR_PRINTER_DRIVER_IN_USE;
2017 goto done;
2020 if ( version == 2 )
2022 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2024 /* if we get to here, we now have 2 driver info structures to remove */
2025 /* remove the Win2k driver first*/
2027 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2028 free_a_printer_driver( info_win2k, 3 );
2030 /* this should not have failed---if it did, report to client */
2031 if ( !W_ERROR_IS_OK(status_win2k) )
2033 status = status_win2k;
2034 goto done;
2039 status = delete_printer_driver(info.info_3, &user, version, False);
2041 /* if at least one of the deletes succeeded return OK */
2043 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2044 status = WERR_OK;
2046 done:
2047 free_a_printer_driver( info, 3 );
2049 return status;
2052 /********************************************************************
2053 * spoolss_deleteprinterdriverex
2054 ********************************************************************/
2056 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2058 fstring driver;
2059 fstring arch;
2060 NT_PRINTER_DRIVER_INFO_LEVEL info;
2061 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2062 int version;
2063 uint32 flags = q_u->delete_flags;
2064 BOOL delete_files;
2065 struct current_user user;
2066 WERROR status;
2067 WERROR status_win2k = WERR_ACCESS_DENIED;
2068 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2070 get_current_user(&user, p);
2072 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2073 and not a printer admin, then fail */
2075 if ( (user.ut.uid != 0)
2076 && !user_has_privileges(user.nt_user_token, &se_printop )
2077 && !token_contains_name_in_list( uidtoname(user.ut.uid),
2078 NULL, user.nt_user_token, lp_printer_admin(-1)) )
2080 return WERR_ACCESS_DENIED;
2083 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2084 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2086 /* check that we have a valid driver name first */
2087 if ((version=get_version_id(arch)) == -1) {
2088 /* this is what NT returns */
2089 return WERR_INVALID_ENVIRONMENT;
2092 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2093 version = q_u->version;
2095 ZERO_STRUCT(info);
2096 ZERO_STRUCT(info_win2k);
2098 status = get_a_printer_driver(&info, 3, driver, arch, version);
2100 if ( !W_ERROR_IS_OK(status) )
2103 * if the client asked for a specific version,
2104 * or this is something other than Windows NT x86,
2105 * then we've failed
2108 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2109 goto done;
2111 /* try for Win2k driver if "Windows NT x86" */
2113 version = 3;
2114 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2115 status = WERR_UNKNOWN_PRINTER_DRIVER;
2116 goto done;
2120 if ( printer_driver_in_use(info.info_3) ) {
2121 status = WERR_PRINTER_DRIVER_IN_USE;
2122 goto done;
2126 * we have a couple of cases to consider.
2127 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2128 * then the delete should fail if **any** files overlap with
2129 * other drivers
2130 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2131 * non-overlapping files
2132 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2133 * is set, the do not delete any files
2134 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2137 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2139 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2141 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2142 /* no idea of the correct error here */
2143 status = WERR_ACCESS_DENIED;
2144 goto done;
2148 /* also check for W32X86/3 if necessary; maybe we already have? */
2150 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2151 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2154 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2155 /* no idea of the correct error here */
2156 free_a_printer_driver( info_win2k, 3 );
2157 status = WERR_ACCESS_DENIED;
2158 goto done;
2161 /* if we get to here, we now have 2 driver info structures to remove */
2162 /* remove the Win2k driver first*/
2164 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2165 free_a_printer_driver( info_win2k, 3 );
2167 /* this should not have failed---if it did, report to client */
2169 if ( !W_ERROR_IS_OK(status_win2k) )
2170 goto done;
2174 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2176 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2177 status = WERR_OK;
2178 done:
2179 free_a_printer_driver( info, 3 );
2181 return status;
2185 /****************************************************************************
2186 Internal routine for retreiving printerdata
2187 ***************************************************************************/
2189 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2190 const char *key, const char *value, uint32 *type, uint8 **data,
2191 uint32 *needed, uint32 in_size )
2193 REGISTRY_VALUE *val;
2194 uint32 size;
2195 int data_len;
2197 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2198 return WERR_BADFILE;
2200 *type = regval_type( val );
2202 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2204 size = regval_size( val );
2206 /* copy the min(in_size, len) */
2208 if ( in_size ) {
2209 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2211 /* special case for 0 length values */
2212 if ( data_len ) {
2213 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2214 return WERR_NOMEM;
2216 else {
2217 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2218 return WERR_NOMEM;
2221 else
2222 *data = NULL;
2224 *needed = size;
2226 DEBUG(5,("get_printer_dataex: copy done\n"));
2228 return WERR_OK;
2231 /****************************************************************************
2232 Internal routine for removing printerdata
2233 ***************************************************************************/
2235 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2237 return delete_printer_data( printer->info_2, key, value );
2240 /****************************************************************************
2241 Internal routine for storing printerdata
2242 ***************************************************************************/
2244 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2245 uint32 type, uint8 *data, int real_len )
2247 /* the registry objects enforce uniqueness based on value name */
2249 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2252 /********************************************************************
2253 GetPrinterData on a printer server Handle.
2254 ********************************************************************/
2256 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2258 int i;
2260 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2262 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2263 *type = REG_DWORD;
2264 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2265 return WERR_NOMEM;
2266 SIVAL(*data, 0, 0x00);
2267 *needed = 0x4;
2268 return WERR_OK;
2271 if (!StrCaseCmp(value, "BeepEnabled")) {
2272 *type = REG_DWORD;
2273 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2274 return WERR_NOMEM;
2275 SIVAL(*data, 0, 0x00);
2276 *needed = 0x4;
2277 return WERR_OK;
2280 if (!StrCaseCmp(value, "EventLog")) {
2281 *type = REG_DWORD;
2282 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2283 return WERR_NOMEM;
2284 /* formally was 0x1b */
2285 SIVAL(*data, 0, 0x0);
2286 *needed = 0x4;
2287 return WERR_OK;
2290 if (!StrCaseCmp(value, "NetPopup")) {
2291 *type = REG_DWORD;
2292 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2293 return WERR_NOMEM;
2294 SIVAL(*data, 0, 0x00);
2295 *needed = 0x4;
2296 return WERR_OK;
2299 if (!StrCaseCmp(value, "MajorVersion")) {
2300 *type = REG_DWORD;
2301 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2302 return WERR_NOMEM;
2304 /* Windows NT 4.0 seems to not allow uploading of drivers
2305 to a server that reports 0x3 as the MajorVersion.
2306 need to investigate more how Win2k gets around this .
2307 -- jerry */
2309 if ( RA_WINNT == get_remote_arch() )
2310 SIVAL(*data, 0, 2);
2311 else
2312 SIVAL(*data, 0, 3);
2314 *needed = 0x4;
2315 return WERR_OK;
2318 if (!StrCaseCmp(value, "MinorVersion")) {
2319 *type = REG_DWORD;
2320 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2321 return WERR_NOMEM;
2322 SIVAL(*data, 0, 0);
2323 *needed = 0x4;
2324 return WERR_OK;
2327 /* REG_BINARY
2328 * uint32 size = 0x114
2329 * uint32 major = 5
2330 * uint32 minor = [0|1]
2331 * uint32 build = [2195|2600]
2332 * extra unicode string = e.g. "Service Pack 3"
2334 if (!StrCaseCmp(value, "OSVersion")) {
2335 *type = REG_BINARY;
2336 *needed = 0x114;
2338 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2339 return WERR_NOMEM;
2341 SIVAL(*data, 0, *needed); /* size */
2342 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2343 SIVAL(*data, 8, 0);
2344 SIVAL(*data, 12, 2195); /* build */
2346 /* leave extra string empty */
2348 return WERR_OK;
2352 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2353 const char *string="C:\\PRINTERS";
2354 *type = REG_SZ;
2355 *needed = 2*(strlen(string)+1);
2356 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2357 return WERR_NOMEM;
2358 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2360 /* it's done by hand ready to go on the wire */
2361 for (i=0; i<strlen(string); i++) {
2362 (*data)[2*i]=string[i];
2363 (*data)[2*i+1]='\0';
2365 return WERR_OK;
2368 if (!StrCaseCmp(value, "Architecture")) {
2369 const char *string="Windows NT x86";
2370 *type = REG_SZ;
2371 *needed = 2*(strlen(string)+1);
2372 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2373 return WERR_NOMEM;
2374 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2375 for (i=0; i<strlen(string); i++) {
2376 (*data)[2*i]=string[i];
2377 (*data)[2*i+1]='\0';
2379 return WERR_OK;
2382 if (!StrCaseCmp(value, "DsPresent")) {
2383 *type = REG_DWORD;
2384 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2385 return WERR_NOMEM;
2387 /* only show the publish check box if we are a
2388 memeber of a AD domain */
2390 if ( lp_security() == SEC_ADS )
2391 SIVAL(*data, 0, 0x01);
2392 else
2393 SIVAL(*data, 0, 0x00);
2395 *needed = 0x4;
2396 return WERR_OK;
2399 if (!StrCaseCmp(value, "DNSMachineName")) {
2400 pstring hostname;
2402 if (!get_mydnsfullname(hostname))
2403 return WERR_BADFILE;
2404 *type = REG_SZ;
2405 *needed = 2*(strlen(hostname)+1);
2406 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2407 return WERR_NOMEM;
2408 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2409 for (i=0; i<strlen(hostname); i++) {
2410 (*data)[2*i]=hostname[i];
2411 (*data)[2*i+1]='\0';
2413 return WERR_OK;
2417 return WERR_BADFILE;
2420 /********************************************************************
2421 * spoolss_getprinterdata
2422 ********************************************************************/
2424 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2426 POLICY_HND *handle = &q_u->handle;
2427 UNISTR2 *valuename = &q_u->valuename;
2428 uint32 in_size = q_u->size;
2429 uint32 *type = &r_u->type;
2430 uint32 *out_size = &r_u->size;
2431 uint8 **data = &r_u->data;
2432 uint32 *needed = &r_u->needed;
2433 WERROR status;
2434 fstring value;
2435 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2436 NT_PRINTER_INFO_LEVEL *printer = NULL;
2437 int snum = 0;
2440 * Reminder: when it's a string, the length is in BYTES
2441 * even if UNICODE is negociated.
2443 * JFM, 4/19/1999
2446 *out_size = in_size;
2448 /* in case of problem, return some default values */
2450 *needed = 0;
2451 *type = 0;
2453 DEBUG(4,("_spoolss_getprinterdata\n"));
2455 if ( !Printer ) {
2456 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2457 status = WERR_BADFID;
2458 goto done;
2461 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2463 if ( Printer->printer_type == SPLHND_SERVER )
2464 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2465 else
2467 if ( !get_printer_snum(p,handle, &snum) ) {
2468 status = WERR_BADFID;
2469 goto done;
2472 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2473 if ( !W_ERROR_IS_OK(status) )
2474 goto done;
2476 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2478 if ( strequal(value, "ChangeId") ) {
2479 *type = REG_DWORD;
2480 *needed = sizeof(uint32);
2481 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2482 status = WERR_NOMEM;
2483 goto done;
2485 SIVAL( *data, 0, printer->info_2->changeid );
2486 status = WERR_OK;
2488 else
2489 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2492 if (*needed > *out_size)
2493 status = WERR_MORE_DATA;
2495 done:
2496 if ( !W_ERROR_IS_OK(status) )
2498 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2500 /* reply this param doesn't exist */
2502 if ( *out_size ) {
2503 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2504 if ( printer )
2505 free_a_printer( &printer, 2 );
2506 return WERR_NOMEM;
2508 } else {
2509 *data = NULL;
2513 /* cleanup & exit */
2515 if ( printer )
2516 free_a_printer( &printer, 2 );
2518 return status;
2521 /*********************************************************
2522 Connect to the client machine.
2523 **********************************************************/
2525 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2526 struct in_addr *client_ip, const char *remote_machine)
2528 NTSTATUS ret;
2529 struct cli_state *the_cli;
2530 struct in_addr rm_addr;
2532 if ( is_zero_ip(*client_ip) ) {
2533 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2534 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2535 return False;
2538 if ( ismyip( rm_addr )) {
2539 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2540 return False;
2542 } else {
2543 rm_addr.s_addr = client_ip->s_addr;
2544 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2545 inet_ntoa(*client_ip) ));
2548 /* setup the connection */
2550 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2551 &rm_addr, 0, "IPC$", "IPC",
2552 "", /* username */
2553 "", /* domain */
2554 "", /* password */
2555 0, lp_client_signing(), NULL );
2557 if ( !NT_STATUS_IS_OK( ret ) ) {
2558 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2559 remote_machine ));
2560 return False;
2563 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2564 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2565 cli_shutdown(the_cli);
2566 return False;
2570 * Ok - we have an anonymous connection to the IPC$ share.
2571 * Now start the NT Domain stuff :-).
2574 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2575 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2576 remote_machine, nt_errstr(ret)));
2577 cli_shutdown(the_cli);
2578 return False;
2581 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2583 (*pp_pipe)->cli = the_cli;
2585 return True;
2588 /***************************************************************************
2589 Connect to the client.
2590 ****************************************************************************/
2592 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2593 uint32 localprinter, uint32 type,
2594 POLICY_HND *handle, struct in_addr *client_ip)
2596 WERROR result;
2599 * If it's the first connection, contact the client
2600 * and connect to the IPC$ share anonymously
2602 if (smb_connections==0) {
2603 fstring unix_printer;
2605 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2607 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ip, unix_printer ))
2608 return False;
2610 message_register(MSG_PRINTER_NOTIFY2,
2611 receive_notify2_message_list, NULL);
2612 /* Tell the connections db we're now interested in printer
2613 * notify messages. */
2614 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2618 * Tell the specific printing tdb we want messages for this printer
2619 * by registering our PID.
2622 if (!print_notify_register_pid(snum))
2623 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2625 smb_connections++;
2627 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2628 type, handle);
2630 if (!W_ERROR_IS_OK(result))
2631 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2632 dos_errstr(result)));
2634 return (W_ERROR_IS_OK(result));
2637 /********************************************************************
2638 * _spoolss_rffpcnex
2639 * ReplyFindFirstPrinterChangeNotifyEx
2641 * before replying OK: status=0 a rpc call is made to the workstation
2642 * asking ReplyOpenPrinter
2644 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2645 * called from api_spoolss_rffpcnex
2646 ********************************************************************/
2648 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2650 POLICY_HND *handle = &q_u->handle;
2651 uint32 flags = q_u->flags;
2652 uint32 options = q_u->options;
2653 UNISTR2 *localmachine = &q_u->localmachine;
2654 uint32 printerlocal = q_u->printerlocal;
2655 int snum = -1;
2656 SPOOL_NOTIFY_OPTION *option = q_u->option;
2657 struct in_addr client_ip;
2659 /* store the notify value in the printer struct */
2661 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2663 if (!Printer) {
2664 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2665 return WERR_BADFID;
2668 Printer->notify.flags=flags;
2669 Printer->notify.options=options;
2670 Printer->notify.printerlocal=printerlocal;
2672 if (Printer->notify.option)
2673 free_spool_notify_option(&Printer->notify.option);
2675 Printer->notify.option=dup_spool_notify_option(option);
2677 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2678 sizeof(Printer->notify.localmachine)-1);
2680 /* Connect to the client machine and send a ReplyOpenPrinter */
2682 if ( Printer->printer_type == SPLHND_SERVER)
2683 snum = -1;
2684 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2685 !get_printer_snum(p, handle, &snum) )
2686 return WERR_BADFID;
2688 client_ip.s_addr = inet_addr(p->conn->client_address);
2690 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2691 Printer->notify.printerlocal, 1,
2692 &Printer->notify.client_hnd, &client_ip))
2693 return WERR_SERVER_UNAVAILABLE;
2695 Printer->notify.client_connected=True;
2697 return WERR_OK;
2700 /*******************************************************************
2701 * fill a notify_info_data with the servername
2702 ********************************************************************/
2704 void spoolss_notify_server_name(int snum,
2705 SPOOL_NOTIFY_INFO_DATA *data,
2706 print_queue_struct *queue,
2707 NT_PRINTER_INFO_LEVEL *printer,
2708 TALLOC_CTX *mem_ctx)
2710 pstring temp;
2711 uint32 len;
2713 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2715 data->notify_data.data.length = len;
2716 if (len) {
2717 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2718 if (!data->notify_data.data.string) {
2719 data->notify_data.data.length = 0;
2720 return;
2723 memcpy(data->notify_data.data.string, temp, len);
2724 } else {
2725 data->notify_data.data.string = NULL;
2729 /*******************************************************************
2730 * fill a notify_info_data with the printername (not including the servername).
2731 ********************************************************************/
2733 void spoolss_notify_printer_name(int snum,
2734 SPOOL_NOTIFY_INFO_DATA *data,
2735 print_queue_struct *queue,
2736 NT_PRINTER_INFO_LEVEL *printer,
2737 TALLOC_CTX *mem_ctx)
2739 pstring temp;
2740 uint32 len;
2742 /* the notify name should not contain the \\server\ part */
2743 char *p = strrchr(printer->info_2->printername, '\\');
2745 if (!p) {
2746 p = printer->info_2->printername;
2747 } else {
2748 p++;
2751 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2753 data->notify_data.data.length = len;
2754 if (len) {
2755 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2756 if (!data->notify_data.data.string) {
2757 data->notify_data.data.length = 0;
2758 return;
2760 memcpy(data->notify_data.data.string, temp, len);
2761 } else {
2762 data->notify_data.data.string = NULL;
2766 /*******************************************************************
2767 * fill a notify_info_data with the servicename
2768 ********************************************************************/
2770 void spoolss_notify_share_name(int snum,
2771 SPOOL_NOTIFY_INFO_DATA *data,
2772 print_queue_struct *queue,
2773 NT_PRINTER_INFO_LEVEL *printer,
2774 TALLOC_CTX *mem_ctx)
2776 pstring temp;
2777 uint32 len;
2779 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2781 data->notify_data.data.length = len;
2782 if (len) {
2783 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2784 if (!data->notify_data.data.string) {
2785 data->notify_data.data.length = 0;
2786 return;
2788 memcpy(data->notify_data.data.string, temp, len);
2789 } else {
2790 data->notify_data.data.string = NULL;
2795 /*******************************************************************
2796 * fill a notify_info_data with the port name
2797 ********************************************************************/
2799 void spoolss_notify_port_name(int snum,
2800 SPOOL_NOTIFY_INFO_DATA *data,
2801 print_queue_struct *queue,
2802 NT_PRINTER_INFO_LEVEL *printer,
2803 TALLOC_CTX *mem_ctx)
2805 pstring temp;
2806 uint32 len;
2808 /* even if it's strange, that's consistant in all the code */
2810 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2812 data->notify_data.data.length = len;
2813 if (len) {
2814 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2816 if (!data->notify_data.data.string) {
2817 data->notify_data.data.length = 0;
2818 return;
2821 memcpy(data->notify_data.data.string, temp, len);
2822 } else {
2823 data->notify_data.data.string = NULL;
2827 /*******************************************************************
2828 * fill a notify_info_data with the printername
2829 * but it doesn't exist, have to see what to do
2830 ********************************************************************/
2832 void spoolss_notify_driver_name(int snum,
2833 SPOOL_NOTIFY_INFO_DATA *data,
2834 print_queue_struct *queue,
2835 NT_PRINTER_INFO_LEVEL *printer,
2836 TALLOC_CTX *mem_ctx)
2838 pstring temp;
2839 uint32 len;
2841 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2843 data->notify_data.data.length = len;
2844 if (len) {
2845 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2847 if (!data->notify_data.data.string) {
2848 data->notify_data.data.length = 0;
2849 return;
2852 memcpy(data->notify_data.data.string, temp, len);
2853 } else {
2854 data->notify_data.data.string = NULL;
2858 /*******************************************************************
2859 * fill a notify_info_data with the comment
2860 ********************************************************************/
2862 void spoolss_notify_comment(int snum,
2863 SPOOL_NOTIFY_INFO_DATA *data,
2864 print_queue_struct *queue,
2865 NT_PRINTER_INFO_LEVEL *printer,
2866 TALLOC_CTX *mem_ctx)
2868 pstring temp;
2869 uint32 len;
2871 if (*printer->info_2->comment == '\0')
2872 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2873 else
2874 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2876 data->notify_data.data.length = len;
2877 if (len) {
2878 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2880 if (!data->notify_data.data.string) {
2881 data->notify_data.data.length = 0;
2882 return;
2885 memcpy(data->notify_data.data.string, temp, len);
2886 } else {
2887 data->notify_data.data.string = NULL;
2891 /*******************************************************************
2892 * fill a notify_info_data with the comment
2893 * location = "Room 1, floor 2, building 3"
2894 ********************************************************************/
2896 void spoolss_notify_location(int snum,
2897 SPOOL_NOTIFY_INFO_DATA *data,
2898 print_queue_struct *queue,
2899 NT_PRINTER_INFO_LEVEL *printer,
2900 TALLOC_CTX *mem_ctx)
2902 pstring temp;
2903 uint32 len;
2905 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2907 data->notify_data.data.length = len;
2908 if (len) {
2909 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2911 if (!data->notify_data.data.string) {
2912 data->notify_data.data.length = 0;
2913 return;
2916 memcpy(data->notify_data.data.string, temp, len);
2917 } else {
2918 data->notify_data.data.string = NULL;
2922 /*******************************************************************
2923 * fill a notify_info_data with the device mode
2924 * jfm:xxxx don't to it for know but that's a real problem !!!
2925 ********************************************************************/
2927 static void spoolss_notify_devmode(int snum,
2928 SPOOL_NOTIFY_INFO_DATA *data,
2929 print_queue_struct *queue,
2930 NT_PRINTER_INFO_LEVEL *printer,
2931 TALLOC_CTX *mem_ctx)
2933 /* for a dummy implementation we have to zero the fields */
2934 data->notify_data.data.length = 0;
2935 data->notify_data.data.string = NULL;
2938 /*******************************************************************
2939 * fill a notify_info_data with the separator file name
2940 ********************************************************************/
2942 void spoolss_notify_sepfile(int snum,
2943 SPOOL_NOTIFY_INFO_DATA *data,
2944 print_queue_struct *queue,
2945 NT_PRINTER_INFO_LEVEL *printer,
2946 TALLOC_CTX *mem_ctx)
2948 pstring temp;
2949 uint32 len;
2951 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2953 data->notify_data.data.length = len;
2954 if (len) {
2955 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2957 if (!data->notify_data.data.string) {
2958 data->notify_data.data.length = 0;
2959 return;
2962 memcpy(data->notify_data.data.string, temp, len);
2963 } else {
2964 data->notify_data.data.string = NULL;
2968 /*******************************************************************
2969 * fill a notify_info_data with the print processor
2970 * jfm:xxxx return always winprint to indicate we don't do anything to it
2971 ********************************************************************/
2973 void spoolss_notify_print_processor(int snum,
2974 SPOOL_NOTIFY_INFO_DATA *data,
2975 print_queue_struct *queue,
2976 NT_PRINTER_INFO_LEVEL *printer,
2977 TALLOC_CTX *mem_ctx)
2979 pstring temp;
2980 uint32 len;
2982 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2984 data->notify_data.data.length = len;
2985 if (len) {
2986 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2988 if (!data->notify_data.data.string) {
2989 data->notify_data.data.length = 0;
2990 return;
2993 memcpy(data->notify_data.data.string, temp, len);
2994 } else {
2995 data->notify_data.data.string = NULL;
2999 /*******************************************************************
3000 * fill a notify_info_data with the print processor options
3001 * jfm:xxxx send an empty string
3002 ********************************************************************/
3004 void spoolss_notify_parameters(int snum,
3005 SPOOL_NOTIFY_INFO_DATA *data,
3006 print_queue_struct *queue,
3007 NT_PRINTER_INFO_LEVEL *printer,
3008 TALLOC_CTX *mem_ctx)
3010 pstring temp;
3011 uint32 len;
3013 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3015 data->notify_data.data.length = len;
3016 if (len) {
3017 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3019 if (!data->notify_data.data.string) {
3020 data->notify_data.data.length = 0;
3021 return;
3024 memcpy(data->notify_data.data.string, temp, len);
3025 } else {
3026 data->notify_data.data.string = NULL;
3030 /*******************************************************************
3031 * fill a notify_info_data with the data type
3032 * jfm:xxxx always send RAW as data type
3033 ********************************************************************/
3035 void spoolss_notify_datatype(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 pstring temp;
3042 uint32 len;
3044 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3046 data->notify_data.data.length = len;
3047 if (len) {
3048 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3050 if (!data->notify_data.data.string) {
3051 data->notify_data.data.length = 0;
3052 return;
3055 memcpy(data->notify_data.data.string, temp, len);
3056 } else {
3057 data->notify_data.data.string = NULL;
3061 /*******************************************************************
3062 * fill a notify_info_data with the security descriptor
3063 * jfm:xxxx send an null pointer to say no security desc
3064 * have to implement security before !
3065 ********************************************************************/
3067 static void spoolss_notify_security_desc(int snum,
3068 SPOOL_NOTIFY_INFO_DATA *data,
3069 print_queue_struct *queue,
3070 NT_PRINTER_INFO_LEVEL *printer,
3071 TALLOC_CTX *mem_ctx)
3073 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3074 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3077 /*******************************************************************
3078 * fill a notify_info_data with the attributes
3079 * jfm:xxxx a samba printer is always shared
3080 ********************************************************************/
3082 void spoolss_notify_attributes(int snum,
3083 SPOOL_NOTIFY_INFO_DATA *data,
3084 print_queue_struct *queue,
3085 NT_PRINTER_INFO_LEVEL *printer,
3086 TALLOC_CTX *mem_ctx)
3088 data->notify_data.value[0] = printer->info_2->attributes;
3089 data->notify_data.value[1] = 0;
3092 /*******************************************************************
3093 * fill a notify_info_data with the priority
3094 ********************************************************************/
3096 static void spoolss_notify_priority(int snum,
3097 SPOOL_NOTIFY_INFO_DATA *data,
3098 print_queue_struct *queue,
3099 NT_PRINTER_INFO_LEVEL *printer,
3100 TALLOC_CTX *mem_ctx)
3102 data->notify_data.value[0] = printer->info_2->priority;
3103 data->notify_data.value[1] = 0;
3106 /*******************************************************************
3107 * fill a notify_info_data with the default priority
3108 ********************************************************************/
3110 static void spoolss_notify_default_priority(int snum,
3111 SPOOL_NOTIFY_INFO_DATA *data,
3112 print_queue_struct *queue,
3113 NT_PRINTER_INFO_LEVEL *printer,
3114 TALLOC_CTX *mem_ctx)
3116 data->notify_data.value[0] = printer->info_2->default_priority;
3117 data->notify_data.value[1] = 0;
3120 /*******************************************************************
3121 * fill a notify_info_data with the start time
3122 ********************************************************************/
3124 static void spoolss_notify_start_time(int snum,
3125 SPOOL_NOTIFY_INFO_DATA *data,
3126 print_queue_struct *queue,
3127 NT_PRINTER_INFO_LEVEL *printer,
3128 TALLOC_CTX *mem_ctx)
3130 data->notify_data.value[0] = printer->info_2->starttime;
3131 data->notify_data.value[1] = 0;
3134 /*******************************************************************
3135 * fill a notify_info_data with the until time
3136 ********************************************************************/
3138 static void spoolss_notify_until_time(int snum,
3139 SPOOL_NOTIFY_INFO_DATA *data,
3140 print_queue_struct *queue,
3141 NT_PRINTER_INFO_LEVEL *printer,
3142 TALLOC_CTX *mem_ctx)
3144 data->notify_data.value[0] = printer->info_2->untiltime;
3145 data->notify_data.value[1] = 0;
3148 /*******************************************************************
3149 * fill a notify_info_data with the status
3150 ********************************************************************/
3152 static void spoolss_notify_status(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 print_status_struct status;
3160 print_queue_length(snum, &status);
3161 data->notify_data.value[0]=(uint32) status.status;
3162 data->notify_data.value[1] = 0;
3165 /*******************************************************************
3166 * fill a notify_info_data with the number of jobs queued
3167 ********************************************************************/
3169 void spoolss_notify_cjobs(int snum,
3170 SPOOL_NOTIFY_INFO_DATA *data,
3171 print_queue_struct *queue,
3172 NT_PRINTER_INFO_LEVEL *printer,
3173 TALLOC_CTX *mem_ctx)
3175 data->notify_data.value[0] = print_queue_length(snum, NULL);
3176 data->notify_data.value[1] = 0;
3179 /*******************************************************************
3180 * fill a notify_info_data with the average ppm
3181 ********************************************************************/
3183 static void spoolss_notify_average_ppm(int snum,
3184 SPOOL_NOTIFY_INFO_DATA *data,
3185 print_queue_struct *queue,
3186 NT_PRINTER_INFO_LEVEL *printer,
3187 TALLOC_CTX *mem_ctx)
3189 /* always respond 8 pages per minutes */
3190 /* a little hard ! */
3191 data->notify_data.value[0] = printer->info_2->averageppm;
3192 data->notify_data.value[1] = 0;
3195 /*******************************************************************
3196 * fill a notify_info_data with username
3197 ********************************************************************/
3199 static void spoolss_notify_username(int snum,
3200 SPOOL_NOTIFY_INFO_DATA *data,
3201 print_queue_struct *queue,
3202 NT_PRINTER_INFO_LEVEL *printer,
3203 TALLOC_CTX *mem_ctx)
3205 pstring temp;
3206 uint32 len;
3208 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3210 data->notify_data.data.length = len;
3211 if (len) {
3212 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3214 if (!data->notify_data.data.string) {
3215 data->notify_data.data.length = 0;
3216 return;
3219 memcpy(data->notify_data.data.string, temp, len);
3220 } else {
3221 data->notify_data.data.string = NULL;
3225 /*******************************************************************
3226 * fill a notify_info_data with job status
3227 ********************************************************************/
3229 static void spoolss_notify_job_status(int snum,
3230 SPOOL_NOTIFY_INFO_DATA *data,
3231 print_queue_struct *queue,
3232 NT_PRINTER_INFO_LEVEL *printer,
3233 TALLOC_CTX *mem_ctx)
3235 data->notify_data.value[0]=nt_printj_status(queue->status);
3236 data->notify_data.value[1] = 0;
3239 /*******************************************************************
3240 * fill a notify_info_data with job name
3241 ********************************************************************/
3243 static void spoolss_notify_job_name(int snum,
3244 SPOOL_NOTIFY_INFO_DATA *data,
3245 print_queue_struct *queue,
3246 NT_PRINTER_INFO_LEVEL *printer,
3247 TALLOC_CTX *mem_ctx)
3249 pstring temp;
3250 uint32 len;
3252 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3254 data->notify_data.data.length = len;
3255 if (len) {
3256 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3258 if (!data->notify_data.data.string) {
3259 data->notify_data.data.length = 0;
3260 return;
3263 memcpy(data->notify_data.data.string, temp, len);
3264 } else {
3265 data->notify_data.data.string = NULL;
3269 /*******************************************************************
3270 * fill a notify_info_data with job status
3271 ********************************************************************/
3273 static void spoolss_notify_job_status_string(int snum,
3274 SPOOL_NOTIFY_INFO_DATA *data,
3275 print_queue_struct *queue,
3276 NT_PRINTER_INFO_LEVEL *printer,
3277 TALLOC_CTX *mem_ctx)
3280 * Now we're returning job status codes we just return a "" here. JRA.
3283 const char *p = "";
3284 pstring temp;
3285 uint32 len;
3287 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3288 p = "unknown";
3290 switch (queue->status) {
3291 case LPQ_QUEUED:
3292 p = "Queued";
3293 break;
3294 case LPQ_PAUSED:
3295 p = ""; /* NT provides the paused string */
3296 break;
3297 case LPQ_SPOOLING:
3298 p = "Spooling";
3299 break;
3300 case LPQ_PRINTING:
3301 p = "Printing";
3302 break;
3304 #endif /* NO LONGER NEEDED. */
3306 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3308 data->notify_data.data.length = len;
3309 if (len) {
3310 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3312 if (!data->notify_data.data.string) {
3313 data->notify_data.data.length = 0;
3314 return;
3317 memcpy(data->notify_data.data.string, temp, len);
3318 } else {
3319 data->notify_data.data.string = NULL;
3323 /*******************************************************************
3324 * fill a notify_info_data with job time
3325 ********************************************************************/
3327 static void spoolss_notify_job_time(int snum,
3328 SPOOL_NOTIFY_INFO_DATA *data,
3329 print_queue_struct *queue,
3330 NT_PRINTER_INFO_LEVEL *printer,
3331 TALLOC_CTX *mem_ctx)
3333 data->notify_data.value[0]=0x0;
3334 data->notify_data.value[1]=0;
3337 /*******************************************************************
3338 * fill a notify_info_data with job size
3339 ********************************************************************/
3341 static void spoolss_notify_job_size(int snum,
3342 SPOOL_NOTIFY_INFO_DATA *data,
3343 print_queue_struct *queue,
3344 NT_PRINTER_INFO_LEVEL *printer,
3345 TALLOC_CTX *mem_ctx)
3347 data->notify_data.value[0]=queue->size;
3348 data->notify_data.value[1]=0;
3351 /*******************************************************************
3352 * fill a notify_info_data with page info
3353 ********************************************************************/
3354 static void spoolss_notify_total_pages(int snum,
3355 SPOOL_NOTIFY_INFO_DATA *data,
3356 print_queue_struct *queue,
3357 NT_PRINTER_INFO_LEVEL *printer,
3358 TALLOC_CTX *mem_ctx)
3360 data->notify_data.value[0]=queue->page_count;
3361 data->notify_data.value[1]=0;
3364 /*******************************************************************
3365 * fill a notify_info_data with pages printed info.
3366 ********************************************************************/
3367 static void spoolss_notify_pages_printed(int snum,
3368 SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer,
3371 TALLOC_CTX *mem_ctx)
3373 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3374 data->notify_data.value[1]=0;
3377 /*******************************************************************
3378 Fill a notify_info_data with job position.
3379 ********************************************************************/
3381 static void spoolss_notify_job_position(int snum,
3382 SPOOL_NOTIFY_INFO_DATA *data,
3383 print_queue_struct *queue,
3384 NT_PRINTER_INFO_LEVEL *printer,
3385 TALLOC_CTX *mem_ctx)
3387 data->notify_data.value[0]=queue->job;
3388 data->notify_data.value[1]=0;
3391 /*******************************************************************
3392 Fill a notify_info_data with submitted time.
3393 ********************************************************************/
3395 static void spoolss_notify_submitted_time(int snum,
3396 SPOOL_NOTIFY_INFO_DATA *data,
3397 print_queue_struct *queue,
3398 NT_PRINTER_INFO_LEVEL *printer,
3399 TALLOC_CTX *mem_ctx)
3401 struct tm *t;
3402 uint32 len;
3403 SYSTEMTIME st;
3404 char *p;
3406 t=gmtime(&queue->time);
3408 len = sizeof(SYSTEMTIME);
3410 data->notify_data.data.length = len;
3411 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3413 if (!data->notify_data.data.string) {
3414 data->notify_data.data.length = 0;
3415 return;
3418 make_systemtime(&st, t);
3421 * Systemtime must be linearized as a set of UINT16's.
3422 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3425 p = (char *)data->notify_data.data.string;
3426 SSVAL(p, 0, st.year);
3427 SSVAL(p, 2, st.month);
3428 SSVAL(p, 4, st.dayofweek);
3429 SSVAL(p, 6, st.day);
3430 SSVAL(p, 8, st.hour);
3431 SSVAL(p, 10, st.minute);
3432 SSVAL(p, 12, st.second);
3433 SSVAL(p, 14, st.milliseconds);
3436 struct s_notify_info_data_table
3438 uint16 type;
3439 uint16 field;
3440 const char *name;
3441 uint32 size;
3442 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3443 print_queue_struct *queue,
3444 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3447 /* A table describing the various print notification constants and
3448 whether the notification data is a pointer to a variable sized
3449 buffer, a one value uint32 or a two value uint32. */
3451 static const struct s_notify_info_data_table notify_info_data_table[] =
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3502 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3505 /*******************************************************************
3506 Return the size of info_data structure.
3507 ********************************************************************/
3509 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3511 int i=0;
3513 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3514 if ( (notify_info_data_table[i].type == type)
3515 && (notify_info_data_table[i].field == field) ) {
3516 switch(notify_info_data_table[i].size) {
3517 case NOTIFY_ONE_VALUE:
3518 case NOTIFY_TWO_VALUE:
3519 return 1;
3520 case NOTIFY_STRING:
3521 return 2;
3523 /* The only pointer notify data I have seen on
3524 the wire is the submitted time and this has
3525 the notify size set to 4. -tpot */
3527 case NOTIFY_POINTER:
3528 return 4;
3530 case NOTIFY_SECDESC:
3531 return 5;
3536 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3538 return 0;
3541 /*******************************************************************
3542 Return the type of notify_info_data.
3543 ********************************************************************/
3545 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3547 uint32 i=0;
3549 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3550 if (notify_info_data_table[i].type == type &&
3551 notify_info_data_table[i].field == field)
3552 return notify_info_data_table[i].size;
3555 return 0;
3558 /****************************************************************************
3559 ****************************************************************************/
3561 static BOOL search_notify(uint16 type, uint16 field, int *value)
3563 int i;
3565 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3566 if (notify_info_data_table[i].type == type &&
3567 notify_info_data_table[i].field == field &&
3568 notify_info_data_table[i].fn != NULL) {
3569 *value = i;
3570 return True;
3574 return False;
3577 /****************************************************************************
3578 ****************************************************************************/
3580 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3582 info_data->type = type;
3583 info_data->field = field;
3584 info_data->reserved = 0;
3586 info_data->size = size_of_notify_info_data(type, field);
3587 info_data->enc_type = type_of_notify_info_data(type, field);
3589 info_data->id = id;
3592 /*******************************************************************
3594 * fill a notify_info struct with info asked
3596 ********************************************************************/
3598 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3599 snum, SPOOL_NOTIFY_OPTION_TYPE
3600 *option_type, uint32 id,
3601 TALLOC_CTX *mem_ctx)
3603 int field_num,j;
3604 uint16 type;
3605 uint16 field;
3607 SPOOL_NOTIFY_INFO_DATA *current_data;
3608 NT_PRINTER_INFO_LEVEL *printer = NULL;
3609 print_queue_struct *queue=NULL;
3611 type=option_type->type;
3613 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3614 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3615 option_type->count, lp_servicename(snum)));
3617 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3618 return False;
3620 for(field_num=0; field_num<option_type->count; field_num++) {
3621 field = option_type->fields[field_num];
3623 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3625 if (!search_notify(type, field, &j) )
3626 continue;
3628 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3629 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3630 free_a_printer(&printer, 2);
3631 return False;
3634 current_data = &info->data[info->count];
3636 construct_info_data(current_data, type, field, id);
3638 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3639 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3641 notify_info_data_table[j].fn(snum, current_data, queue,
3642 printer, mem_ctx);
3644 info->count++;
3647 free_a_printer(&printer, 2);
3648 return True;
3651 /*******************************************************************
3653 * fill a notify_info struct with info asked
3655 ********************************************************************/
3657 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3658 SPOOL_NOTIFY_INFO *info,
3659 NT_PRINTER_INFO_LEVEL *printer,
3660 int snum, SPOOL_NOTIFY_OPTION_TYPE
3661 *option_type, uint32 id,
3662 TALLOC_CTX *mem_ctx)
3664 int field_num,j;
3665 uint16 type;
3666 uint16 field;
3668 SPOOL_NOTIFY_INFO_DATA *current_data;
3670 DEBUG(4,("construct_notify_jobs_info\n"));
3672 type = option_type->type;
3674 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3675 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3676 option_type->count));
3678 for(field_num=0; field_num<option_type->count; field_num++) {
3679 field = option_type->fields[field_num];
3681 if (!search_notify(type, field, &j) )
3682 continue;
3684 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3685 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3686 return False;
3689 current_data=&(info->data[info->count]);
3691 construct_info_data(current_data, type, field, id);
3692 notify_info_data_table[j].fn(snum, current_data, queue,
3693 printer, mem_ctx);
3694 info->count++;
3697 return True;
3701 * JFM: The enumeration is not that simple, it's even non obvious.
3703 * let's take an example: I want to monitor the PRINTER SERVER for
3704 * the printer's name and the number of jobs currently queued.
3705 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3706 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3708 * I have 3 printers on the back of my server.
3710 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3711 * structures.
3712 * Number Data Id
3713 * 1 printer 1 name 1
3714 * 2 printer 1 cjob 1
3715 * 3 printer 2 name 2
3716 * 4 printer 2 cjob 2
3717 * 5 printer 3 name 3
3718 * 6 printer 3 name 3
3720 * that's the print server case, the printer case is even worse.
3723 /*******************************************************************
3725 * enumerate all printers on the printserver
3726 * fill a notify_info struct with info asked
3728 ********************************************************************/
3730 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3731 SPOOL_NOTIFY_INFO *info,
3732 TALLOC_CTX *mem_ctx)
3734 int snum;
3735 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3736 int n_services=lp_numservices();
3737 int i;
3738 SPOOL_NOTIFY_OPTION *option;
3739 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3741 DEBUG(4,("printserver_notify_info\n"));
3743 if (!Printer)
3744 return WERR_BADFID;
3746 option=Printer->notify.option;
3747 info->version=2;
3748 info->data=NULL;
3749 info->count=0;
3751 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3752 sending a ffpcn() request first */
3754 if ( !option )
3755 return WERR_BADFID;
3757 for (i=0; i<option->count; i++) {
3758 option_type=&(option->ctr.type[i]);
3760 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3761 continue;
3763 for (snum=0; snum<n_services; snum++)
3765 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3766 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3770 #if 0
3772 * Debugging information, don't delete.
3775 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3776 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3777 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3779 for (i=0; i<info->count; i++) {
3780 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3781 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3782 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3784 #endif
3786 return WERR_OK;
3789 /*******************************************************************
3791 * fill a notify_info struct with info asked
3793 ********************************************************************/
3795 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3796 TALLOC_CTX *mem_ctx)
3798 int snum;
3799 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3800 int i;
3801 uint32 id;
3802 SPOOL_NOTIFY_OPTION *option;
3803 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3804 int count,j;
3805 print_queue_struct *queue=NULL;
3806 print_status_struct status;
3808 DEBUG(4,("printer_notify_info\n"));
3810 if (!Printer)
3811 return WERR_BADFID;
3813 option=Printer->notify.option;
3814 id = 0x0;
3815 info->version=2;
3816 info->data=NULL;
3817 info->count=0;
3819 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3820 sending a ffpcn() request first */
3822 if ( !option )
3823 return WERR_BADFID;
3825 get_printer_snum(p, hnd, &snum);
3827 for (i=0; i<option->count; i++) {
3828 option_type=&option->ctr.type[i];
3830 switch ( option_type->type ) {
3831 case PRINTER_NOTIFY_TYPE:
3832 if(construct_notify_printer_info(Printer, info, snum,
3833 option_type, id,
3834 mem_ctx))
3835 id--;
3836 break;
3838 case JOB_NOTIFY_TYPE: {
3839 NT_PRINTER_INFO_LEVEL *printer = NULL;
3841 count = print_queue_status(snum, &queue, &status);
3843 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3844 goto done;
3846 for (j=0; j<count; j++) {
3847 construct_notify_jobs_info(&queue[j], info,
3848 printer, snum,
3849 option_type,
3850 queue[j].job,
3851 mem_ctx);
3854 free_a_printer(&printer, 2);
3856 done:
3857 SAFE_FREE(queue);
3858 break;
3864 * Debugging information, don't delete.
3867 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3868 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3869 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3871 for (i=0; i<info->count; i++) {
3872 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3873 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3874 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3877 return WERR_OK;
3880 /********************************************************************
3881 * spoolss_rfnpcnex
3882 ********************************************************************/
3884 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3886 POLICY_HND *handle = &q_u->handle;
3887 SPOOL_NOTIFY_INFO *info = &r_u->info;
3889 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3890 WERROR result = WERR_BADFID;
3892 /* we always have a NOTIFY_INFO struct */
3893 r_u->info_ptr=0x1;
3895 if (!Printer) {
3896 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3897 OUR_HANDLE(handle)));
3898 goto done;
3901 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3904 * We are now using the change value, and
3905 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3906 * I don't have a global notification system, I'm sending back all the
3907 * informations even when _NOTHING_ has changed.
3910 /* We need to keep track of the change value to send back in
3911 RRPCN replies otherwise our updates are ignored. */
3913 Printer->notify.fnpcn = True;
3915 if (Printer->notify.client_connected) {
3916 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3917 Printer->notify.change = q_u->change;
3920 /* just ignore the SPOOL_NOTIFY_OPTION */
3922 switch (Printer->printer_type) {
3923 case SPLHND_SERVER:
3924 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3925 break;
3927 case SPLHND_PRINTER:
3928 result = printer_notify_info(p, handle, info, p->mem_ctx);
3929 break;
3932 Printer->notify.fnpcn = False;
3934 done:
3935 return result;
3938 /********************************************************************
3939 * construct_printer_info_0
3940 * fill a printer_info_0 struct
3941 ********************************************************************/
3943 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3945 pstring chaine;
3946 int count;
3947 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3948 counter_printer_0 *session_counter;
3949 uint32 global_counter;
3950 struct tm *t;
3951 time_t setuptime;
3952 print_status_struct status;
3954 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3955 return False;
3957 count = print_queue_length(snum, &status);
3959 /* check if we already have a counter for this printer */
3960 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3961 if (session_counter->snum == snum)
3962 break;
3965 /* it's the first time, add it to the list */
3966 if (session_counter==NULL) {
3967 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3968 free_a_printer(&ntprinter, 2);
3969 return False;
3971 ZERO_STRUCTP(session_counter);
3972 session_counter->snum=snum;
3973 session_counter->counter=0;
3974 DLIST_ADD(counter_list, session_counter);
3977 /* increment it */
3978 session_counter->counter++;
3980 /* JFM:
3981 * the global_counter should be stored in a TDB as it's common to all the clients
3982 * and should be zeroed on samba startup
3984 global_counter=session_counter->counter;
3986 pstrcpy(chaine,ntprinter->info_2->printername);
3988 init_unistr(&printer->printername, chaine);
3990 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3991 init_unistr(&printer->servername, chaine);
3993 printer->cjobs = count;
3994 printer->total_jobs = 0;
3995 printer->total_bytes = 0;
3997 setuptime = (time_t)ntprinter->info_2->setuptime;
3998 t=gmtime(&setuptime);
4000 printer->year = t->tm_year+1900;
4001 printer->month = t->tm_mon+1;
4002 printer->dayofweek = t->tm_wday;
4003 printer->day = t->tm_mday;
4004 printer->hour = t->tm_hour;
4005 printer->minute = t->tm_min;
4006 printer->second = t->tm_sec;
4007 printer->milliseconds = 0;
4009 printer->global_counter = global_counter;
4010 printer->total_pages = 0;
4012 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4013 printer->major_version = 0x0005; /* NT 5 */
4014 printer->build_version = 0x0893; /* build 2195 */
4016 printer->unknown7 = 0x1;
4017 printer->unknown8 = 0x0;
4018 printer->unknown9 = 0x0;
4019 printer->session_counter = session_counter->counter;
4020 printer->unknown11 = 0x0;
4021 printer->printer_errors = 0x0; /* number of print failure */
4022 printer->unknown13 = 0x0;
4023 printer->unknown14 = 0x1;
4024 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4025 printer->unknown16 = 0x0;
4026 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4027 printer->unknown18 = 0x0;
4028 printer->status = nt_printq_status(status.status);
4029 printer->unknown20 = 0x0;
4030 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4031 printer->unknown22 = 0x0;
4032 printer->unknown23 = 0x6; /* 6 ???*/
4033 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4034 printer->unknown25 = 0;
4035 printer->unknown26 = 0;
4036 printer->unknown27 = 0;
4037 printer->unknown28 = 0;
4038 printer->unknown29 = 0;
4040 free_a_printer(&ntprinter,2);
4041 return (True);
4044 /********************************************************************
4045 * construct_printer_info_1
4046 * fill a printer_info_1 struct
4047 ********************************************************************/
4048 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4050 pstring chaine;
4051 pstring chaine2;
4052 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4054 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4055 return False;
4057 printer->flags=flags;
4059 if (*ntprinter->info_2->comment == '\0') {
4060 init_unistr(&printer->comment, lp_comment(snum));
4061 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4062 ntprinter->info_2->drivername, lp_comment(snum));
4064 else {
4065 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4066 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4067 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4070 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4072 init_unistr(&printer->description, chaine);
4073 init_unistr(&printer->name, chaine2);
4075 free_a_printer(&ntprinter,2);
4077 return True;
4080 /****************************************************************************
4081 Free a DEVMODE struct.
4082 ****************************************************************************/
4084 static void free_dev_mode(DEVICEMODE *dev)
4086 if (dev == NULL)
4087 return;
4089 SAFE_FREE(dev->dev_private);
4090 SAFE_FREE(dev);
4094 /****************************************************************************
4095 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4096 should be valid upon entry
4097 ****************************************************************************/
4099 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4101 if ( !devmode || !ntdevmode )
4102 return False;
4104 init_unistr(&devmode->devicename, ntdevmode->devicename);
4106 init_unistr(&devmode->formname, ntdevmode->formname);
4108 devmode->specversion = ntdevmode->specversion;
4109 devmode->driverversion = ntdevmode->driverversion;
4110 devmode->size = ntdevmode->size;
4111 devmode->driverextra = ntdevmode->driverextra;
4112 devmode->fields = ntdevmode->fields;
4114 devmode->orientation = ntdevmode->orientation;
4115 devmode->papersize = ntdevmode->papersize;
4116 devmode->paperlength = ntdevmode->paperlength;
4117 devmode->paperwidth = ntdevmode->paperwidth;
4118 devmode->scale = ntdevmode->scale;
4119 devmode->copies = ntdevmode->copies;
4120 devmode->defaultsource = ntdevmode->defaultsource;
4121 devmode->printquality = ntdevmode->printquality;
4122 devmode->color = ntdevmode->color;
4123 devmode->duplex = ntdevmode->duplex;
4124 devmode->yresolution = ntdevmode->yresolution;
4125 devmode->ttoption = ntdevmode->ttoption;
4126 devmode->collate = ntdevmode->collate;
4127 devmode->icmmethod = ntdevmode->icmmethod;
4128 devmode->icmintent = ntdevmode->icmintent;
4129 devmode->mediatype = ntdevmode->mediatype;
4130 devmode->dithertype = ntdevmode->dithertype;
4132 if (ntdevmode->nt_dev_private != NULL) {
4133 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4134 return False;
4137 return True;
4140 /****************************************************************************
4141 Create a DEVMODE struct. Returns malloced memory.
4142 ****************************************************************************/
4144 DEVICEMODE *construct_dev_mode(const char *servicename)
4146 NT_PRINTER_INFO_LEVEL *printer = NULL;
4147 DEVICEMODE *devmode = NULL;
4149 DEBUG(7,("construct_dev_mode\n"));
4151 DEBUGADD(8,("getting printer characteristics\n"));
4153 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4154 return NULL;
4156 if ( !printer->info_2->devmode ) {
4157 DEBUG(5, ("BONG! There was no device mode!\n"));
4158 goto done;
4161 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4162 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4163 goto done;
4166 ZERO_STRUCTP(devmode);
4168 DEBUGADD(8,("loading DEVICEMODE\n"));
4170 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4171 free_dev_mode( devmode );
4172 devmode = NULL;
4175 done:
4176 free_a_printer(&printer,2);
4178 return devmode;
4181 /********************************************************************
4182 * construct_printer_info_2
4183 * fill a printer_info_2 struct
4184 ********************************************************************/
4186 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4188 int count;
4189 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4191 print_status_struct status;
4193 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4194 return False;
4196 count = print_queue_length(snum, &status);
4198 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4199 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4200 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4201 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4202 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4204 if (*ntprinter->info_2->comment == '\0')
4205 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4206 else
4207 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4209 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4210 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4211 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4212 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4213 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4215 printer->attributes = ntprinter->info_2->attributes;
4217 printer->priority = ntprinter->info_2->priority; /* priority */
4218 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4219 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4220 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4221 printer->status = nt_printq_status(status.status); /* status */
4222 printer->cjobs = count; /* jobs */
4223 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4225 if ( !(printer->devmode = construct_dev_mode(
4226 lp_const_servicename(snum))) )
4227 DEBUG(8, ("Returning NULL Devicemode!\n"));
4229 printer->secdesc = NULL;
4231 if ( ntprinter->info_2->secdesc_buf
4232 && ntprinter->info_2->secdesc_buf->len != 0 )
4234 /* don't use talloc_steal() here unless you do a deep steal of all
4235 the SEC_DESC members */
4237 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4238 ntprinter->info_2->secdesc_buf->sec );
4241 free_a_printer(&ntprinter, 2);
4243 return True;
4246 /********************************************************************
4247 * construct_printer_info_3
4248 * fill a printer_info_3 struct
4249 ********************************************************************/
4251 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4253 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4254 PRINTER_INFO_3 *printer = NULL;
4256 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4257 return False;
4259 *pp_printer = NULL;
4260 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4261 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4262 free_a_printer(&ntprinter, 2);
4263 return False;
4266 ZERO_STRUCTP(printer);
4268 /* These are the components of the SD we are returning. */
4270 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4271 /* don't use talloc_steal() here unless you do a deep steal of all
4272 the SEC_DESC members */
4274 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4275 ntprinter->info_2->secdesc_buf->sec );
4278 free_a_printer(&ntprinter, 2);
4280 *pp_printer = printer;
4281 return True;
4284 /********************************************************************
4285 * construct_printer_info_4
4286 * fill a printer_info_4 struct
4287 ********************************************************************/
4289 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4291 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4293 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4294 return False;
4296 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4297 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4298 printer->attributes = ntprinter->info_2->attributes;
4300 free_a_printer(&ntprinter, 2);
4301 return True;
4304 /********************************************************************
4305 * construct_printer_info_5
4306 * fill a printer_info_5 struct
4307 ********************************************************************/
4309 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4311 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4313 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4314 return False;
4316 init_unistr(&printer->printername, ntprinter->info_2->printername);
4317 init_unistr(&printer->portname, ntprinter->info_2->portname);
4318 printer->attributes = ntprinter->info_2->attributes;
4320 /* these two are not used by NT+ according to MSDN */
4322 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4323 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4325 free_a_printer(&ntprinter, 2);
4327 return True;
4330 /********************************************************************
4331 * construct_printer_info_7
4332 * fill a printer_info_7 struct
4333 ********************************************************************/
4335 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4337 char *guid_str = NULL;
4338 struct GUID guid;
4340 if (is_printer_published(print_hnd, snum, &guid)) {
4341 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4342 strupper_m(guid_str);
4343 init_unistr(&printer->guid, guid_str);
4344 printer->action = SPOOL_DS_PUBLISH;
4345 } else {
4346 init_unistr(&printer->guid, "");
4347 printer->action = SPOOL_DS_UNPUBLISH;
4350 return True;
4353 /********************************************************************
4354 Spoolss_enumprinters.
4355 ********************************************************************/
4357 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4359 int snum;
4360 int i;
4361 int n_services=lp_numservices();
4362 PRINTER_INFO_1 *printers=NULL;
4363 PRINTER_INFO_1 current_prt;
4364 WERROR result = WERR_OK;
4366 DEBUG(4,("enum_all_printers_info_1\n"));
4368 for (snum=0; snum<n_services; snum++) {
4369 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4370 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4372 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4373 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4374 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4375 *returned=0;
4376 return WERR_NOMEM;
4378 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4380 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4381 (*returned)++;
4386 /* check the required size. */
4387 for (i=0; i<*returned; i++)
4388 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4390 if (*needed > offered) {
4391 result = WERR_INSUFFICIENT_BUFFER;
4392 goto out;
4395 if (!rpcbuf_alloc_size(buffer, *needed)) {
4396 result = WERR_NOMEM;
4397 goto out;
4400 /* fill the buffer with the structures */
4401 for (i=0; i<*returned; i++)
4402 smb_io_printer_info_1("", buffer, &printers[i], 0);
4404 out:
4405 /* clear memory */
4407 SAFE_FREE(printers);
4409 if ( !W_ERROR_IS_OK(result) )
4410 *returned = 0;
4412 return result;
4415 /********************************************************************
4416 enum_all_printers_info_1_local.
4417 *********************************************************************/
4419 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4421 DEBUG(4,("enum_all_printers_info_1_local\n"));
4423 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4426 /********************************************************************
4427 enum_all_printers_info_1_name.
4428 *********************************************************************/
4430 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4432 char *s = name;
4434 DEBUG(4,("enum_all_printers_info_1_name\n"));
4436 if ((name[0] == '\\') && (name[1] == '\\'))
4437 s = name + 2;
4439 if (is_myname_or_ipaddr(s)) {
4440 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4442 else
4443 return WERR_INVALID_NAME;
4446 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4447 /********************************************************************
4448 enum_all_printers_info_1_remote.
4449 *********************************************************************/
4451 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4453 PRINTER_INFO_1 *printer;
4454 fstring printername;
4455 fstring desc;
4456 fstring comment;
4457 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4458 WERROR result = WERR_OK;
4460 /* JFM: currently it's more a place holder than anything else.
4461 * In the spooler world there is a notion of server registration.
4462 * the print servers are registered on the PDC (in the same domain)
4464 * We should have a TDB here. The registration is done thru an
4465 * undocumented RPC call.
4468 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4469 return WERR_NOMEM;
4471 *returned=1;
4473 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4474 slprintf(desc, sizeof(desc)-1,"%s", name);
4475 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4477 init_unistr(&printer->description, desc);
4478 init_unistr(&printer->name, printername);
4479 init_unistr(&printer->comment, comment);
4480 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4482 /* check the required size. */
4483 *needed += spoolss_size_printer_info_1(printer);
4485 if (*needed > offered) {
4486 result = WERR_INSUFFICIENT_BUFFER;
4487 goto out;
4490 if (!rpcbuf_alloc_size(buffer, *needed)) {
4491 result = WERR_NOMEM;
4492 goto out;
4495 /* fill the buffer with the structures */
4496 smb_io_printer_info_1("", buffer, printer, 0);
4498 out:
4499 /* clear memory */
4500 SAFE_FREE(printer);
4502 if ( !W_ERROR_IS_OK(result) )
4503 *returned = 0;
4505 return result;
4508 #endif
4510 /********************************************************************
4511 enum_all_printers_info_1_network.
4512 *********************************************************************/
4514 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4516 char *s = name;
4518 DEBUG(4,("enum_all_printers_info_1_network\n"));
4520 /* If we respond to a enum_printers level 1 on our name with flags
4521 set to PRINTER_ENUM_REMOTE with a list of printers then these
4522 printers incorrectly appear in the APW browse list.
4523 Specifically the printers for the server appear at the workgroup
4524 level where all the other servers in the domain are
4525 listed. Windows responds to this call with a
4526 WERR_CAN_NOT_COMPLETE so we should do the same. */
4528 if (name[0] == '\\' && name[1] == '\\')
4529 s = name + 2;
4531 if (is_myname_or_ipaddr(s))
4532 return WERR_CAN_NOT_COMPLETE;
4534 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4537 /********************************************************************
4538 * api_spoolss_enumprinters
4540 * called from api_spoolss_enumprinters (see this to understand)
4541 ********************************************************************/
4543 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4545 int snum;
4546 int i;
4547 int n_services=lp_numservices();
4548 PRINTER_INFO_2 *printers=NULL;
4549 PRINTER_INFO_2 current_prt;
4550 WERROR result = WERR_OK;
4552 *returned = 0;
4554 for (snum=0; snum<n_services; snum++) {
4555 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4556 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4558 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4559 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4560 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4561 *returned = 0;
4562 return WERR_NOMEM;
4565 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4567 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4569 (*returned)++;
4574 /* check the required size. */
4575 for (i=0; i<*returned; i++)
4576 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4578 if (*needed > offered) {
4579 result = WERR_INSUFFICIENT_BUFFER;
4580 goto out;
4583 if (!rpcbuf_alloc_size(buffer, *needed)) {
4584 result = WERR_NOMEM;
4585 goto out;
4588 /* fill the buffer with the structures */
4589 for (i=0; i<*returned; i++)
4590 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4592 out:
4593 /* clear memory */
4595 for (i=0; i<*returned; i++)
4596 free_devmode(printers[i].devmode);
4598 SAFE_FREE(printers);
4600 if ( !W_ERROR_IS_OK(result) )
4601 *returned = 0;
4603 return result;
4606 /********************************************************************
4607 * handle enumeration of printers at level 1
4608 ********************************************************************/
4610 static WERROR enumprinters_level1( uint32 flags, fstring name,
4611 RPC_BUFFER *buffer, uint32 offered,
4612 uint32 *needed, uint32 *returned)
4614 /* Not all the flags are equals */
4616 if (flags & PRINTER_ENUM_LOCAL)
4617 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4619 if (flags & PRINTER_ENUM_NAME)
4620 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4622 #if 0 /* JERRY - disabled for now */
4623 if (flags & PRINTER_ENUM_REMOTE)
4624 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4625 #endif
4627 if (flags & PRINTER_ENUM_NETWORK)
4628 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4630 return WERR_OK; /* NT4sp5 does that */
4633 /********************************************************************
4634 * handle enumeration of printers at level 2
4635 ********************************************************************/
4637 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4638 RPC_BUFFER *buffer, uint32 offered,
4639 uint32 *needed, uint32 *returned)
4641 char *s = servername;
4643 if (flags & PRINTER_ENUM_LOCAL) {
4644 return enum_all_printers_info_2(buffer, offered, needed, returned);
4647 if (flags & PRINTER_ENUM_NAME) {
4648 if ((servername[0] == '\\') && (servername[1] == '\\'))
4649 s = servername + 2;
4650 if (is_myname_or_ipaddr(s))
4651 return enum_all_printers_info_2(buffer, offered, needed, returned);
4652 else
4653 return WERR_INVALID_NAME;
4656 if (flags & PRINTER_ENUM_REMOTE)
4657 return WERR_UNKNOWN_LEVEL;
4659 return WERR_OK;
4662 /********************************************************************
4663 * handle enumeration of printers at level 5
4664 ********************************************************************/
4666 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4667 RPC_BUFFER *buffer, uint32 offered,
4668 uint32 *needed, uint32 *returned)
4670 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4671 return WERR_OK;
4674 /********************************************************************
4675 * api_spoolss_enumprinters
4677 * called from api_spoolss_enumprinters (see this to understand)
4678 ********************************************************************/
4680 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4682 uint32 flags = q_u->flags;
4683 UNISTR2 *servername = &q_u->servername;
4684 uint32 level = q_u->level;
4685 RPC_BUFFER *buffer = NULL;
4686 uint32 offered = q_u->offered;
4687 uint32 *needed = &r_u->needed;
4688 uint32 *returned = &r_u->returned;
4690 fstring name;
4692 /* that's an [in out] buffer */
4694 if (!q_u->buffer && (offered!=0)) {
4695 return WERR_INVALID_PARAM;
4698 rpcbuf_move(q_u->buffer, &r_u->buffer);
4699 buffer = r_u->buffer;
4701 DEBUG(4,("_spoolss_enumprinters\n"));
4703 *needed=0;
4704 *returned=0;
4707 * Level 1:
4708 * flags==PRINTER_ENUM_NAME
4709 * if name=="" then enumerates all printers
4710 * if name!="" then enumerate the printer
4711 * flags==PRINTER_ENUM_REMOTE
4712 * name is NULL, enumerate printers
4713 * Level 2: name!="" enumerates printers, name can't be NULL
4714 * Level 3: doesn't exist
4715 * Level 4: does a local registry lookup
4716 * Level 5: same as Level 2
4719 unistr2_to_ascii(name, servername, sizeof(name)-1);
4720 strupper_m(name);
4722 switch (level) {
4723 case 1:
4724 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4725 case 2:
4726 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4727 case 5:
4728 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4729 case 3:
4730 case 4:
4731 break;
4733 return WERR_UNKNOWN_LEVEL;
4736 /****************************************************************************
4737 ****************************************************************************/
4739 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4741 PRINTER_INFO_0 *printer=NULL;
4742 WERROR result = WERR_OK;
4744 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4745 return WERR_NOMEM;
4747 construct_printer_info_0(print_hnd, printer, snum);
4749 /* check the required size. */
4750 *needed += spoolss_size_printer_info_0(printer);
4752 if (*needed > offered) {
4753 result = WERR_INSUFFICIENT_BUFFER;
4754 goto out;
4757 if (!rpcbuf_alloc_size(buffer, *needed)) {
4758 result = WERR_NOMEM;
4759 goto out;
4762 /* fill the buffer with the structures */
4763 smb_io_printer_info_0("", buffer, printer, 0);
4765 out:
4766 /* clear memory */
4768 SAFE_FREE(printer);
4770 return result;
4773 /****************************************************************************
4774 ****************************************************************************/
4776 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4778 PRINTER_INFO_1 *printer=NULL;
4779 WERROR result = WERR_OK;
4781 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4782 return WERR_NOMEM;
4784 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4786 /* check the required size. */
4787 *needed += spoolss_size_printer_info_1(printer);
4789 if (*needed > offered) {
4790 result = WERR_INSUFFICIENT_BUFFER;
4791 goto out;
4794 if (!rpcbuf_alloc_size(buffer, *needed)) {
4795 result = WERR_NOMEM;
4796 goto out;
4799 /* fill the buffer with the structures */
4800 smb_io_printer_info_1("", buffer, printer, 0);
4802 out:
4803 /* clear memory */
4804 SAFE_FREE(printer);
4806 return result;
4809 /****************************************************************************
4810 ****************************************************************************/
4812 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4814 PRINTER_INFO_2 *printer=NULL;
4815 WERROR result = WERR_OK;
4817 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4818 return WERR_NOMEM;
4820 construct_printer_info_2(print_hnd, printer, snum);
4822 /* check the required size. */
4823 *needed += spoolss_size_printer_info_2(printer);
4825 if (*needed > offered) {
4826 result = WERR_INSUFFICIENT_BUFFER;
4827 goto out;
4830 if (!rpcbuf_alloc_size(buffer, *needed)) {
4831 result = WERR_NOMEM;
4832 goto out;
4835 /* fill the buffer with the structures */
4836 if (!smb_io_printer_info_2("", buffer, printer, 0))
4837 result = WERR_NOMEM;
4839 out:
4840 /* clear memory */
4841 free_printer_info_2(printer);
4843 return result;
4846 /****************************************************************************
4847 ****************************************************************************/
4849 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4851 PRINTER_INFO_3 *printer=NULL;
4852 WERROR result = WERR_OK;
4854 if (!construct_printer_info_3(print_hnd, &printer, snum))
4855 return WERR_NOMEM;
4857 /* check the required size. */
4858 *needed += spoolss_size_printer_info_3(printer);
4860 if (*needed > offered) {
4861 result = WERR_INSUFFICIENT_BUFFER;
4862 goto out;
4865 if (!rpcbuf_alloc_size(buffer, *needed)) {
4866 result = WERR_NOMEM;
4867 goto out;
4870 /* fill the buffer with the structures */
4871 smb_io_printer_info_3("", buffer, printer, 0);
4873 out:
4874 /* clear memory */
4875 free_printer_info_3(printer);
4877 return result;
4880 /****************************************************************************
4881 ****************************************************************************/
4883 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4885 PRINTER_INFO_4 *printer=NULL;
4886 WERROR result = WERR_OK;
4888 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4889 return WERR_NOMEM;
4891 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4892 SAFE_FREE(printer);
4893 return WERR_NOMEM;
4896 /* check the required size. */
4897 *needed += spoolss_size_printer_info_4(printer);
4899 if (*needed > offered) {
4900 result = WERR_INSUFFICIENT_BUFFER;
4901 goto out;
4904 if (!rpcbuf_alloc_size(buffer, *needed)) {
4905 result = WERR_NOMEM;
4906 goto out;
4909 /* fill the buffer with the structures */
4910 smb_io_printer_info_4("", buffer, printer, 0);
4912 out:
4913 /* clear memory */
4914 free_printer_info_4(printer);
4916 return result;
4919 /****************************************************************************
4920 ****************************************************************************/
4922 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4924 PRINTER_INFO_5 *printer=NULL;
4925 WERROR result = WERR_OK;
4927 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4928 return WERR_NOMEM;
4930 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4931 free_printer_info_5(printer);
4932 return WERR_NOMEM;
4935 /* check the required size. */
4936 *needed += spoolss_size_printer_info_5(printer);
4938 if (*needed > offered) {
4939 result = WERR_INSUFFICIENT_BUFFER;
4940 goto out;
4943 if (!rpcbuf_alloc_size(buffer, *needed)) {
4944 result = WERR_NOMEM;
4945 goto out;
4948 /* fill the buffer with the structures */
4949 smb_io_printer_info_5("", buffer, printer, 0);
4951 out:
4952 /* clear memory */
4953 free_printer_info_5(printer);
4955 return result;
4958 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4960 PRINTER_INFO_7 *printer=NULL;
4961 WERROR result = WERR_OK;
4963 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4964 return WERR_NOMEM;
4966 if (!construct_printer_info_7(print_hnd, printer, snum))
4967 return WERR_NOMEM;
4969 /* check the required size. */
4970 *needed += spoolss_size_printer_info_7(printer);
4972 if (*needed > offered) {
4973 result = WERR_INSUFFICIENT_BUFFER;
4974 goto out;
4977 if (!rpcbuf_alloc_size(buffer, *needed)) {
4978 result = WERR_NOMEM;
4979 goto out;
4983 /* fill the buffer with the structures */
4984 smb_io_printer_info_7("", buffer, printer, 0);
4986 out:
4987 /* clear memory */
4988 free_printer_info_7(printer);
4990 return result;
4993 /****************************************************************************
4994 ****************************************************************************/
4996 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4998 POLICY_HND *handle = &q_u->handle;
4999 uint32 level = q_u->level;
5000 RPC_BUFFER *buffer = NULL;
5001 uint32 offered = q_u->offered;
5002 uint32 *needed = &r_u->needed;
5003 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5005 int snum;
5007 /* that's an [in out] buffer */
5009 if (!q_u->buffer && (offered!=0)) {
5010 return WERR_INVALID_PARAM;
5013 rpcbuf_move(q_u->buffer, &r_u->buffer);
5014 buffer = r_u->buffer;
5016 *needed=0;
5018 if (!get_printer_snum(p, handle, &snum))
5019 return WERR_BADFID;
5021 switch (level) {
5022 case 0:
5023 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5024 case 1:
5025 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5026 case 2:
5027 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5028 case 3:
5029 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5030 case 4:
5031 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5032 case 5:
5033 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5034 case 7:
5035 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5037 return WERR_UNKNOWN_LEVEL;
5040 /********************************************************************
5041 * fill a DRIVER_INFO_1 struct
5042 ********************************************************************/
5044 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5046 init_unistr( &info->name, driver.info_3->name);
5049 /********************************************************************
5050 * construct_printer_driver_info_1
5051 ********************************************************************/
5053 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5055 NT_PRINTER_INFO_LEVEL *printer = NULL;
5056 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5058 ZERO_STRUCT(driver);
5060 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5061 return WERR_INVALID_PRINTER_NAME;
5063 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5064 free_a_printer(&printer, 2);
5065 return WERR_UNKNOWN_PRINTER_DRIVER;
5068 fill_printer_driver_info_1(info, driver, servername, architecture);
5070 free_a_printer(&printer,2);
5072 return WERR_OK;
5075 /********************************************************************
5076 * construct_printer_driver_info_2
5077 * fill a printer_info_2 struct
5078 ********************************************************************/
5080 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5082 pstring temp;
5084 info->version=driver.info_3->cversion;
5086 init_unistr( &info->name, driver.info_3->name );
5087 init_unistr( &info->architecture, driver.info_3->environment );
5090 if (strlen(driver.info_3->driverpath)) {
5091 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5092 init_unistr( &info->driverpath, temp );
5093 } else
5094 init_unistr( &info->driverpath, "" );
5096 if (strlen(driver.info_3->datafile)) {
5097 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5098 init_unistr( &info->datafile, temp );
5099 } else
5100 init_unistr( &info->datafile, "" );
5102 if (strlen(driver.info_3->configfile)) {
5103 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5104 init_unistr( &info->configfile, temp );
5105 } else
5106 init_unistr( &info->configfile, "" );
5109 /********************************************************************
5110 * construct_printer_driver_info_2
5111 * fill a printer_info_2 struct
5112 ********************************************************************/
5114 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5116 NT_PRINTER_INFO_LEVEL *printer = NULL;
5117 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5119 ZERO_STRUCT(printer);
5120 ZERO_STRUCT(driver);
5122 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5123 return WERR_INVALID_PRINTER_NAME;
5125 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5126 free_a_printer(&printer, 2);
5127 return WERR_UNKNOWN_PRINTER_DRIVER;
5130 fill_printer_driver_info_2(info, driver, servername);
5132 free_a_printer(&printer,2);
5134 return WERR_OK;
5137 /********************************************************************
5138 * copy a strings array and convert to UNICODE
5140 * convert an array of ascii string to a UNICODE string
5141 ********************************************************************/
5143 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5145 int i=0;
5146 int j=0;
5147 const char *v;
5148 pstring line;
5150 DEBUG(6,("init_unistr_array\n"));
5151 *uni_array=NULL;
5153 while (True)
5155 if ( !char_array )
5156 v = "";
5157 else
5159 v = char_array[i];
5160 if (!v)
5161 v = ""; /* hack to handle null lists */
5164 /* hack to allow this to be used in places other than when generating
5165 the list of dependent files */
5167 if ( servername )
5168 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5169 else
5170 pstrcpy( line, v );
5172 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5174 /* add one extra unit16 for the second terminating NULL */
5176 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5177 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5178 return 0;
5181 if ( !strlen(v) )
5182 break;
5184 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5185 i++;
5188 if (*uni_array) {
5189 /* special case for ""; we need to add both NULL's here */
5190 if (!j)
5191 (*uni_array)[j++]=0x0000;
5192 (*uni_array)[j]=0x0000;
5195 DEBUGADD(6,("last one:done\n"));
5197 /* return size of array in uint16's */
5199 return j+1;
5202 /********************************************************************
5203 * construct_printer_info_3
5204 * fill a printer_info_3 struct
5205 ********************************************************************/
5207 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5209 pstring temp;
5211 ZERO_STRUCTP(info);
5213 info->version=driver.info_3->cversion;
5215 init_unistr( &info->name, driver.info_3->name );
5216 init_unistr( &info->architecture, driver.info_3->environment );
5218 if (strlen(driver.info_3->driverpath)) {
5219 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5220 init_unistr( &info->driverpath, temp );
5221 } else
5222 init_unistr( &info->driverpath, "" );
5224 if (strlen(driver.info_3->datafile)) {
5225 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5226 init_unistr( &info->datafile, temp );
5227 } else
5228 init_unistr( &info->datafile, "" );
5230 if (strlen(driver.info_3->configfile)) {
5231 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5232 init_unistr( &info->configfile, temp );
5233 } else
5234 init_unistr( &info->configfile, "" );
5236 if (strlen(driver.info_3->helpfile)) {
5237 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5238 init_unistr( &info->helpfile, temp );
5239 } else
5240 init_unistr( &info->helpfile, "" );
5242 init_unistr( &info->monitorname, driver.info_3->monitorname );
5243 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5245 info->dependentfiles=NULL;
5246 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5249 /********************************************************************
5250 * construct_printer_info_3
5251 * fill a printer_info_3 struct
5252 ********************************************************************/
5254 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5256 NT_PRINTER_INFO_LEVEL *printer = NULL;
5257 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5258 WERROR status;
5259 ZERO_STRUCT(driver);
5261 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5262 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5263 if (!W_ERROR_IS_OK(status))
5264 return WERR_INVALID_PRINTER_NAME;
5266 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5267 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5269 #if 0 /* JERRY */
5272 * I put this code in during testing. Helpful when commenting out the
5273 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5274 * as win2k always queries the driver using an infor level of 6.
5275 * I've left it in (but ifdef'd out) because I'll probably
5276 * use it in experimentation again in the future. --jerry 22/01/2002
5279 if (!W_ERROR_IS_OK(status)) {
5281 * Is this a W2k client ?
5283 if (version == 3) {
5284 /* Yes - try again with a WinNT driver. */
5285 version = 2;
5286 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5287 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5289 #endif
5291 if (!W_ERROR_IS_OK(status)) {
5292 free_a_printer(&printer,2);
5293 return WERR_UNKNOWN_PRINTER_DRIVER;
5296 #if 0 /* JERRY */
5298 #endif
5301 fill_printer_driver_info_3(info, driver, servername);
5303 free_a_printer(&printer,2);
5305 return WERR_OK;
5308 /********************************************************************
5309 * construct_printer_info_6
5310 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5311 ********************************************************************/
5313 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5315 pstring temp;
5316 fstring nullstr;
5318 ZERO_STRUCTP(info);
5319 memset(&nullstr, '\0', sizeof(fstring));
5321 info->version=driver.info_3->cversion;
5323 init_unistr( &info->name, driver.info_3->name );
5324 init_unistr( &info->architecture, driver.info_3->environment );
5326 if (strlen(driver.info_3->driverpath)) {
5327 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5328 init_unistr( &info->driverpath, temp );
5329 } else
5330 init_unistr( &info->driverpath, "" );
5332 if (strlen(driver.info_3->datafile)) {
5333 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5334 init_unistr( &info->datafile, temp );
5335 } else
5336 init_unistr( &info->datafile, "" );
5338 if (strlen(driver.info_3->configfile)) {
5339 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5340 init_unistr( &info->configfile, temp );
5341 } else
5342 init_unistr( &info->configfile, "" );
5344 if (strlen(driver.info_3->helpfile)) {
5345 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5346 init_unistr( &info->helpfile, temp );
5347 } else
5348 init_unistr( &info->helpfile, "" );
5350 init_unistr( &info->monitorname, driver.info_3->monitorname );
5351 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5353 info->dependentfiles = NULL;
5354 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5356 info->previousdrivernames=NULL;
5357 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5359 info->driver_date=0;
5361 info->padding=0;
5362 info->driver_version_low=0;
5363 info->driver_version_high=0;
5365 init_unistr( &info->mfgname, "");
5366 init_unistr( &info->oem_url, "");
5367 init_unistr( &info->hardware_id, "");
5368 init_unistr( &info->provider, "");
5371 /********************************************************************
5372 * construct_printer_info_6
5373 * fill a printer_info_6 struct
5374 ********************************************************************/
5376 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5377 fstring servername, fstring architecture, uint32 version)
5379 NT_PRINTER_INFO_LEVEL *printer = NULL;
5380 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5381 WERROR status;
5383 ZERO_STRUCT(driver);
5385 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5387 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5389 if (!W_ERROR_IS_OK(status))
5390 return WERR_INVALID_PRINTER_NAME;
5392 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5394 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5396 if (!W_ERROR_IS_OK(status))
5399 * Is this a W2k client ?
5402 if (version < 3) {
5403 free_a_printer(&printer,2);
5404 return WERR_UNKNOWN_PRINTER_DRIVER;
5407 /* Yes - try again with a WinNT driver. */
5408 version = 2;
5409 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5410 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5411 if (!W_ERROR_IS_OK(status)) {
5412 free_a_printer(&printer,2);
5413 return WERR_UNKNOWN_PRINTER_DRIVER;
5417 fill_printer_driver_info_6(info, driver, servername);
5419 free_a_printer(&printer,2);
5420 free_a_printer_driver(driver, 3);
5422 return WERR_OK;
5425 /****************************************************************************
5426 ****************************************************************************/
5428 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5430 SAFE_FREE(info->dependentfiles);
5433 /****************************************************************************
5434 ****************************************************************************/
5436 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5438 SAFE_FREE(info->dependentfiles);
5441 /****************************************************************************
5442 ****************************************************************************/
5444 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5446 DRIVER_INFO_1 *info=NULL;
5447 WERROR result;
5449 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5450 return WERR_NOMEM;
5452 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5453 if (!W_ERROR_IS_OK(result))
5454 goto out;
5456 /* check the required size. */
5457 *needed += spoolss_size_printer_driver_info_1(info);
5459 if (*needed > offered) {
5460 result = WERR_INSUFFICIENT_BUFFER;
5461 goto out;
5464 if (!rpcbuf_alloc_size(buffer, *needed)) {
5465 result = WERR_NOMEM;
5466 goto out;
5469 /* fill the buffer with the structures */
5470 smb_io_printer_driver_info_1("", buffer, info, 0);
5472 out:
5473 /* clear memory */
5474 SAFE_FREE(info);
5476 return result;
5479 /****************************************************************************
5480 ****************************************************************************/
5482 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5484 DRIVER_INFO_2 *info=NULL;
5485 WERROR result;
5487 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5488 return WERR_NOMEM;
5490 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5491 if (!W_ERROR_IS_OK(result))
5492 goto out;
5494 /* check the required size. */
5495 *needed += spoolss_size_printer_driver_info_2(info);
5497 if (*needed > offered) {
5498 result = WERR_INSUFFICIENT_BUFFER;
5499 goto out;
5502 if (!rpcbuf_alloc_size(buffer, *needed)) {
5503 result = WERR_NOMEM;
5504 goto out;
5507 /* fill the buffer with the structures */
5508 smb_io_printer_driver_info_2("", buffer, info, 0);
5510 out:
5511 /* clear memory */
5512 SAFE_FREE(info);
5514 return result;
5517 /****************************************************************************
5518 ****************************************************************************/
5520 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5522 DRIVER_INFO_3 info;
5523 WERROR result;
5525 ZERO_STRUCT(info);
5527 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5528 if (!W_ERROR_IS_OK(result))
5529 goto out;
5531 /* check the required size. */
5532 *needed += spoolss_size_printer_driver_info_3(&info);
5534 if (*needed > offered) {
5535 result = WERR_INSUFFICIENT_BUFFER;
5536 goto out;
5539 if (!rpcbuf_alloc_size(buffer, *needed)) {
5540 result = WERR_NOMEM;
5541 goto out;
5544 /* fill the buffer with the structures */
5545 smb_io_printer_driver_info_3("", buffer, &info, 0);
5547 out:
5548 free_printer_driver_info_3(&info);
5550 return result;
5553 /****************************************************************************
5554 ****************************************************************************/
5556 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5558 DRIVER_INFO_6 info;
5559 WERROR result;
5561 ZERO_STRUCT(info);
5563 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5564 if (!W_ERROR_IS_OK(result))
5565 goto out;
5567 /* check the required size. */
5568 *needed += spoolss_size_printer_driver_info_6(&info);
5570 if (*needed > offered) {
5571 result = WERR_INSUFFICIENT_BUFFER;
5572 goto out;
5575 if (!rpcbuf_alloc_size(buffer, *needed)) {
5576 result = WERR_NOMEM;
5577 goto out;
5580 /* fill the buffer with the structures */
5581 smb_io_printer_driver_info_6("", buffer, &info, 0);
5583 out:
5584 free_printer_driver_info_6(&info);
5586 return result;
5589 /****************************************************************************
5590 ****************************************************************************/
5592 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5594 POLICY_HND *handle = &q_u->handle;
5595 UNISTR2 *uni_arch = &q_u->architecture;
5596 uint32 level = q_u->level;
5597 uint32 clientmajorversion = q_u->clientmajorversion;
5598 RPC_BUFFER *buffer = NULL;
5599 uint32 offered = q_u->offered;
5600 uint32 *needed = &r_u->needed;
5601 uint32 *servermajorversion = &r_u->servermajorversion;
5602 uint32 *serverminorversion = &r_u->serverminorversion;
5603 Printer_entry *printer;
5605 fstring servername;
5606 fstring architecture;
5607 int snum;
5609 /* that's an [in out] buffer */
5611 if (!q_u->buffer && (offered!=0)) {
5612 return WERR_INVALID_PARAM;
5615 rpcbuf_move(q_u->buffer, &r_u->buffer);
5616 buffer = r_u->buffer;
5618 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5620 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5621 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5622 return WERR_INVALID_PRINTER_NAME;
5625 *needed = 0;
5626 *servermajorversion = 0;
5627 *serverminorversion = 0;
5629 fstrcpy(servername, get_server_name( printer ));
5630 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5632 if (!get_printer_snum(p, handle, &snum))
5633 return WERR_BADFID;
5635 switch (level) {
5636 case 1:
5637 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5638 case 2:
5639 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5640 case 3:
5641 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5642 case 6:
5643 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5644 #if 0 /* JERRY */
5645 case 101:
5646 /* apparently this call is the equivalent of
5647 EnumPrinterDataEx() for the DsDriver key */
5648 break;
5649 #endif
5652 return WERR_UNKNOWN_LEVEL;
5655 /****************************************************************************
5656 ****************************************************************************/
5658 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5660 POLICY_HND *handle = &q_u->handle;
5662 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5664 if (!Printer) {
5665 DEBUG(3,("Error in startpageprinter printer handle\n"));
5666 return WERR_BADFID;
5669 Printer->page_started=True;
5670 return WERR_OK;
5673 /****************************************************************************
5674 ****************************************************************************/
5676 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5678 POLICY_HND *handle = &q_u->handle;
5679 int snum;
5681 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5683 if (!Printer) {
5684 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5685 return WERR_BADFID;
5688 if (!get_printer_snum(p, handle, &snum))
5689 return WERR_BADFID;
5691 Printer->page_started=False;
5692 print_job_endpage(snum, Printer->jobid);
5694 return WERR_OK;
5697 /********************************************************************
5698 * api_spoolss_getprinter
5699 * called from the spoolss dispatcher
5701 ********************************************************************/
5703 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5705 POLICY_HND *handle = &q_u->handle;
5706 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5707 uint32 *jobid = &r_u->jobid;
5709 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5710 int snum;
5711 pstring jobname;
5712 fstring datatype;
5713 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5714 struct current_user user;
5716 if (!Printer) {
5717 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5718 return WERR_BADFID;
5721 get_current_user(&user, p);
5724 * a nice thing with NT is it doesn't listen to what you tell it.
5725 * when asked to send _only_ RAW datas, it tries to send datas
5726 * in EMF format.
5728 * So I add checks like in NT Server ...
5731 if (info_1->p_datatype != 0) {
5732 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5733 if (strcmp(datatype, "RAW") != 0) {
5734 (*jobid)=0;
5735 return WERR_INVALID_DATATYPE;
5739 /* get the share number of the printer */
5740 if (!get_printer_snum(p, handle, &snum)) {
5741 return WERR_BADFID;
5744 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5746 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5748 /* An error occured in print_job_start() so return an appropriate
5749 NT error code. */
5751 if (Printer->jobid == -1) {
5752 return map_werror_from_unix(errno);
5755 Printer->document_started=True;
5756 (*jobid) = Printer->jobid;
5758 return WERR_OK;
5761 /********************************************************************
5762 * api_spoolss_getprinter
5763 * called from the spoolss dispatcher
5765 ********************************************************************/
5767 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5769 POLICY_HND *handle = &q_u->handle;
5771 return _spoolss_enddocprinter_internal(p, handle);
5774 /****************************************************************************
5775 ****************************************************************************/
5777 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5779 POLICY_HND *handle = &q_u->handle;
5780 uint32 buffer_size = q_u->buffer_size;
5781 uint8 *buffer = q_u->buffer;
5782 uint32 *buffer_written = &q_u->buffer_size2;
5783 int snum;
5784 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5786 if (!Printer) {
5787 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5788 r_u->buffer_written = q_u->buffer_size2;
5789 return WERR_BADFID;
5792 if (!get_printer_snum(p, handle, &snum))
5793 return WERR_BADFID;
5795 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5796 (SMB_OFF_T)-1, (size_t)buffer_size);
5797 if (*buffer_written == (uint32)-1) {
5798 r_u->buffer_written = 0;
5799 if (errno == ENOSPC)
5800 return WERR_NO_SPOOL_SPACE;
5801 else
5802 return WERR_ACCESS_DENIED;
5805 r_u->buffer_written = q_u->buffer_size2;
5807 return WERR_OK;
5810 /********************************************************************
5811 * api_spoolss_getprinter
5812 * called from the spoolss dispatcher
5814 ********************************************************************/
5816 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5817 pipes_struct *p)
5819 struct current_user user;
5820 int snum;
5821 WERROR errcode = WERR_BADFUNC;
5822 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5824 get_current_user(&user, p);
5826 if (!Printer) {
5827 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5828 return WERR_BADFID;
5831 if (!get_printer_snum(p, handle, &snum))
5832 return WERR_BADFID;
5834 switch (command) {
5835 case PRINTER_CONTROL_PAUSE:
5836 if (print_queue_pause(&user, snum, &errcode)) {
5837 errcode = WERR_OK;
5839 break;
5840 case PRINTER_CONTROL_RESUME:
5841 case PRINTER_CONTROL_UNPAUSE:
5842 if (print_queue_resume(&user, snum, &errcode)) {
5843 errcode = WERR_OK;
5845 break;
5846 case PRINTER_CONTROL_PURGE:
5847 if (print_queue_purge(&user, snum, &errcode)) {
5848 errcode = WERR_OK;
5850 break;
5851 default:
5852 return WERR_UNKNOWN_LEVEL;
5855 return errcode;
5858 /********************************************************************
5859 * api_spoolss_abortprinter
5860 * From MSDN: "Deletes printer's spool file if printer is configured
5861 * for spooling"
5862 ********************************************************************/
5864 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5866 POLICY_HND *handle = &q_u->handle;
5867 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5868 int snum;
5869 struct current_user user;
5870 WERROR errcode = WERR_OK;
5872 if (!Printer) {
5873 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5874 return WERR_BADFID;
5877 if (!get_printer_snum(p, handle, &snum))
5878 return WERR_BADFID;
5880 get_current_user( &user, p );
5882 print_job_delete( &user, snum, Printer->jobid, &errcode );
5884 return errcode;
5887 /********************************************************************
5888 * called by spoolss_api_setprinter
5889 * when updating a printer description
5890 ********************************************************************/
5892 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5893 const SPOOL_PRINTER_INFO_LEVEL *info,
5894 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5896 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5897 WERROR result;
5898 int snum;
5900 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5902 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5903 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5904 OUR_HANDLE(handle)));
5906 result = WERR_BADFID;
5907 goto done;
5910 if (!secdesc_ctr) {
5911 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5912 result = WERR_INVALID_PARAM;
5913 goto done;
5916 /* Check the user has permissions to change the security
5917 descriptor. By experimentation with two NT machines, the user
5918 requires Full Access to the printer to change security
5919 information. */
5921 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5922 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5923 result = WERR_ACCESS_DENIED;
5924 goto done;
5927 /* NT seems to like setting the security descriptor even though
5928 nothing may have actually changed. */
5930 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5932 if (DEBUGLEVEL >= 10) {
5933 SEC_ACL *the_acl;
5934 int i;
5936 the_acl = old_secdesc_ctr->sec->dacl;
5937 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5938 PRINTERNAME(snum), the_acl->num_aces));
5940 for (i = 0; i < the_acl->num_aces; i++) {
5941 fstring sid_str;
5943 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5945 DEBUG(10, ("%s 0x%08x\n", sid_str,
5946 the_acl->aces[i].access_mask));
5949 the_acl = secdesc_ctr->sec->dacl;
5951 if (the_acl) {
5952 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5953 PRINTERNAME(snum), the_acl->num_aces));
5955 for (i = 0; i < the_acl->num_aces; i++) {
5956 fstring sid_str;
5958 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5960 DEBUG(10, ("%s 0x%08x\n", sid_str,
5961 the_acl->aces[i].access_mask));
5963 } else {
5964 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5968 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5969 if (!new_secdesc_ctr) {
5970 result = WERR_NOMEM;
5971 goto done;
5974 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5975 result = WERR_OK;
5976 goto done;
5979 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5981 done:
5983 return result;
5986 /********************************************************************
5987 Canonicalize printer info from a client
5989 ATTN: It does not matter what we set the servername to hear
5990 since we do the necessary work in get_a_printer() to set it to
5991 the correct value based on what the client sent in the
5992 _spoolss_open_printer_ex().
5993 ********************************************************************/
5995 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5997 fstring printername;
5998 const char *p;
6000 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6001 "portname=%s drivername=%s comment=%s location=%s\n",
6002 info->servername, info->printername, info->sharename,
6003 info->portname, info->drivername, info->comment, info->location));
6005 /* we force some elements to "correct" values */
6006 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6007 fstrcpy(info->sharename, lp_servicename(snum));
6009 /* check to see if we allow printername != sharename */
6011 if ( lp_force_printername(snum) ) {
6012 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6013 global_myname(), info->sharename );
6014 } else {
6016 /* make sure printername is in \\server\printername format */
6018 fstrcpy( printername, info->printername );
6019 p = printername;
6020 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6021 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6022 p++;
6025 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6026 global_myname(), p );
6029 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6030 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6034 return True;
6037 /****************************************************************************
6038 ****************************************************************************/
6040 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6042 char *cmd = lp_addport_cmd();
6043 pstring command;
6044 int ret;
6045 int fd;
6046 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6047 BOOL is_print_op = False;
6049 if ( !*cmd ) {
6050 return WERR_ACCESS_DENIED;
6053 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6055 if ( token )
6056 is_print_op = user_has_privileges( token, &se_printop );
6058 DEBUG(10,("Running [%s]\n", command));
6060 /********* BEGIN SePrintOperatorPrivilege **********/
6062 if ( is_print_op )
6063 become_root();
6065 ret = smbrun(command, &fd);
6067 if ( is_print_op )
6068 unbecome_root();
6070 /********* END SePrintOperatorPrivilege **********/
6072 DEBUGADD(10,("returned [%d]\n", ret));
6074 if ( ret != 0 ) {
6075 if (fd != -1)
6076 close(fd);
6077 return WERR_ACCESS_DENIED;
6080 return WERR_OK;
6083 /****************************************************************************
6084 ****************************************************************************/
6086 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6088 char *cmd = lp_addprinter_cmd();
6089 char **qlines;
6090 pstring command;
6091 int numlines;
6092 int ret;
6093 int fd;
6094 fstring remote_machine = "%m";
6095 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6096 BOOL is_print_op = False;
6098 standard_sub_basic(current_user_info.smb_name,
6099 current_user_info.domain,
6100 remote_machine,sizeof(remote_machine));
6102 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6103 cmd, printer->info_2->printername, printer->info_2->sharename,
6104 printer->info_2->portname, printer->info_2->drivername,
6105 printer->info_2->location, printer->info_2->comment, remote_machine);
6107 if ( token )
6108 is_print_op = user_has_privileges( token, &se_printop );
6110 DEBUG(10,("Running [%s]\n", command));
6112 /********* BEGIN SePrintOperatorPrivilege **********/
6114 if ( is_print_op )
6115 become_root();
6117 if ( (ret = smbrun(command, &fd)) == 0 ) {
6118 /* Tell everyone we updated smb.conf. */
6119 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6122 if ( is_print_op )
6123 unbecome_root();
6125 /********* END SePrintOperatorPrivilege **********/
6127 DEBUGADD(10,("returned [%d]\n", ret));
6129 if ( ret != 0 ) {
6130 if (fd != -1)
6131 close(fd);
6132 return False;
6135 /* reload our services immediately */
6136 reload_services( False );
6138 numlines = 0;
6139 /* Get lines and convert them back to dos-codepage */
6140 qlines = fd_lines_load(fd, &numlines, 0);
6141 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6142 close(fd);
6144 /* Set the portname to what the script says the portname should be. */
6145 /* but don't require anything to be return from the script exit a good error code */
6147 if (numlines) {
6148 /* Set the portname to what the script says the portname should be. */
6149 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6150 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6153 file_lines_free(qlines);
6154 return True;
6158 /********************************************************************
6159 * Called by spoolss_api_setprinter
6160 * when updating a printer description.
6161 ********************************************************************/
6163 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6164 const SPOOL_PRINTER_INFO_LEVEL *info,
6165 DEVICEMODE *devmode)
6167 int snum;
6168 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6169 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6170 WERROR result;
6171 UNISTR2 buffer;
6172 fstring asc_buffer;
6174 DEBUG(8,("update_printer\n"));
6176 result = WERR_OK;
6178 if (!Printer) {
6179 result = WERR_BADFID;
6180 goto done;
6183 if (!get_printer_snum(p, handle, &snum)) {
6184 result = WERR_BADFID;
6185 goto done;
6188 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6189 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6190 result = WERR_BADFID;
6191 goto done;
6194 DEBUGADD(8,("Converting info_2 struct\n"));
6197 * convert_printer_info converts the incoming
6198 * info from the client and overwrites the info
6199 * just read from the tdb in the pointer 'printer'.
6202 if (!convert_printer_info(info, printer, level)) {
6203 result = WERR_NOMEM;
6204 goto done;
6207 if (devmode) {
6208 /* we have a valid devmode
6209 convert it and link it*/
6211 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6212 if (!convert_devicemode(printer->info_2->printername, devmode,
6213 &printer->info_2->devmode)) {
6214 result = WERR_NOMEM;
6215 goto done;
6219 /* Do sanity check on the requested changes for Samba */
6221 if (!check_printer_ok(printer->info_2, snum)) {
6222 result = WERR_INVALID_PARAM;
6223 goto done;
6226 /* FIXME!!! If the driver has changed we really should verify that
6227 it is installed before doing much else --jerry */
6229 /* Check calling user has permission to update printer description */
6231 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6232 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6233 result = WERR_ACCESS_DENIED;
6234 goto done;
6237 /* Call addprinter hook */
6238 /* Check changes to see if this is really needed */
6240 if ( *lp_addprinter_cmd()
6241 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6242 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6243 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6244 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6246 /* add_printer_hook() will call reload_services() */
6248 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6249 result = WERR_ACCESS_DENIED;
6250 goto done;
6255 * When a *new* driver is bound to a printer, the drivername is used to
6256 * lookup previously saved driver initialization info, which is then
6257 * bound to the printer, simulating what happens in the Windows arch.
6259 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6261 if (!set_driver_init(printer, 2))
6263 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6264 printer->info_2->drivername));
6267 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6268 printer->info_2->drivername));
6270 notify_printer_driver(snum, printer->info_2->drivername);
6274 * flag which changes actually occured. This is a small subset of
6275 * all the possible changes. We also have to update things in the
6276 * DsSpooler key.
6279 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6280 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6281 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6282 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6284 notify_printer_comment(snum, printer->info_2->comment);
6287 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6288 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6289 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6290 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6292 notify_printer_sharename(snum, printer->info_2->sharename);
6295 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6296 char *pname;
6298 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6299 pname++;
6300 else
6301 pname = printer->info_2->printername;
6304 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6305 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6306 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6308 notify_printer_printername( snum, pname );
6311 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6312 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6313 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6314 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6316 notify_printer_port(snum, printer->info_2->portname);
6319 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6320 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6321 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6322 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6324 notify_printer_location(snum, printer->info_2->location);
6327 /* here we need to update some more DsSpooler keys */
6328 /* uNCName, serverName, shortServerName */
6330 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6331 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6332 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6333 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6334 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6336 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6337 global_myname(), printer->info_2->sharename );
6338 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6339 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6340 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6342 /* Update printer info */
6343 result = mod_a_printer(printer, 2);
6345 done:
6346 free_a_printer(&printer, 2);
6347 free_a_printer(&old_printer, 2);
6350 return result;
6353 /****************************************************************************
6354 ****************************************************************************/
6355 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6356 const SPOOL_PRINTER_INFO_LEVEL *info)
6358 #ifdef HAVE_ADS
6359 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6360 int snum;
6361 Printer_entry *Printer;
6363 if ( lp_security() != SEC_ADS ) {
6364 return WERR_UNKNOWN_LEVEL;
6367 Printer = find_printer_index_by_hnd(p, handle);
6369 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6371 if (!Printer)
6372 return WERR_BADFID;
6374 if (!get_printer_snum(p, handle, &snum))
6375 return WERR_BADFID;
6377 nt_printer_publish(Printer, snum, info7->action);
6379 return WERR_OK;
6380 #else
6381 return WERR_UNKNOWN_LEVEL;
6382 #endif
6384 /****************************************************************************
6385 ****************************************************************************/
6387 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6389 POLICY_HND *handle = &q_u->handle;
6390 uint32 level = q_u->level;
6391 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6392 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6393 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6394 uint32 command = q_u->command;
6395 WERROR result;
6397 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6399 if (!Printer) {
6400 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6401 return WERR_BADFID;
6404 /* check the level */
6405 switch (level) {
6406 case 0:
6407 return control_printer(handle, command, p);
6408 case 2:
6409 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6410 if (!W_ERROR_IS_OK(result))
6411 return result;
6412 if (secdesc_ctr)
6413 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6414 return result;
6415 case 3:
6416 return update_printer_sec(handle, level, info, p,
6417 secdesc_ctr);
6418 case 7:
6419 return publish_or_unpublish_printer(p, handle, info);
6420 default:
6421 return WERR_UNKNOWN_LEVEL;
6425 /****************************************************************************
6426 ****************************************************************************/
6428 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6430 POLICY_HND *handle = &q_u->handle;
6431 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6433 if (!Printer) {
6434 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6435 return WERR_BADFID;
6438 if (Printer->notify.client_connected==True) {
6439 int snum = -1;
6441 if ( Printer->printer_type == SPLHND_SERVER)
6442 snum = -1;
6443 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6444 !get_printer_snum(p, handle, &snum) )
6445 return WERR_BADFID;
6447 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6450 Printer->notify.flags=0;
6451 Printer->notify.options=0;
6452 Printer->notify.localmachine[0]='\0';
6453 Printer->notify.printerlocal=0;
6454 if (Printer->notify.option)
6455 free_spool_notify_option(&Printer->notify.option);
6456 Printer->notify.client_connected=False;
6458 return WERR_OK;
6461 /****************************************************************************
6462 ****************************************************************************/
6464 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6466 /* that's an [in out] buffer */
6468 if (!q_u->buffer && (q_u->offered!=0)) {
6469 return WERR_INVALID_PARAM;
6472 rpcbuf_move(q_u->buffer, &r_u->buffer);
6474 r_u->needed = 0;
6475 return WERR_INVALID_PARAM; /* this is what a NT server
6476 returns for AddJob. AddJob
6477 must fail on non-local
6478 printers */
6481 /****************************************************************************
6482 ****************************************************************************/
6484 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6485 int position, int snum,
6486 const NT_PRINTER_INFO_LEVEL *ntprinter)
6488 struct tm *t;
6490 t=gmtime(&queue->time);
6492 job_info->jobid=queue->job;
6493 init_unistr(&job_info->printername, lp_servicename(snum));
6494 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6495 init_unistr(&job_info->username, queue->fs_user);
6496 init_unistr(&job_info->document, queue->fs_file);
6497 init_unistr(&job_info->datatype, "RAW");
6498 init_unistr(&job_info->text_status, "");
6499 job_info->status=nt_printj_status(queue->status);
6500 job_info->priority=queue->priority;
6501 job_info->position=position;
6502 job_info->totalpages=queue->page_count;
6503 job_info->pagesprinted=0;
6505 make_systemtime(&job_info->submitted, t);
6508 /****************************************************************************
6509 ****************************************************************************/
6511 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6512 int position, int snum,
6513 const NT_PRINTER_INFO_LEVEL *ntprinter,
6514 DEVICEMODE *devmode)
6516 struct tm *t;
6518 t=gmtime(&queue->time);
6520 job_info->jobid=queue->job;
6522 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6524 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6525 init_unistr(&job_info->username, queue->fs_user);
6526 init_unistr(&job_info->document, queue->fs_file);
6527 init_unistr(&job_info->notifyname, queue->fs_user);
6528 init_unistr(&job_info->datatype, "RAW");
6529 init_unistr(&job_info->printprocessor, "winprint");
6530 init_unistr(&job_info->parameters, "");
6531 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6532 init_unistr(&job_info->text_status, "");
6534 /* and here the security descriptor */
6536 job_info->status=nt_printj_status(queue->status);
6537 job_info->priority=queue->priority;
6538 job_info->position=position;
6539 job_info->starttime=0;
6540 job_info->untiltime=0;
6541 job_info->totalpages=queue->page_count;
6542 job_info->size=queue->size;
6543 make_systemtime(&(job_info->submitted), t);
6544 job_info->timeelapsed=0;
6545 job_info->pagesprinted=0;
6547 job_info->devmode = devmode;
6549 return (True);
6552 /****************************************************************************
6553 Enumjobs at level 1.
6554 ****************************************************************************/
6556 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6557 const NT_PRINTER_INFO_LEVEL *ntprinter,
6558 RPC_BUFFER *buffer, uint32 offered,
6559 uint32 *needed, uint32 *returned)
6561 JOB_INFO_1 *info;
6562 int i;
6563 WERROR result = WERR_OK;
6565 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6566 if (info==NULL) {
6567 *returned=0;
6568 return WERR_NOMEM;
6571 for (i=0; i<*returned; i++)
6572 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6574 /* check the required size. */
6575 for (i=0; i<*returned; i++)
6576 (*needed) += spoolss_size_job_info_1(&info[i]);
6578 if (*needed > offered) {
6579 result = WERR_INSUFFICIENT_BUFFER;
6580 goto out;
6583 if (!rpcbuf_alloc_size(buffer, *needed)) {
6584 result = WERR_NOMEM;
6585 goto out;
6588 /* fill the buffer with the structures */
6589 for (i=0; i<*returned; i++)
6590 smb_io_job_info_1("", buffer, &info[i], 0);
6592 out:
6593 /* clear memory */
6594 SAFE_FREE(info);
6596 if ( !W_ERROR_IS_OK(result) )
6597 *returned = 0;
6599 return result;
6602 /****************************************************************************
6603 Enumjobs at level 2.
6604 ****************************************************************************/
6606 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6607 const NT_PRINTER_INFO_LEVEL *ntprinter,
6608 RPC_BUFFER *buffer, uint32 offered,
6609 uint32 *needed, uint32 *returned)
6611 JOB_INFO_2 *info = NULL;
6612 int i;
6613 WERROR result = WERR_OK;
6614 DEVICEMODE *devmode = NULL;
6616 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6617 *returned=0;
6618 return WERR_NOMEM;
6621 /* this should not be a failure condition if the devmode is NULL */
6623 devmode = construct_dev_mode(lp_const_servicename(snum));
6625 for (i=0; i<*returned; i++)
6626 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6628 /* check the required size. */
6629 for (i=0; i<*returned; i++)
6630 (*needed) += spoolss_size_job_info_2(&info[i]);
6632 if (*needed > offered) {
6633 result = WERR_INSUFFICIENT_BUFFER;
6634 goto out;
6637 if (!rpcbuf_alloc_size(buffer, *needed)) {
6638 result = WERR_NOMEM;
6639 goto out;
6642 /* fill the buffer with the structures */
6643 for (i=0; i<*returned; i++)
6644 smb_io_job_info_2("", buffer, &info[i], 0);
6646 out:
6647 free_devmode(devmode);
6648 SAFE_FREE(info);
6650 if ( !W_ERROR_IS_OK(result) )
6651 *returned = 0;
6653 return result;
6657 /****************************************************************************
6658 Enumjobs.
6659 ****************************************************************************/
6661 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6663 POLICY_HND *handle = &q_u->handle;
6664 uint32 level = q_u->level;
6665 RPC_BUFFER *buffer = NULL;
6666 uint32 offered = q_u->offered;
6667 uint32 *needed = &r_u->needed;
6668 uint32 *returned = &r_u->returned;
6669 WERROR wret;
6670 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6671 int snum;
6672 print_status_struct prt_status;
6673 print_queue_struct *queue=NULL;
6675 /* that's an [in out] buffer */
6677 if (!q_u->buffer && (offered!=0)) {
6678 return WERR_INVALID_PARAM;
6681 rpcbuf_move(q_u->buffer, &r_u->buffer);
6682 buffer = r_u->buffer;
6684 DEBUG(4,("_spoolss_enumjobs\n"));
6686 *needed=0;
6687 *returned=0;
6689 /* lookup the printer snum and tdb entry */
6691 if (!get_printer_snum(p, handle, &snum))
6692 return WERR_BADFID;
6694 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6695 if ( !W_ERROR_IS_OK(wret) )
6696 return wret;
6698 *returned = print_queue_status(snum, &queue, &prt_status);
6699 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6701 if (*returned == 0) {
6702 SAFE_FREE(queue);
6703 free_a_printer(&ntprinter, 2);
6704 return WERR_OK;
6707 switch (level) {
6708 case 1:
6709 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6710 break;
6711 case 2:
6712 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6713 break;
6714 default:
6715 *returned=0;
6716 wret = WERR_UNKNOWN_LEVEL;
6717 break;
6720 SAFE_FREE(queue);
6721 free_a_printer( &ntprinter, 2 );
6722 return wret;
6725 /****************************************************************************
6726 ****************************************************************************/
6728 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6730 return WERR_OK;
6733 /****************************************************************************
6734 ****************************************************************************/
6736 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6738 POLICY_HND *handle = &q_u->handle;
6739 uint32 jobid = q_u->jobid;
6740 uint32 command = q_u->command;
6742 struct current_user user;
6743 int snum;
6744 WERROR errcode = WERR_BADFUNC;
6746 if (!get_printer_snum(p, handle, &snum)) {
6747 return WERR_BADFID;
6750 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6751 return WERR_INVALID_PRINTER_NAME;
6754 get_current_user(&user, p);
6756 switch (command) {
6757 case JOB_CONTROL_CANCEL:
6758 case JOB_CONTROL_DELETE:
6759 if (print_job_delete(&user, snum, jobid, &errcode)) {
6760 errcode = WERR_OK;
6762 break;
6763 case JOB_CONTROL_PAUSE:
6764 if (print_job_pause(&user, snum, jobid, &errcode)) {
6765 errcode = WERR_OK;
6767 break;
6768 case JOB_CONTROL_RESTART:
6769 case JOB_CONTROL_RESUME:
6770 if (print_job_resume(&user, snum, jobid, &errcode)) {
6771 errcode = WERR_OK;
6773 break;
6774 default:
6775 return WERR_UNKNOWN_LEVEL;
6778 return errcode;
6781 /****************************************************************************
6782 Enumerates all printer drivers at level 1.
6783 ****************************************************************************/
6785 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6787 int i;
6788 int ndrivers;
6789 uint32 version;
6790 fstring *list = NULL;
6791 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6792 DRIVER_INFO_1 *driver_info_1=NULL;
6793 WERROR result = WERR_OK;
6795 *returned=0;
6797 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6798 list=NULL;
6799 ndrivers=get_ntdrivers(&list, architecture, version);
6800 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6802 if(ndrivers == -1) {
6803 SAFE_FREE(driver_info_1);
6804 return WERR_NOMEM;
6807 if(ndrivers != 0) {
6808 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6809 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6810 SAFE_FREE(list);
6811 return WERR_NOMEM;
6815 for (i=0; i<ndrivers; i++) {
6816 WERROR status;
6817 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6818 ZERO_STRUCT(driver);
6819 status = get_a_printer_driver(&driver, 3, list[i],
6820 architecture, version);
6821 if (!W_ERROR_IS_OK(status)) {
6822 SAFE_FREE(list);
6823 SAFE_FREE(driver_info_1);
6824 return status;
6826 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6827 free_a_printer_driver(driver, 3);
6830 *returned+=ndrivers;
6831 SAFE_FREE(list);
6834 /* check the required size. */
6835 for (i=0; i<*returned; i++) {
6836 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6837 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6840 if (*needed > offered) {
6841 result = WERR_INSUFFICIENT_BUFFER;
6842 goto out;
6845 if (!rpcbuf_alloc_size(buffer, *needed)) {
6846 result = WERR_NOMEM;
6847 goto out;
6850 /* fill the buffer with the driver structures */
6851 for (i=0; i<*returned; i++) {
6852 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6853 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6856 out:
6857 SAFE_FREE(driver_info_1);
6859 if ( !W_ERROR_IS_OK(result) )
6860 *returned = 0;
6862 return result;
6865 /****************************************************************************
6866 Enumerates all printer drivers at level 2.
6867 ****************************************************************************/
6869 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6871 int i;
6872 int ndrivers;
6873 uint32 version;
6874 fstring *list = NULL;
6875 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6876 DRIVER_INFO_2 *driver_info_2=NULL;
6877 WERROR result = WERR_OK;
6879 *returned=0;
6881 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6882 list=NULL;
6883 ndrivers=get_ntdrivers(&list, architecture, version);
6884 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6886 if(ndrivers == -1) {
6887 SAFE_FREE(driver_info_2);
6888 return WERR_NOMEM;
6891 if(ndrivers != 0) {
6892 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6893 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6894 SAFE_FREE(list);
6895 return WERR_NOMEM;
6899 for (i=0; i<ndrivers; i++) {
6900 WERROR status;
6902 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6903 ZERO_STRUCT(driver);
6904 status = get_a_printer_driver(&driver, 3, list[i],
6905 architecture, version);
6906 if (!W_ERROR_IS_OK(status)) {
6907 SAFE_FREE(list);
6908 SAFE_FREE(driver_info_2);
6909 return status;
6911 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6912 free_a_printer_driver(driver, 3);
6915 *returned+=ndrivers;
6916 SAFE_FREE(list);
6919 /* check the required size. */
6920 for (i=0; i<*returned; i++) {
6921 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6922 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6925 if (*needed > offered) {
6926 result = WERR_INSUFFICIENT_BUFFER;
6927 goto out;
6930 if (!rpcbuf_alloc_size(buffer, *needed)) {
6931 result = WERR_NOMEM;
6932 goto out;
6935 /* fill the buffer with the form structures */
6936 for (i=0; i<*returned; i++) {
6937 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6938 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6941 out:
6942 SAFE_FREE(driver_info_2);
6944 if ( !W_ERROR_IS_OK(result) )
6945 *returned = 0;
6947 return result;
6950 /****************************************************************************
6951 Enumerates all printer drivers at level 3.
6952 ****************************************************************************/
6954 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6956 int i;
6957 int ndrivers;
6958 uint32 version;
6959 fstring *list = NULL;
6960 DRIVER_INFO_3 *driver_info_3=NULL;
6961 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6962 WERROR result = WERR_OK;
6964 *returned=0;
6966 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6967 list=NULL;
6968 ndrivers=get_ntdrivers(&list, architecture, version);
6969 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6971 if(ndrivers == -1) {
6972 SAFE_FREE(driver_info_3);
6973 return WERR_NOMEM;
6976 if(ndrivers != 0) {
6977 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6978 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6979 SAFE_FREE(list);
6980 return WERR_NOMEM;
6984 for (i=0; i<ndrivers; i++) {
6985 WERROR status;
6987 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6988 ZERO_STRUCT(driver);
6989 status = get_a_printer_driver(&driver, 3, list[i],
6990 architecture, version);
6991 if (!W_ERROR_IS_OK(status)) {
6992 SAFE_FREE(list);
6993 SAFE_FREE(driver_info_3);
6994 return status;
6996 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6997 free_a_printer_driver(driver, 3);
7000 *returned+=ndrivers;
7001 SAFE_FREE(list);
7004 /* check the required size. */
7005 for (i=0; i<*returned; i++) {
7006 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7007 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7010 if (*needed > offered) {
7011 result = WERR_INSUFFICIENT_BUFFER;
7012 goto out;
7015 if (!rpcbuf_alloc_size(buffer, *needed)) {
7016 result = WERR_NOMEM;
7017 goto out;
7020 /* fill the buffer with the driver structures */
7021 for (i=0; i<*returned; i++) {
7022 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7023 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7026 out:
7027 for (i=0; i<*returned; i++) {
7028 SAFE_FREE(driver_info_3[i].dependentfiles);
7031 SAFE_FREE(driver_info_3);
7033 if ( !W_ERROR_IS_OK(result) )
7034 *returned = 0;
7036 return result;
7039 /****************************************************************************
7040 Enumerates all printer drivers.
7041 ****************************************************************************/
7043 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7045 uint32 level = q_u->level;
7046 RPC_BUFFER *buffer = NULL;
7047 uint32 offered = q_u->offered;
7048 uint32 *needed = &r_u->needed;
7049 uint32 *returned = &r_u->returned;
7051 fstring servername;
7052 fstring architecture;
7054 /* that's an [in out] buffer */
7056 if (!q_u->buffer && (offered!=0)) {
7057 return WERR_INVALID_PARAM;
7060 rpcbuf_move(q_u->buffer, &r_u->buffer);
7061 buffer = r_u->buffer;
7063 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7065 *needed = 0;
7066 *returned = 0;
7068 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7069 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7071 if ( !is_myname_or_ipaddr( servername ) )
7072 return WERR_UNKNOWN_PRINTER_DRIVER;
7074 switch (level) {
7075 case 1:
7076 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7077 case 2:
7078 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7079 case 3:
7080 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7081 default:
7082 return WERR_UNKNOWN_LEVEL;
7086 /****************************************************************************
7087 ****************************************************************************/
7089 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7091 form->flag=list->flag;
7092 init_unistr(&form->name, list->name);
7093 form->width=list->width;
7094 form->length=list->length;
7095 form->left=list->left;
7096 form->top=list->top;
7097 form->right=list->right;
7098 form->bottom=list->bottom;
7101 /****************************************************************************
7102 ****************************************************************************/
7104 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7106 uint32 level = q_u->level;
7107 RPC_BUFFER *buffer = NULL;
7108 uint32 offered = q_u->offered;
7109 uint32 *needed = &r_u->needed;
7110 uint32 *numofforms = &r_u->numofforms;
7111 uint32 numbuiltinforms;
7113 nt_forms_struct *list=NULL;
7114 nt_forms_struct *builtinlist=NULL;
7115 FORM_1 *forms_1;
7116 int buffer_size=0;
7117 int i;
7119 /* that's an [in out] buffer */
7121 if (!q_u->buffer && (offered!=0) ) {
7122 return WERR_INVALID_PARAM;
7125 rpcbuf_move(q_u->buffer, &r_u->buffer);
7126 buffer = r_u->buffer;
7128 DEBUG(4,("_spoolss_enumforms\n"));
7129 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7130 DEBUGADD(5,("Info level [%d]\n", level));
7132 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7133 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7134 *numofforms = get_ntforms(&list);
7135 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7136 *numofforms += numbuiltinforms;
7138 if (*numofforms == 0) {
7139 SAFE_FREE(builtinlist);
7140 SAFE_FREE(list);
7141 return WERR_NO_MORE_ITEMS;
7144 switch (level) {
7145 case 1:
7146 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7147 SAFE_FREE(builtinlist);
7148 SAFE_FREE(list);
7149 *numofforms=0;
7150 return WERR_NOMEM;
7153 /* construct the list of form structures */
7154 for (i=0; i<numbuiltinforms; i++) {
7155 DEBUGADD(6,("Filling form number [%d]\n",i));
7156 fill_form_1(&forms_1[i], &builtinlist[i]);
7159 SAFE_FREE(builtinlist);
7161 for (; i<*numofforms; i++) {
7162 DEBUGADD(6,("Filling form number [%d]\n",i));
7163 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7166 SAFE_FREE(list);
7168 /* check the required size. */
7169 for (i=0; i<numbuiltinforms; i++) {
7170 DEBUGADD(6,("adding form [%d]'s size\n",i));
7171 buffer_size += spoolss_size_form_1(&forms_1[i]);
7173 for (; i<*numofforms; i++) {
7174 DEBUGADD(6,("adding form [%d]'s size\n",i));
7175 buffer_size += spoolss_size_form_1(&forms_1[i]);
7178 *needed=buffer_size;
7180 if (*needed > offered) {
7181 SAFE_FREE(forms_1);
7182 *numofforms=0;
7183 return WERR_INSUFFICIENT_BUFFER;
7186 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7187 SAFE_FREE(forms_1);
7188 *numofforms=0;
7189 return WERR_NOMEM;
7192 /* fill the buffer with the form structures */
7193 for (i=0; i<numbuiltinforms; i++) {
7194 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7195 smb_io_form_1("", buffer, &forms_1[i], 0);
7197 for (; i<*numofforms; i++) {
7198 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7199 smb_io_form_1("", buffer, &forms_1[i], 0);
7202 SAFE_FREE(forms_1);
7204 return WERR_OK;
7206 default:
7207 SAFE_FREE(list);
7208 SAFE_FREE(builtinlist);
7209 return WERR_UNKNOWN_LEVEL;
7213 /****************************************************************************
7214 ****************************************************************************/
7216 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7218 uint32 level = q_u->level;
7219 UNISTR2 *uni_formname = &q_u->formname;
7220 RPC_BUFFER *buffer = NULL;
7221 uint32 offered = q_u->offered;
7222 uint32 *needed = &r_u->needed;
7224 nt_forms_struct *list=NULL;
7225 nt_forms_struct builtin_form;
7226 BOOL foundBuiltin;
7227 FORM_1 form_1;
7228 fstring form_name;
7229 int buffer_size=0;
7230 int numofforms=0, i=0;
7232 /* that's an [in out] buffer */
7234 if (!q_u->buffer && (offered!=0)) {
7235 return WERR_INVALID_PARAM;
7238 rpcbuf_move(q_u->buffer, &r_u->buffer);
7239 buffer = r_u->buffer;
7241 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7243 DEBUG(4,("_spoolss_getform\n"));
7244 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7245 DEBUGADD(5,("Info level [%d]\n", level));
7247 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7248 if (!foundBuiltin) {
7249 numofforms = get_ntforms(&list);
7250 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7252 if (numofforms == 0)
7253 return WERR_BADFID;
7256 switch (level) {
7257 case 1:
7258 if (foundBuiltin) {
7259 fill_form_1(&form_1, &builtin_form);
7260 } else {
7262 /* Check if the requested name is in the list of form structures */
7263 for (i=0; i<numofforms; i++) {
7265 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7267 if (strequal(form_name, list[i].name)) {
7268 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7269 fill_form_1(&form_1, &list[i]);
7270 break;
7274 SAFE_FREE(list);
7275 if (i == numofforms) {
7276 return WERR_BADFID;
7279 /* check the required size. */
7281 *needed=spoolss_size_form_1(&form_1);
7283 if (*needed > offered)
7284 return WERR_INSUFFICIENT_BUFFER;
7286 if (!rpcbuf_alloc_size(buffer, buffer_size))
7287 return WERR_NOMEM;
7289 /* fill the buffer with the form structures */
7290 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7291 smb_io_form_1("", buffer, &form_1, 0);
7293 return WERR_OK;
7295 default:
7296 SAFE_FREE(list);
7297 return WERR_UNKNOWN_LEVEL;
7301 /****************************************************************************
7302 ****************************************************************************/
7304 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7306 init_unistr(&port->port_name, name);
7309 /****************************************************************************
7310 TODO: This probably needs distinguish between TCP/IP and Local ports
7311 somehow.
7312 ****************************************************************************/
7314 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7316 init_unistr(&port->port_name, name);
7317 init_unistr(&port->monitor_name, "Local Monitor");
7318 init_unistr(&port->description, SPL_LOCAL_PORT );
7319 port->port_type=PORT_TYPE_WRITE;
7320 port->reserved=0x0;
7324 /****************************************************************************
7325 wrapper around the enumer ports command
7326 ****************************************************************************/
7328 WERROR enumports_hook( int *count, char ***lines )
7330 char *cmd = lp_enumports_cmd();
7331 char **qlines;
7332 pstring command;
7333 int numlines;
7334 int ret;
7335 int fd;
7337 *count = 0;
7338 *lines = NULL;
7340 /* if no hook then just fill in the default port */
7342 if ( !*cmd ) {
7343 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7344 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7345 qlines[1] = NULL;
7346 numlines = 1;
7348 else {
7349 /* we have a valid enumport command */
7351 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7353 DEBUG(10,("Running [%s]\n", command));
7354 ret = smbrun(command, &fd);
7355 DEBUG(10,("Returned [%d]\n", ret));
7356 if (ret != 0) {
7357 if (fd != -1) {
7358 close(fd);
7360 return WERR_ACCESS_DENIED;
7363 numlines = 0;
7364 qlines = fd_lines_load(fd, &numlines, 0);
7365 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7366 close(fd);
7369 *count = numlines;
7370 *lines = qlines;
7372 return WERR_OK;
7375 /****************************************************************************
7376 enumports level 1.
7377 ****************************************************************************/
7379 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7381 PORT_INFO_1 *ports=NULL;
7382 int i=0;
7383 WERROR result = WERR_OK;
7384 char **qlines = NULL;
7385 int numlines = 0;
7387 result = enumports_hook( &numlines, &qlines );
7388 if (!W_ERROR_IS_OK(result)) {
7389 file_lines_free(qlines);
7390 return result;
7393 if(numlines) {
7394 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7395 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7396 dos_errstr(WERR_NOMEM)));
7397 file_lines_free(qlines);
7398 return WERR_NOMEM;
7401 for (i=0; i<numlines; i++) {
7402 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7403 fill_port_1(&ports[i], qlines[i]);
7406 file_lines_free(qlines);
7408 *returned = numlines;
7410 /* check the required size. */
7411 for (i=0; i<*returned; i++) {
7412 DEBUGADD(6,("adding port [%d]'s size\n", i));
7413 *needed += spoolss_size_port_info_1(&ports[i]);
7416 if (*needed > offered) {
7417 result = WERR_INSUFFICIENT_BUFFER;
7418 goto out;
7421 if (!rpcbuf_alloc_size(buffer, *needed)) {
7422 result = WERR_NOMEM;
7423 goto out;
7426 /* fill the buffer with the ports structures */
7427 for (i=0; i<*returned; i++) {
7428 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7429 smb_io_port_1("", buffer, &ports[i], 0);
7432 out:
7433 SAFE_FREE(ports);
7435 if ( !W_ERROR_IS_OK(result) )
7436 *returned = 0;
7438 return result;
7441 /****************************************************************************
7442 enumports level 2.
7443 ****************************************************************************/
7445 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7447 PORT_INFO_2 *ports=NULL;
7448 int i=0;
7449 WERROR result = WERR_OK;
7450 char **qlines = NULL;
7451 int numlines = 0;
7453 result = enumports_hook( &numlines, &qlines );
7454 if ( !W_ERROR_IS_OK(result)) {
7455 file_lines_free(qlines);
7456 return result;
7459 if(numlines) {
7460 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7461 file_lines_free(qlines);
7462 return WERR_NOMEM;
7465 for (i=0; i<numlines; i++) {
7466 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7467 fill_port_2(&(ports[i]), qlines[i]);
7471 file_lines_free(qlines);
7473 *returned = numlines;
7475 /* check the required size. */
7476 for (i=0; i<*returned; i++) {
7477 DEBUGADD(6,("adding port [%d]'s size\n", i));
7478 *needed += spoolss_size_port_info_2(&ports[i]);
7481 if (*needed > offered) {
7482 result = WERR_INSUFFICIENT_BUFFER;
7483 goto out;
7486 if (!rpcbuf_alloc_size(buffer, *needed)) {
7487 result = WERR_NOMEM;
7488 goto out;
7491 /* fill the buffer with the ports structures */
7492 for (i=0; i<*returned; i++) {
7493 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7494 smb_io_port_2("", buffer, &ports[i], 0);
7497 out:
7498 SAFE_FREE(ports);
7500 if ( !W_ERROR_IS_OK(result) )
7501 *returned = 0;
7503 return result;
7506 /****************************************************************************
7507 enumports.
7508 ****************************************************************************/
7510 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7512 uint32 level = q_u->level;
7513 RPC_BUFFER *buffer = NULL;
7514 uint32 offered = q_u->offered;
7515 uint32 *needed = &r_u->needed;
7516 uint32 *returned = &r_u->returned;
7518 /* that's an [in out] buffer */
7520 if (!q_u->buffer && (offered!=0)) {
7521 return WERR_INVALID_PARAM;
7524 rpcbuf_move(q_u->buffer, &r_u->buffer);
7525 buffer = r_u->buffer;
7527 DEBUG(4,("_spoolss_enumports\n"));
7529 *returned=0;
7530 *needed=0;
7532 switch (level) {
7533 case 1:
7534 return enumports_level_1(buffer, offered, needed, returned);
7535 case 2:
7536 return enumports_level_2(buffer, offered, needed, returned);
7537 default:
7538 return WERR_UNKNOWN_LEVEL;
7542 /****************************************************************************
7543 ****************************************************************************/
7545 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7546 const SPOOL_PRINTER_INFO_LEVEL *info,
7547 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7548 uint32 user_switch, const SPOOL_USER_CTR *user,
7549 POLICY_HND *handle)
7551 NT_PRINTER_INFO_LEVEL *printer = NULL;
7552 fstring name;
7553 int snum;
7554 WERROR err = WERR_OK;
7556 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7557 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7558 return WERR_NOMEM;
7561 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7562 if (!convert_printer_info(info, printer, 2)) {
7563 free_a_printer(&printer, 2);
7564 return WERR_NOMEM;
7567 /* check to see if the printer already exists */
7569 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7570 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7571 printer->info_2->sharename));
7572 free_a_printer(&printer, 2);
7573 return WERR_PRINTER_ALREADY_EXISTS;
7576 /* FIXME!!! smbd should check to see if the driver is installed before
7577 trying to add a printer like this --jerry */
7579 if (*lp_addprinter_cmd() ) {
7580 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7581 free_a_printer(&printer,2);
7582 return WERR_ACCESS_DENIED;
7584 } else {
7585 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7586 "smb.conf parameter \"addprinter command\" is defined. This"
7587 "parameter must exist for this call to succeed\n",
7588 printer->info_2->sharename ));
7591 /* use our primary netbios name since get_a_printer() will convert
7592 it to what the client expects on a case by case basis */
7594 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7595 printer->info_2->sharename);
7598 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7599 free_a_printer(&printer,2);
7600 return WERR_ACCESS_DENIED;
7603 /* you must be a printer admin to add a new printer */
7604 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7605 free_a_printer(&printer,2);
7606 return WERR_ACCESS_DENIED;
7610 * Do sanity check on the requested changes for Samba.
7613 if (!check_printer_ok(printer->info_2, snum)) {
7614 free_a_printer(&printer,2);
7615 return WERR_INVALID_PARAM;
7619 * When a printer is created, the drivername bound to the printer is used
7620 * to lookup previously saved driver initialization info, which is then
7621 * bound to the new printer, simulating what happens in the Windows arch.
7624 if (!devmode)
7626 set_driver_init(printer, 2);
7628 else
7630 /* A valid devmode was included, convert and link it
7632 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7634 if (!convert_devicemode(printer->info_2->printername, devmode,
7635 &printer->info_2->devmode))
7636 return WERR_NOMEM;
7639 /* write the ASCII on disk */
7640 err = mod_a_printer(printer, 2);
7641 if (!W_ERROR_IS_OK(err)) {
7642 free_a_printer(&printer,2);
7643 return err;
7646 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7647 /* Handle open failed - remove addition. */
7648 del_a_printer(printer->info_2->sharename);
7649 free_a_printer(&printer,2);
7650 return WERR_ACCESS_DENIED;
7653 update_c_setprinter(False);
7654 free_a_printer(&printer,2);
7656 return WERR_OK;
7659 /****************************************************************************
7660 ****************************************************************************/
7662 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7664 UNISTR2 *uni_srv_name = q_u->server_name;
7665 uint32 level = q_u->level;
7666 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7667 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7668 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7669 uint32 user_switch = q_u->user_switch;
7670 SPOOL_USER_CTR *user = &q_u->user_ctr;
7671 POLICY_HND *handle = &r_u->handle;
7673 switch (level) {
7674 case 1:
7675 /* we don't handle yet */
7676 /* but I know what to do ... */
7677 return WERR_UNKNOWN_LEVEL;
7678 case 2:
7679 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7680 devmode, sdb,
7681 user_switch, user, handle);
7682 default:
7683 return WERR_UNKNOWN_LEVEL;
7687 /****************************************************************************
7688 ****************************************************************************/
7690 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7692 uint32 level = q_u->level;
7693 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7694 WERROR err = WERR_OK;
7695 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7696 struct current_user user;
7697 fstring driver_name;
7698 uint32 version;
7700 ZERO_STRUCT(driver);
7702 get_current_user(&user, p);
7704 if (!convert_printer_driver_info(info, &driver, level)) {
7705 err = WERR_NOMEM;
7706 goto done;
7709 DEBUG(5,("Cleaning driver's information\n"));
7710 err = clean_up_driver_struct(driver, level, &user);
7711 if (!W_ERROR_IS_OK(err))
7712 goto done;
7714 DEBUG(5,("Moving driver to final destination\n"));
7715 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7716 goto done;
7719 if (add_a_printer_driver(driver, level)!=0) {
7720 err = WERR_ACCESS_DENIED;
7721 goto done;
7725 * I think this is where he DrvUpgradePrinter() hook would be
7726 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7727 * server. Right now, we just need to send ourselves a message
7728 * to update each printer bound to this driver. --jerry
7731 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7732 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7733 driver_name));
7737 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7738 * decide if the driver init data should be deleted. The rules are:
7739 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7740 * 2) delete init data only if there is no 2k/Xp driver
7741 * 3) always delete init data
7742 * The generalized rule is always use init data from the highest order driver.
7743 * It is necessary to follow the driver install by an initialization step to
7744 * finish off this process.
7746 if (level == 3)
7747 version = driver.info_3->cversion;
7748 else if (level == 6)
7749 version = driver.info_6->version;
7750 else
7751 version = -1;
7752 switch (version) {
7754 * 9x printer driver - never delete init data
7756 case 0:
7757 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7758 driver_name));
7759 break;
7762 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7763 * there is no 2k/Xp driver init data for this driver name.
7765 case 2:
7767 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7769 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7771 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7773 if (!del_driver_init(driver_name))
7774 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7775 } else {
7777 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7779 free_a_printer_driver(driver1,3);
7780 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7781 driver_name));
7784 break;
7787 * 2k or Xp printer driver - always delete init data
7789 case 3:
7790 if (!del_driver_init(driver_name))
7791 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7792 break;
7794 default:
7795 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7796 break;
7800 done:
7801 free_a_printer_driver(driver, level);
7802 return err;
7805 /********************************************************************
7806 * spoolss_addprinterdriverex
7807 ********************************************************************/
7809 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7811 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7812 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7815 * we only support the semantics of AddPrinterDriver()
7816 * i.e. only copy files that are newer than existing ones
7819 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7820 return WERR_ACCESS_DENIED;
7822 ZERO_STRUCT(q_u_local);
7823 ZERO_STRUCT(r_u_local);
7825 /* just pass the information off to _spoolss_addprinterdriver() */
7826 q_u_local.server_name_ptr = q_u->server_name_ptr;
7827 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7828 q_u_local.level = q_u->level;
7829 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7831 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7834 /****************************************************************************
7835 ****************************************************************************/
7837 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7839 init_unistr(&info->name, name);
7842 /****************************************************************************
7843 ****************************************************************************/
7845 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7847 pstring path;
7848 pstring long_archi;
7849 fstring servername;
7850 char *pservername;
7851 const char *short_archi;
7852 DRIVER_DIRECTORY_1 *info=NULL;
7853 WERROR result = WERR_OK;
7855 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7856 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7858 /* check for beginning double '\'s and that the server
7859 long enough */
7861 pservername = servername;
7862 if ( *pservername == '\\' && strlen(servername)>2 ) {
7863 pservername += 2;
7866 if ( !is_myname_or_ipaddr( pservername ) )
7867 return WERR_INVALID_PARAM;
7869 if (!(short_archi = get_short_archi(long_archi)))
7870 return WERR_INVALID_ENVIRONMENT;
7872 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7873 return WERR_NOMEM;
7875 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7877 DEBUG(4,("printer driver directory: [%s]\n", path));
7879 fill_driverdir_1(info, path);
7881 *needed += spoolss_size_driverdir_info_1(info);
7883 if (*needed > offered) {
7884 result = WERR_INSUFFICIENT_BUFFER;
7885 goto out;
7888 if (!rpcbuf_alloc_size(buffer, *needed)) {
7889 result = WERR_NOMEM;
7890 goto out;
7893 smb_io_driverdir_1("", buffer, info, 0);
7895 out:
7896 SAFE_FREE(info);
7898 return result;
7901 /****************************************************************************
7902 ****************************************************************************/
7904 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7906 UNISTR2 *name = &q_u->name;
7907 UNISTR2 *uni_environment = &q_u->environment;
7908 uint32 level = q_u->level;
7909 RPC_BUFFER *buffer = NULL;
7910 uint32 offered = q_u->offered;
7911 uint32 *needed = &r_u->needed;
7913 /* that's an [in out] buffer */
7915 if (!q_u->buffer && (offered!=0)) {
7916 return WERR_INVALID_PARAM;
7919 rpcbuf_move(q_u->buffer, &r_u->buffer);
7920 buffer = r_u->buffer;
7922 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7924 *needed=0;
7926 switch(level) {
7927 case 1:
7928 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7929 default:
7930 return WERR_UNKNOWN_LEVEL;
7934 /****************************************************************************
7935 ****************************************************************************/
7937 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7939 POLICY_HND *handle = &q_u->handle;
7940 uint32 idx = q_u->index;
7941 uint32 in_value_len = q_u->valuesize;
7942 uint32 in_data_len = q_u->datasize;
7943 uint32 *out_max_value_len = &r_u->valuesize;
7944 uint16 **out_value = &r_u->value;
7945 uint32 *out_value_len = &r_u->realvaluesize;
7946 uint32 *out_type = &r_u->type;
7947 uint32 *out_max_data_len = &r_u->datasize;
7948 uint8 **data_out = &r_u->data;
7949 uint32 *out_data_len = &r_u->realdatasize;
7951 NT_PRINTER_INFO_LEVEL *printer = NULL;
7953 uint32 biggest_valuesize;
7954 uint32 biggest_datasize;
7955 uint32 data_len;
7956 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7957 int snum;
7958 WERROR result;
7959 REGISTRY_VALUE *val = NULL;
7960 NT_PRINTER_DATA *p_data;
7961 int i, key_index, num_values;
7962 int name_length;
7964 *out_type = 0;
7966 *out_max_data_len = 0;
7967 *data_out = NULL;
7968 *out_data_len = 0;
7970 DEBUG(5,("spoolss_enumprinterdata\n"));
7972 if (!Printer) {
7973 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7974 return WERR_BADFID;
7977 if (!get_printer_snum(p,handle, &snum))
7978 return WERR_BADFID;
7980 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7981 if (!W_ERROR_IS_OK(result))
7982 return result;
7984 p_data = printer->info_2->data;
7985 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7987 result = WERR_OK;
7990 * The NT machine wants to know the biggest size of value and data
7992 * cf: MSDN EnumPrinterData remark section
7995 if ( !in_value_len && !in_data_len && (key_index != -1) )
7997 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7999 biggest_valuesize = 0;
8000 biggest_datasize = 0;
8002 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8004 for ( i=0; i<num_values; i++ )
8006 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8008 name_length = strlen(val->valuename);
8009 if ( strlen(val->valuename) > biggest_valuesize )
8010 biggest_valuesize = name_length;
8012 if ( val->size > biggest_datasize )
8013 biggest_datasize = val->size;
8015 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8016 biggest_datasize));
8019 /* the value is an UNICODE string but real_value_size is the length
8020 in bytes including the trailing 0 */
8022 *out_value_len = 2 * (1+biggest_valuesize);
8023 *out_data_len = biggest_datasize;
8025 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8027 goto done;
8031 * the value len is wrong in NT sp3
8032 * that's the number of bytes not the number of unicode chars
8035 if ( key_index != -1 )
8036 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8038 if ( !val )
8041 /* out_value should default to "" or else NT4 has
8042 problems unmarshalling the response */
8044 *out_max_value_len=(in_value_len/sizeof(uint16));
8046 if (in_value_len) {
8047 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8049 result = WERR_NOMEM;
8050 goto done;
8052 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8053 } else {
8054 *out_value=NULL;
8055 *out_value_len = 0;
8058 /* the data is counted in bytes */
8060 *out_max_data_len = in_data_len;
8061 *out_data_len = in_data_len;
8063 /* only allocate when given a non-zero data_len */
8065 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8067 result = WERR_NOMEM;
8068 goto done;
8071 result = WERR_NO_MORE_ITEMS;
8073 else
8076 * the value is:
8077 * - counted in bytes in the request
8078 * - counted in UNICODE chars in the max reply
8079 * - counted in bytes in the real size
8081 * take a pause *before* coding not *during* coding
8084 /* name */
8085 *out_max_value_len=(in_value_len/sizeof(uint16));
8086 if (in_value_len) {
8087 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8089 result = WERR_NOMEM;
8090 goto done;
8093 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8094 } else {
8095 *out_value = NULL;
8096 *out_value_len = 0;
8099 /* type */
8101 *out_type = regval_type( val );
8103 /* data - counted in bytes */
8105 *out_max_data_len = in_data_len;
8106 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8108 result = WERR_NOMEM;
8109 goto done;
8111 data_len = regval_size(val);
8112 if ( *data_out && data_len )
8113 memcpy( *data_out, regval_data_p(val), data_len );
8114 *out_data_len = data_len;
8117 done:
8118 free_a_printer(&printer, 2);
8119 return result;
8122 /****************************************************************************
8123 ****************************************************************************/
8125 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8127 POLICY_HND *handle = &q_u->handle;
8128 UNISTR2 *value = &q_u->value;
8129 uint32 type = q_u->type;
8130 uint8 *data = q_u->data;
8131 uint32 real_len = q_u->real_len;
8133 NT_PRINTER_INFO_LEVEL *printer = NULL;
8134 int snum=0;
8135 WERROR status = WERR_OK;
8136 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8137 fstring valuename;
8139 DEBUG(5,("spoolss_setprinterdata\n"));
8141 if (!Printer) {
8142 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8143 return WERR_BADFID;
8146 if ( Printer->printer_type == SPLHND_SERVER ) {
8147 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8148 return WERR_INVALID_PARAM;
8151 if (!get_printer_snum(p,handle, &snum))
8152 return WERR_BADFID;
8155 * Access check : NT returns "access denied" if you make a
8156 * SetPrinterData call without the necessary privildge.
8157 * we were originally returning OK if nothing changed
8158 * which made Win2k issue **a lot** of SetPrinterData
8159 * when connecting to a printer --jerry
8162 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8164 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8165 status = WERR_ACCESS_DENIED;
8166 goto done;
8169 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8170 if (!W_ERROR_IS_OK(status))
8171 return status;
8173 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8176 * When client side code sets a magic printer data key, detect it and save
8177 * the current printer data and the magic key's data (its the DEVMODE) for
8178 * future printer/driver initializations.
8180 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8182 /* Set devmode and printer initialization info */
8183 status = save_driver_init( printer, 2, data, real_len );
8185 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8187 else
8189 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8190 type, data, real_len );
8191 if ( W_ERROR_IS_OK(status) )
8192 status = mod_a_printer(printer, 2);
8195 done:
8196 free_a_printer(&printer, 2);
8198 return status;
8201 /****************************************************************************
8202 ****************************************************************************/
8204 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8206 POLICY_HND *handle = &q_u->handle;
8207 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8208 int snum;
8210 DEBUG(5,("_spoolss_resetprinter\n"));
8213 * All we do is to check to see if the handle and queue is valid.
8214 * This call really doesn't mean anything to us because we only
8215 * support RAW printing. --jerry
8218 if (!Printer) {
8219 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8220 return WERR_BADFID;
8223 if (!get_printer_snum(p,handle, &snum))
8224 return WERR_BADFID;
8227 /* blindly return success */
8228 return WERR_OK;
8232 /****************************************************************************
8233 ****************************************************************************/
8235 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8237 POLICY_HND *handle = &q_u->handle;
8238 UNISTR2 *value = &q_u->valuename;
8240 NT_PRINTER_INFO_LEVEL *printer = NULL;
8241 int snum=0;
8242 WERROR status = WERR_OK;
8243 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8244 pstring valuename;
8246 DEBUG(5,("spoolss_deleteprinterdata\n"));
8248 if (!Printer) {
8249 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8250 return WERR_BADFID;
8253 if (!get_printer_snum(p, handle, &snum))
8254 return WERR_BADFID;
8256 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8257 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8258 return WERR_ACCESS_DENIED;
8261 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8262 if (!W_ERROR_IS_OK(status))
8263 return status;
8265 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8267 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8269 if ( W_ERROR_IS_OK(status) )
8270 mod_a_printer( printer, 2 );
8272 free_a_printer(&printer, 2);
8274 return status;
8277 /****************************************************************************
8278 ****************************************************************************/
8280 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8282 POLICY_HND *handle = &q_u->handle;
8283 FORM *form = &q_u->form;
8284 nt_forms_struct tmpForm;
8285 int snum;
8286 WERROR status = WERR_OK;
8287 NT_PRINTER_INFO_LEVEL *printer = NULL;
8289 int count=0;
8290 nt_forms_struct *list=NULL;
8291 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8293 DEBUG(5,("spoolss_addform\n"));
8295 if (!Printer) {
8296 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8297 return WERR_BADFID;
8301 /* forms can be added on printer of on the print server handle */
8303 if ( Printer->printer_type == SPLHND_PRINTER )
8305 if (!get_printer_snum(p,handle, &snum))
8306 return WERR_BADFID;
8308 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8309 if (!W_ERROR_IS_OK(status))
8310 goto done;
8313 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8314 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8315 status = WERR_ACCESS_DENIED;
8316 goto done;
8319 /* can't add if builtin */
8321 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8322 status = WERR_ALREADY_EXISTS;
8323 goto done;
8326 count = get_ntforms(&list);
8328 if(!add_a_form(&list, form, &count)) {
8329 status = WERR_NOMEM;
8330 goto done;
8333 write_ntforms(&list, count);
8336 * ChangeID must always be set if this is a printer
8339 if ( Printer->printer_type == SPLHND_PRINTER )
8340 status = mod_a_printer(printer, 2);
8342 done:
8343 if ( printer )
8344 free_a_printer(&printer, 2);
8345 SAFE_FREE(list);
8347 return status;
8350 /****************************************************************************
8351 ****************************************************************************/
8353 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8355 POLICY_HND *handle = &q_u->handle;
8356 UNISTR2 *form_name = &q_u->name;
8357 nt_forms_struct tmpForm;
8358 int count=0;
8359 nt_forms_struct *list=NULL;
8360 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8361 int snum;
8362 WERROR status = WERR_OK;
8363 NT_PRINTER_INFO_LEVEL *printer = NULL;
8365 DEBUG(5,("spoolss_deleteform\n"));
8367 if (!Printer) {
8368 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8369 return WERR_BADFID;
8372 /* forms can be deleted on printer of on the print server handle */
8374 if ( Printer->printer_type == SPLHND_PRINTER )
8376 if (!get_printer_snum(p,handle, &snum))
8377 return WERR_BADFID;
8379 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8380 if (!W_ERROR_IS_OK(status))
8381 goto done;
8384 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8385 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8386 status = WERR_ACCESS_DENIED;
8387 goto done;
8390 /* can't delete if builtin */
8392 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8393 status = WERR_INVALID_PARAM;
8394 goto done;
8397 count = get_ntforms(&list);
8399 if ( !delete_a_form(&list, form_name, &count, &status ))
8400 goto done;
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);
8409 done:
8410 if ( printer )
8411 free_a_printer(&printer, 2);
8412 SAFE_FREE(list);
8414 return status;
8417 /****************************************************************************
8418 ****************************************************************************/
8420 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8422 POLICY_HND *handle = &q_u->handle;
8423 FORM *form = &q_u->form;
8424 nt_forms_struct tmpForm;
8425 int snum;
8426 WERROR status = WERR_OK;
8427 NT_PRINTER_INFO_LEVEL *printer = NULL;
8429 int count=0;
8430 nt_forms_struct *list=NULL;
8431 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8433 DEBUG(5,("spoolss_setform\n"));
8435 if (!Printer) {
8436 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8437 return WERR_BADFID;
8440 /* forms can be modified on printer of on the print server handle */
8442 if ( Printer->printer_type == SPLHND_PRINTER )
8444 if (!get_printer_snum(p,handle, &snum))
8445 return WERR_BADFID;
8447 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8448 if (!W_ERROR_IS_OK(status))
8449 goto done;
8452 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8453 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8454 status = WERR_ACCESS_DENIED;
8455 goto done;
8458 /* can't set if builtin */
8459 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8460 status = WERR_INVALID_PARAM;
8461 goto done;
8464 count = get_ntforms(&list);
8465 update_a_form(&list, form, count);
8466 write_ntforms(&list, count);
8469 * ChangeID must always be set if this is a printer
8472 if ( Printer->printer_type == SPLHND_PRINTER )
8473 status = mod_a_printer(printer, 2);
8476 done:
8477 if ( printer )
8478 free_a_printer(&printer, 2);
8479 SAFE_FREE(list);
8481 return status;
8484 /****************************************************************************
8485 enumprintprocessors level 1.
8486 ****************************************************************************/
8488 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8490 PRINTPROCESSOR_1 *info_1=NULL;
8491 WERROR result = WERR_OK;
8493 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8494 return WERR_NOMEM;
8496 (*returned) = 0x1;
8498 init_unistr(&info_1->name, "winprint");
8500 *needed += spoolss_size_printprocessor_info_1(info_1);
8502 if (*needed > offered) {
8503 result = WERR_INSUFFICIENT_BUFFER;
8504 goto out;
8507 if (!rpcbuf_alloc_size(buffer, *needed)) {
8508 result = WERR_NOMEM;
8509 goto out;
8512 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8514 out:
8515 SAFE_FREE(info_1);
8517 if ( !W_ERROR_IS_OK(result) )
8518 *returned = 0;
8520 return result;
8523 /****************************************************************************
8524 ****************************************************************************/
8526 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8528 uint32 level = q_u->level;
8529 RPC_BUFFER *buffer = NULL;
8530 uint32 offered = q_u->offered;
8531 uint32 *needed = &r_u->needed;
8532 uint32 *returned = &r_u->returned;
8534 /* that's an [in out] buffer */
8536 if (!q_u->buffer && (offered!=0)) {
8537 return WERR_INVALID_PARAM;
8540 rpcbuf_move(q_u->buffer, &r_u->buffer);
8541 buffer = r_u->buffer;
8543 DEBUG(5,("spoolss_enumprintprocessors\n"));
8546 * Enumerate the print processors ...
8548 * Just reply with "winprint", to keep NT happy
8549 * and I can use my nice printer checker.
8552 *returned=0;
8553 *needed=0;
8555 switch (level) {
8556 case 1:
8557 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8558 default:
8559 return WERR_UNKNOWN_LEVEL;
8563 /****************************************************************************
8564 enumprintprocdatatypes level 1.
8565 ****************************************************************************/
8567 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8569 PRINTPROCDATATYPE_1 *info_1=NULL;
8570 WERROR result = WERR_OK;
8572 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8573 return WERR_NOMEM;
8575 (*returned) = 0x1;
8577 init_unistr(&info_1->name, "RAW");
8579 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8581 if (*needed > offered) {
8582 result = WERR_INSUFFICIENT_BUFFER;
8583 goto out;
8586 if (!rpcbuf_alloc_size(buffer, *needed)) {
8587 result = WERR_NOMEM;
8588 goto out;
8591 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8593 out:
8594 SAFE_FREE(info_1);
8596 if ( !W_ERROR_IS_OK(result) )
8597 *returned = 0;
8599 return result;
8602 /****************************************************************************
8603 ****************************************************************************/
8605 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8607 uint32 level = q_u->level;
8608 RPC_BUFFER *buffer = NULL;
8609 uint32 offered = q_u->offered;
8610 uint32 *needed = &r_u->needed;
8611 uint32 *returned = &r_u->returned;
8613 /* that's an [in out] buffer */
8615 if (!q_u->buffer && (offered!=0)) {
8616 return WERR_INVALID_PARAM;
8619 rpcbuf_move(q_u->buffer, &r_u->buffer);
8620 buffer = r_u->buffer;
8622 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8624 *returned=0;
8625 *needed=0;
8627 switch (level) {
8628 case 1:
8629 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8630 default:
8631 return WERR_UNKNOWN_LEVEL;
8635 /****************************************************************************
8636 enumprintmonitors level 1.
8637 ****************************************************************************/
8639 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8641 PRINTMONITOR_1 *info_1;
8642 WERROR result = WERR_OK;
8643 int i;
8645 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8646 return WERR_NOMEM;
8648 *returned = 2;
8650 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8651 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8653 for ( i=0; i<*returned; i++ ) {
8654 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8657 if (*needed > offered) {
8658 result = WERR_INSUFFICIENT_BUFFER;
8659 goto out;
8662 if (!rpcbuf_alloc_size(buffer, *needed)) {
8663 result = WERR_NOMEM;
8664 goto out;
8667 for ( i=0; i<*returned; i++ ) {
8668 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8671 out:
8672 SAFE_FREE(info_1);
8674 if ( !W_ERROR_IS_OK(result) )
8675 *returned = 0;
8677 return result;
8680 /****************************************************************************
8681 enumprintmonitors level 2.
8682 ****************************************************************************/
8684 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8686 PRINTMONITOR_2 *info_2;
8687 WERROR result = WERR_OK;
8688 int i;
8690 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8691 return WERR_NOMEM;
8693 *returned = 2;
8695 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8696 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8697 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8699 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8700 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8701 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8703 for ( i=0; i<*returned; i++ ) {
8704 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8707 if (*needed > offered) {
8708 result = WERR_INSUFFICIENT_BUFFER;
8709 goto out;
8712 if (!rpcbuf_alloc_size(buffer, *needed)) {
8713 result = WERR_NOMEM;
8714 goto out;
8717 for ( i=0; i<*returned; i++ ) {
8718 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8721 out:
8722 SAFE_FREE(info_2);
8724 if ( !W_ERROR_IS_OK(result) )
8725 *returned = 0;
8727 return result;
8730 /****************************************************************************
8731 ****************************************************************************/
8733 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8735 uint32 level = q_u->level;
8736 RPC_BUFFER *buffer = NULL;
8737 uint32 offered = q_u->offered;
8738 uint32 *needed = &r_u->needed;
8739 uint32 *returned = &r_u->returned;
8741 /* that's an [in out] buffer */
8743 if (!q_u->buffer && (offered!=0)) {
8744 return WERR_INVALID_PARAM;
8747 rpcbuf_move(q_u->buffer, &r_u->buffer);
8748 buffer = r_u->buffer;
8750 DEBUG(5,("spoolss_enumprintmonitors\n"));
8753 * Enumerate the print monitors ...
8755 * Just reply with "Local Port", to keep NT happy
8756 * and I can use my nice printer checker.
8759 *returned=0;
8760 *needed=0;
8762 switch (level) {
8763 case 1:
8764 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8765 case 2:
8766 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8767 default:
8768 return WERR_UNKNOWN_LEVEL;
8772 /****************************************************************************
8773 ****************************************************************************/
8775 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8776 NT_PRINTER_INFO_LEVEL *ntprinter,
8777 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8778 uint32 *needed)
8780 int i=0;
8781 BOOL found=False;
8782 JOB_INFO_1 *info_1=NULL;
8783 WERROR result = WERR_OK;
8785 info_1=SMB_MALLOC_P(JOB_INFO_1);
8787 if (info_1 == NULL) {
8788 return WERR_NOMEM;
8791 for (i=0; i<count && found==False; i++) {
8792 if ((*queue)[i].job==(int)jobid)
8793 found=True;
8796 if (found==False) {
8797 SAFE_FREE(info_1);
8798 /* NT treats not found as bad param... yet another bad choice */
8799 return WERR_INVALID_PARAM;
8802 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8804 *needed += spoolss_size_job_info_1(info_1);
8806 if (*needed > offered) {
8807 result = WERR_INSUFFICIENT_BUFFER;
8808 goto out;
8811 if (!rpcbuf_alloc_size(buffer, *needed)) {
8812 result = WERR_NOMEM;
8813 goto out;
8816 smb_io_job_info_1("", buffer, info_1, 0);
8818 out:
8819 SAFE_FREE(info_1);
8821 return result;
8824 /****************************************************************************
8825 ****************************************************************************/
8827 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8828 NT_PRINTER_INFO_LEVEL *ntprinter,
8829 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8830 uint32 *needed)
8832 int i = 0;
8833 BOOL found = False;
8834 JOB_INFO_2 *info_2;
8835 WERROR result;
8836 DEVICEMODE *devmode = NULL;
8837 NT_DEVICEMODE *nt_devmode = NULL;
8839 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8840 return WERR_NOMEM;
8842 ZERO_STRUCTP(info_2);
8844 for ( i=0; i<count && found==False; i++ )
8846 if ((*queue)[i].job == (int)jobid)
8847 found = True;
8850 if ( !found ) {
8851 /* NT treats not found as bad param... yet another bad
8852 choice */
8853 result = WERR_INVALID_PARAM;
8854 goto done;
8858 * if the print job does not have a DEVMODE associated with it,
8859 * just use the one for the printer. A NULL devicemode is not
8860 * a failure condition
8863 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8864 devmode = construct_dev_mode(lp_const_servicename(snum));
8865 else {
8866 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8867 ZERO_STRUCTP( devmode );
8868 convert_nt_devicemode( devmode, nt_devmode );
8872 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8874 *needed += spoolss_size_job_info_2(info_2);
8876 if (*needed > offered) {
8877 result = WERR_INSUFFICIENT_BUFFER;
8878 goto done;
8881 if (!rpcbuf_alloc_size(buffer, *needed)) {
8882 result = WERR_NOMEM;
8883 goto done;
8886 smb_io_job_info_2("", buffer, info_2, 0);
8888 result = WERR_OK;
8890 done:
8891 /* Cleanup allocated memory */
8893 free_job_info_2(info_2); /* Also frees devmode */
8894 SAFE_FREE(info_2);
8896 return result;
8899 /****************************************************************************
8900 ****************************************************************************/
8902 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8904 POLICY_HND *handle = &q_u->handle;
8905 uint32 jobid = q_u->jobid;
8906 uint32 level = q_u->level;
8907 RPC_BUFFER *buffer = NULL;
8908 uint32 offered = q_u->offered;
8909 uint32 *needed = &r_u->needed;
8910 WERROR wstatus = WERR_OK;
8911 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8912 int snum;
8913 int count;
8914 print_queue_struct *queue = NULL;
8915 print_status_struct prt_status;
8917 /* that's an [in out] buffer */
8919 if (!q_u->buffer && (offered!=0)) {
8920 return WERR_INVALID_PARAM;
8923 rpcbuf_move(q_u->buffer, &r_u->buffer);
8924 buffer = r_u->buffer;
8926 DEBUG(5,("spoolss_getjob\n"));
8928 *needed = 0;
8930 if (!get_printer_snum(p, handle, &snum))
8931 return WERR_BADFID;
8933 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8934 if ( !W_ERROR_IS_OK(wstatus) )
8935 return wstatus;
8937 count = print_queue_status(snum, &queue, &prt_status);
8939 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8940 count, prt_status.status, prt_status.message));
8942 switch ( level ) {
8943 case 1:
8944 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8945 buffer, offered, needed);
8946 break;
8947 case 2:
8948 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8949 buffer, offered, needed);
8950 break;
8951 default:
8952 wstatus = WERR_UNKNOWN_LEVEL;
8953 break;
8956 SAFE_FREE(queue);
8957 free_a_printer( &ntprinter, 2 );
8959 return wstatus;
8962 /********************************************************************
8963 spoolss_getprinterdataex
8965 From MSDN documentation of GetPrinterDataEx: pass request
8966 to GetPrinterData if key is "PrinterDriverData".
8967 ********************************************************************/
8969 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8971 POLICY_HND *handle = &q_u->handle;
8972 uint32 in_size = q_u->size;
8973 uint32 *type = &r_u->type;
8974 uint32 *out_size = &r_u->size;
8975 uint8 **data = &r_u->data;
8976 uint32 *needed = &r_u->needed;
8977 fstring keyname, valuename;
8979 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8981 NT_PRINTER_INFO_LEVEL *printer = NULL;
8982 int snum = 0;
8983 WERROR status = WERR_OK;
8985 DEBUG(4,("_spoolss_getprinterdataex\n"));
8987 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8988 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8990 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8991 keyname, valuename));
8993 /* in case of problem, return some default values */
8995 *needed = 0;
8996 *type = 0;
8997 *out_size = in_size;
8999 if (!Printer) {
9000 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9001 status = WERR_BADFID;
9002 goto done;
9005 /* Is the handle to a printer or to the server? */
9007 if (Printer->printer_type == SPLHND_SERVER) {
9008 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9009 status = WERR_INVALID_PARAM;
9010 goto done;
9013 if ( !get_printer_snum(p,handle, &snum) )
9014 return WERR_BADFID;
9016 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9017 if ( !W_ERROR_IS_OK(status) )
9018 goto done;
9020 /* check to see if the keyname is valid */
9021 if ( !strlen(keyname) ) {
9022 status = WERR_INVALID_PARAM;
9023 goto done;
9026 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9027 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9028 free_a_printer( &printer, 2 );
9029 status = WERR_BADFILE;
9030 goto done;
9033 /* When given a new keyname, we should just create it */
9035 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9037 if (*needed > *out_size)
9038 status = WERR_MORE_DATA;
9040 done:
9041 if ( !W_ERROR_IS_OK(status) )
9043 DEBUG(5, ("error: allocating %d\n", *out_size));
9045 /* reply this param doesn't exist */
9047 if ( *out_size )
9049 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9050 status = WERR_NOMEM;
9051 goto done;
9053 } else {
9054 *data = NULL;
9058 if ( printer )
9059 free_a_printer( &printer, 2 );
9061 return status;
9064 /********************************************************************
9065 * spoolss_setprinterdataex
9066 ********************************************************************/
9068 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9070 POLICY_HND *handle = &q_u->handle;
9071 uint32 type = q_u->type;
9072 uint8 *data = q_u->data;
9073 uint32 real_len = q_u->real_len;
9075 NT_PRINTER_INFO_LEVEL *printer = NULL;
9076 int snum = 0;
9077 WERROR status = WERR_OK;
9078 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9079 fstring valuename;
9080 fstring keyname;
9081 char *oid_string;
9083 DEBUG(4,("_spoolss_setprinterdataex\n"));
9085 /* From MSDN documentation of SetPrinterDataEx: pass request to
9086 SetPrinterData if key is "PrinterDriverData" */
9088 if (!Printer) {
9089 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9090 return WERR_BADFID;
9093 if ( Printer->printer_type == SPLHND_SERVER ) {
9094 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9095 return WERR_INVALID_PARAM;
9098 if ( !get_printer_snum(p,handle, &snum) )
9099 return WERR_BADFID;
9102 * Access check : NT returns "access denied" if you make a
9103 * SetPrinterData call without the necessary privildge.
9104 * we were originally returning OK if nothing changed
9105 * which made Win2k issue **a lot** of SetPrinterData
9106 * when connecting to a printer --jerry
9109 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9111 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9112 return WERR_ACCESS_DENIED;
9115 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9116 if (!W_ERROR_IS_OK(status))
9117 return status;
9119 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9120 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9122 /* check for OID in valuename */
9124 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9126 *oid_string = '\0';
9127 oid_string++;
9130 /* save the registry data */
9132 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9134 if ( W_ERROR_IS_OK(status) )
9136 /* save the OID if one was specified */
9137 if ( oid_string ) {
9138 fstrcat( keyname, "\\" );
9139 fstrcat( keyname, SPOOL_OID_KEY );
9142 * I'm not checking the status here on purpose. Don't know
9143 * if this is right, but I'm returning the status from the
9144 * previous set_printer_dataex() call. I have no idea if
9145 * this is right. --jerry
9148 set_printer_dataex( printer, keyname, valuename,
9149 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9152 status = mod_a_printer(printer, 2);
9155 free_a_printer(&printer, 2);
9157 return status;
9161 /********************************************************************
9162 * spoolss_deleteprinterdataex
9163 ********************************************************************/
9165 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9167 POLICY_HND *handle = &q_u->handle;
9168 UNISTR2 *value = &q_u->valuename;
9169 UNISTR2 *key = &q_u->keyname;
9171 NT_PRINTER_INFO_LEVEL *printer = NULL;
9172 int snum=0;
9173 WERROR status = WERR_OK;
9174 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9175 pstring valuename, keyname;
9177 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9179 if (!Printer) {
9180 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9181 return WERR_BADFID;
9184 if (!get_printer_snum(p, handle, &snum))
9185 return WERR_BADFID;
9187 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9188 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9189 return WERR_ACCESS_DENIED;
9192 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9193 if (!W_ERROR_IS_OK(status))
9194 return status;
9196 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9197 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9199 status = delete_printer_dataex( printer, keyname, valuename );
9201 if ( W_ERROR_IS_OK(status) )
9202 mod_a_printer( printer, 2 );
9204 free_a_printer(&printer, 2);
9206 return status;
9209 /********************************************************************
9210 * spoolss_enumprinterkey
9211 ********************************************************************/
9214 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9216 fstring key;
9217 fstring *keynames = NULL;
9218 uint16 *enumkeys = NULL;
9219 int num_keys;
9220 int printerkey_len;
9221 POLICY_HND *handle = &q_u->handle;
9222 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9223 NT_PRINTER_DATA *data;
9224 NT_PRINTER_INFO_LEVEL *printer = NULL;
9225 int snum = 0;
9226 WERROR status = WERR_BADFILE;
9229 DEBUG(4,("_spoolss_enumprinterkey\n"));
9231 if (!Printer) {
9232 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9233 return WERR_BADFID;
9236 if ( !get_printer_snum(p,handle, &snum) )
9237 return WERR_BADFID;
9239 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9240 if (!W_ERROR_IS_OK(status))
9241 return status;
9243 /* get the list of subkey names */
9245 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9246 data = printer->info_2->data;
9248 num_keys = get_printer_subkeys( data, key, &keynames );
9250 if ( num_keys == -1 ) {
9251 status = WERR_BADFILE;
9252 goto done;
9255 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9257 r_u->needed = printerkey_len*2;
9259 if ( q_u->size < r_u->needed ) {
9260 status = WERR_MORE_DATA;
9261 goto done;
9264 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9265 status = WERR_NOMEM;
9266 goto done;
9269 status = WERR_OK;
9271 if ( q_u->size < r_u->needed )
9272 status = WERR_MORE_DATA;
9274 done:
9275 free_a_printer( &printer, 2 );
9276 SAFE_FREE( keynames );
9278 return status;
9281 /********************************************************************
9282 * spoolss_deleteprinterkey
9283 ********************************************************************/
9285 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9287 POLICY_HND *handle = &q_u->handle;
9288 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9289 fstring key;
9290 NT_PRINTER_INFO_LEVEL *printer = NULL;
9291 int snum=0;
9292 WERROR status;
9294 DEBUG(5,("spoolss_deleteprinterkey\n"));
9296 if (!Printer) {
9297 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9298 return WERR_BADFID;
9301 /* if keyname == NULL, return error */
9303 if ( !q_u->keyname.buffer )
9304 return WERR_INVALID_PARAM;
9306 if (!get_printer_snum(p, handle, &snum))
9307 return WERR_BADFID;
9309 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9310 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9311 return WERR_ACCESS_DENIED;
9314 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9315 if (!W_ERROR_IS_OK(status))
9316 return status;
9318 /* delete the key and all subneys */
9320 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9322 status = delete_all_printer_data( printer->info_2, key );
9324 if ( W_ERROR_IS_OK(status) )
9325 status = mod_a_printer(printer, 2);
9327 free_a_printer( &printer, 2 );
9329 return status;
9333 /********************************************************************
9334 * spoolss_enumprinterdataex
9335 ********************************************************************/
9337 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9339 POLICY_HND *handle = &q_u->handle;
9340 uint32 in_size = q_u->size;
9341 uint32 num_entries,
9342 needed;
9343 NT_PRINTER_INFO_LEVEL *printer = NULL;
9344 PRINTER_ENUM_VALUES *enum_values = NULL;
9345 NT_PRINTER_DATA *p_data;
9346 fstring key;
9347 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9348 int snum;
9349 WERROR result;
9350 int key_index;
9351 int i;
9352 REGISTRY_VALUE *val;
9353 char *value_name;
9354 uint32 data_len;
9357 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9359 if (!Printer) {
9360 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9361 return WERR_BADFID;
9365 * first check for a keyname of NULL or "". Win2k seems to send
9366 * this a lot and we should send back WERR_INVALID_PARAM
9367 * no need to spend time looking up the printer in this case.
9368 * --jerry
9371 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9372 if ( !strlen(key) ) {
9373 result = WERR_INVALID_PARAM;
9374 goto done;
9377 /* get the printer off of disk */
9379 if (!get_printer_snum(p,handle, &snum))
9380 return WERR_BADFID;
9382 ZERO_STRUCT(printer);
9383 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9384 if (!W_ERROR_IS_OK(result))
9385 return result;
9387 /* now look for a match on the key name */
9389 p_data = printer->info_2->data;
9391 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9392 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9394 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9395 result = WERR_INVALID_PARAM;
9396 goto done;
9399 result = WERR_OK;
9400 needed = 0;
9402 /* allocate the memory for the array of pointers -- if necessary */
9404 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9405 if ( num_entries )
9407 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9409 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9410 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9411 result = WERR_NOMEM;
9412 goto done;
9415 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9419 * loop through all params and build the array to pass
9420 * back to the client
9423 for ( i=0; i<num_entries; i++ )
9425 /* lookup the registry value */
9427 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9428 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9430 /* copy the data */
9432 value_name = regval_name( val );
9433 init_unistr( &enum_values[i].valuename, value_name );
9434 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9435 enum_values[i].type = regval_type( val );
9437 data_len = regval_size( val );
9438 if ( data_len ) {
9439 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9441 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9442 data_len ));
9443 result = WERR_NOMEM;
9444 goto done;
9447 enum_values[i].data_len = data_len;
9449 /* keep track of the size of the array in bytes */
9451 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9454 /* housekeeping information in the reply */
9456 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9457 * the hand marshalled container size is a multiple
9458 * of 4 bytes for RPC alignment.
9461 if (needed % 4) {
9462 needed += 4-(needed % 4);
9465 r_u->needed = needed;
9466 r_u->returned = num_entries;
9468 if (needed > in_size) {
9469 result = WERR_MORE_DATA;
9470 goto done;
9473 /* copy data into the reply */
9475 r_u->ctr.size = r_u->needed;
9477 r_u->ctr.size_of_array = r_u->returned;
9478 r_u->ctr.values = enum_values;
9482 done:
9483 if ( printer )
9484 free_a_printer(&printer, 2);
9486 return result;
9489 /****************************************************************************
9490 ****************************************************************************/
9492 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9494 init_unistr(&info->name, name);
9497 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9498 UNISTR2 *environment,
9499 RPC_BUFFER *buffer,
9500 uint32 offered,
9501 uint32 *needed)
9503 pstring path;
9504 pstring long_archi;
9505 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9506 WERROR result = WERR_OK;
9508 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9510 if (!get_short_archi(long_archi))
9511 return WERR_INVALID_ENVIRONMENT;
9513 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9514 return WERR_NOMEM;
9516 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9518 fill_printprocessordirectory_1(info, path);
9520 *needed += spoolss_size_printprocessordirectory_info_1(info);
9522 if (*needed > offered) {
9523 result = WERR_INSUFFICIENT_BUFFER;
9524 goto out;
9527 if (!rpcbuf_alloc_size(buffer, *needed)) {
9528 result = WERR_INSUFFICIENT_BUFFER;
9529 goto out;
9532 smb_io_printprocessordirectory_1("", buffer, info, 0);
9534 out:
9535 SAFE_FREE(info);
9537 return result;
9540 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9542 uint32 level = q_u->level;
9543 RPC_BUFFER *buffer = NULL;
9544 uint32 offered = q_u->offered;
9545 uint32 *needed = &r_u->needed;
9546 WERROR result;
9548 /* that's an [in out] buffer */
9550 if (!q_u->buffer && (offered!=0)) {
9551 return WERR_INVALID_PARAM;
9554 rpcbuf_move(q_u->buffer, &r_u->buffer);
9555 buffer = r_u->buffer;
9557 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9559 *needed=0;
9561 switch(level) {
9562 case 1:
9563 result = getprintprocessordirectory_level_1
9564 (&q_u->name, &q_u->environment, buffer, offered, needed);
9565 break;
9566 default:
9567 result = WERR_UNKNOWN_LEVEL;
9570 return result;
9573 /*******************************************************************
9574 Streams the monitor UI DLL name in UNICODE
9575 *******************************************************************/
9577 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9578 RPC_BUFFER *out, uint32 *needed )
9580 const char *dllname = "tcpmonui.dll";
9582 *needed = (strlen(dllname)+1) * 2;
9584 if ( rpcbuf_get_size(out) < *needed ) {
9585 return WERR_INSUFFICIENT_BUFFER;
9588 if ( !make_monitorui_buf( out, dllname ) ) {
9589 return WERR_NOMEM;
9592 return WERR_OK;
9595 /*******************************************************************
9596 Create a new TCP/IP port
9597 *******************************************************************/
9599 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9600 RPC_BUFFER *out, uint32 *needed )
9602 NT_PORT_DATA_1 port1;
9603 pstring device_uri;
9605 ZERO_STRUCT( port1 );
9607 /* convert to our internal port data structure */
9609 if ( !convert_port_data_1( &port1, in ) ) {
9610 return WERR_NOMEM;
9613 /* create the device URI and call the add_port_hook() */
9615 switch ( port1.protocol ) {
9616 case PORT_PROTOCOL_DIRECT:
9617 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9618 break;
9620 case PORT_PROTOCOL_LPR:
9621 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9622 break;
9624 default:
9625 return WERR_UNKNOWN_PORT;
9628 return add_port_hook( token, port1.name, device_uri );
9631 /*******************************************************************
9632 *******************************************************************/
9634 struct xcv_api_table xcvtcp_cmds[] = {
9635 { "MonitorUI", xcvtcp_monitorui },
9636 { "AddPort", xcvtcp_addport},
9637 { NULL, NULL }
9640 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9641 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9642 uint32 *needed )
9644 int i;
9646 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9648 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9649 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9650 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9653 return WERR_BADFUNC;
9656 /*******************************************************************
9657 *******************************************************************/
9658 #if 0 /* don't support management using the "Local Port" monitor */
9660 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9661 RPC_BUFFER *out, uint32 *needed )
9663 const char *dllname = "localui.dll";
9665 *needed = (strlen(dllname)+1) * 2;
9667 if ( rpcbuf_get_size(out) < *needed ) {
9668 return WERR_INSUFFICIENT_BUFFER;
9671 if ( !make_monitorui_buf( out, dllname )) {
9672 return WERR_NOMEM;
9675 return WERR_OK;
9678 /*******************************************************************
9679 *******************************************************************/
9681 struct xcv_api_table xcvlocal_cmds[] = {
9682 { "MonitorUI", xcvlocal_monitorui },
9683 { NULL, NULL }
9685 #else
9686 struct xcv_api_table xcvlocal_cmds[] = {
9687 { NULL, NULL }
9689 #endif
9693 /*******************************************************************
9694 *******************************************************************/
9696 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9697 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9698 uint32 *needed )
9700 int i;
9702 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9704 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9705 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9706 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9708 return WERR_BADFUNC;
9711 /*******************************************************************
9712 *******************************************************************/
9714 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9716 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9717 fstring command;
9719 if (!Printer) {
9720 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9721 return WERR_BADFID;
9724 /* Has to be a handle to the TCP/IP port monitor */
9726 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9727 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9728 return WERR_BADFID;
9731 /* requires administrative access to the server */
9733 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9734 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9735 return WERR_ACCESS_DENIED;
9738 /* Get the command name. There's numerous commands supported by the
9739 TCPMON interface. */
9741 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9742 q_u->dataname.uni_str_len*2, 0);
9744 /* Allocate the outgoing buffer */
9746 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9748 switch ( Printer->printer_type ) {
9749 case SPLHND_PORTMON_TCP:
9750 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9751 &q_u->indata, &r_u->outdata, &r_u->needed );
9752 case SPLHND_PORTMON_LOCAL:
9753 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9754 &q_u->indata, &r_u->outdata, &r_u->needed );
9757 return WERR_INVALID_PRINT_MONITOR;